2012-04-04 19 views
14

Tengo una estructura de objeto de modelo de vista padre-hijo configurada y necesito actualizar un elemento observable en el elemento primario del elemento secundario. básicamente me he llegado con dos patrones para hacerlo:Patrón para modificar el knockout observable en el modelo principal de vista desde el niño

1] pasa una referencia de la propiedad de los padres para el niño y actualizar la propiedad desde el interior del niño:

var ParentViewModel = function(){ 
    var self = this; 
    this.selectedItem = ko.observable(); 
    this.child = ko.observable(new ChildViewModel(self.selectedItem)); 
} 

var ChildViewModel = function(parentSelectedItem){ 
    var self = this; 
    this.id = ko.observable(); 
    this.parentSelectedItem = parentSelectedItem; 
    this.select = function(){ 
     self.parentSelectedItem(self); 
    } 
} 

2] Crear el niño de seleccione el método en el padre y haga referencia al padre observable localmente:

var ParentViewModel = function(){ 
    var self = this; 
    this.selectedItem = ko.observable(); 

    var child = new ChildViewModel(); 
    child.select = function(){ 
     self.selectedItem(child); 
    } 
    this.child = ko.observable(child); 
} 

var ChildViewModel = function(){ 
    this.id = ko.observable(); 
} 

Ninguno de estos patrones me envía a los talones. El primero introduce toda la referencia de propiedad en modelos de vista de niños, el segundo define la función de un niño fuera del alcance del niño.

¿Alguien tiene alguna sugerencia de patrón sobre cómo se puede lograr esta operación en JavaScript de una manera limpia y comprobable? ¿O estoy más o menos atrapado con solo estas dos opciones?

Respuesta

19

El patrón más común para hacer esto en Knockout es poner un método "selectChild" en su padre que toma a un niño. En la mayoría de los casos, el niño real no necesita saber que está siendo seleccionado.

Luego en su encuadernación, puede enlazar a $root.selectChild o $parent.selectChild. El primer argumento pasado a un controlador vinculado al enlace de clic/evento es la información real (en KO 2.0), por lo que su método puede vivir en el padre y recibir al hijo como primer argumento.

var Item = function(id, name) { 
    this.id = id; 
    this.name = ko.observable(name);  
}; 

var ViewModel = function() { 
    var self = this; 
    this.items = ko.observableArray([ 
     new Item(1, "one"), 
     new Item(2, "two"), 
     new Item(3, "three") 
    ]); 

    this.selectedItem = ko.observable(); 

    this.selectItem = function(item) { 
     self.selectedItem(item); 
    };  
}; 

En este caso, su unión se vería así:

<ul data-bind="foreach: items"> 
    <li> 
     <a href="#" data-bind="text: name, click: $root.selectItem"></a> 
    </li> 
</ul> 

Aquí está en jsFiddle: http://jsfiddle.net/rniemeyer/anRsA/

Incluso se puede simplificar aún más. Los observables son funciones y el primer argumento que les pasa se usa para establecer su valor, por lo que incluso puede elegir no incluir el método selectItem y simplemente enlazar directamente contra $root.selectedItem (se vería así: http://jsfiddle.net/rniemeyer/anRsA/1/). Usualmente utilizo un método separado para ser explícito, para darle un nombre (acción) apropiado, y en caso de que haya un procesamiento adicional que deba hacerse antes o después de configurar el elemento.

Antes de KO 2.0 (donde $root y $parent se introdujeron junto con el cambio para pasar los datos como el primer argumento a click y event manipuladores), solía utilizar el primer método que usted ha sugerido un poco. Una cosa que puede hacer allí es no crear la propiedad hija (this.parentSelectedItem) y simplemente hacer referencia parentSelectedItem (que se pasó como argumento) directamente en el método select, ya que estará disponible en la función debido al cierre que se crea .

+0

Gracias Ryan, agradezco la respuesta bien pensada. – KodeKreachor

+0

Necesito un botón +2 para esta respuesta – KodeKreachor

+0

Lo añadiré para usted también :-) Manera muy limpia de hacer esto. Además, salga a menudo del modelo de vista infantil que la gente quiere es realmente solo otro modelo (es solo datos puros). A veces es más fácil pensarlo de esa manera, como sea que los llamemos –

Cuestiones relacionadas