2011-07-15 14 views
23

Tengo varias cajas de entrada que quiero ocultar/mostrar en función de una selección del usuario.knockoutjs: ¿podemos crear una función dependienteObservable con un parámetro?

puedo lograr esto por tener un dependentObservable separado para cada entrada y a su vez hacer que el dependentObservable observar la selección de los padres.

viewModel.showField1= ko.dependentObservable(function() { 
    return viewModel.selectedType() ? IsFeatureVisible(viewModel, "BusinessFieldName1") : false; 
}, viewModel 
); 

viewModel.showField1= ko.dependentObservable(function() { 
    return viewModel.selectedType() ? IsFeatureVisible(viewModel, "BusinessFieldName2") : false; 
}, viewModel 
); 

esto es un poco tediosa que hacer para cada campo. ¿Puedo vincular los elementos con una función dependienteObservable que puede tomar un parámetro? Lo importante es que debe activarse cuando el padre cambia

Otra opción es que cuando el padre cambia, recorro los elementos y ocultar/mostrar pero eso me requerirá asignar el elemento id < -> nombre comercial del campo.

actual

<tr data-bind="visible: showField1"> 
<tr data-bind="visible: showField2"> 

Desired

<tr data-bind="visible: showField('BusinessFieldName1')"> 
<tr data-bind="visible: showField('BusinessFieldName2')"> 

Respuesta

31

En Knockout, los enlaces se implementan utilizando internamente dependentObservables, por lo que en realidad se puede utilizar una función normal en lugar de un dependentObservable en sus fijaciones. El enlace ejecutará su función dentro de un dependienteDebservable, por lo que cualquier observable que tenga acceso a su valor creará una dependencia (su enlace se activará de nuevo cuando cambie).

Este es un ejemplo: http://jsfiddle.net/rniemeyer/2pB9Y/

html

type "one", "two", or "three": <input data-bind="value: text" /> 
<hr /> 
<ul data-bind="template: { name: 'itemTmpl', foreach: items }"></ul> 

js

<script id="itemTmpl" type="text/html"> 
    <li data-bind="text: name, visible: viewModel.shouldThisBeVisible(name)"></li> 
</script> 

var viewModel = { 
    text: ko.observable("one"), 
    items: [{name: "one"}, {name: "two"}, {name: "three"}], 
}; 

viewModel.shouldThisBeVisible = function(name) { 
    return this.text() === name; 
}.bind(viewModel); 

ko.applyBindings(viewModel); 
+0

gracias. Funcionó maravillosamente. Me salvaste mucho tiempo. –

+2

Solo una nota para actualizar a cualquiera que se presente. En versiones más recientes de knockout no hay necesidad de usar una 'plantilla' en este caso, solo puede usar' foreach'.He visto desarrolladores usando 'plantilla' porque no entendían esto. No hay nada especial sobre el enlace de la plantilla que lo habilite. –

12
var someOtherViewModel = { 
    showField: function(fieldName) { 
     return ko.dependentObservable(function() { 
      return viewModel.selectedType() ? IsFeatureVisible(viewModel, fieldName) : false; 
     }, viewModel); 
    } 
}; 

Usted puede crear una función similar a la anterior. La función devuelve un nuevo dependiente observable para el nombre de campo específico.

Ahora usted puede hacer:

<tr data-bind="visible: someOtherViewModel.showField('Field1')"> 

informarme si ese código no funciona - tal vez me haya perdido algo. Luego editaré esta publicación.

+0

que parece genial. Voy a intentarlo. –

+0

¡Funciona como un amuleto, gracias! –

+0

Esto es genial, aunque creo que debes tener cuidado al usar esto. Digamos que si estás llamando a showField en un ciclo con cientos de registros, básicamente estás creando 100 dependienteObservables en la memoria. En ese caso, sería mejor simplemente definir showFieldX, showFieldY, etc. en su VM dado que no están en los 100 para mantener baja la huella de memoria del lado del cliente. – jesal

0

Tomando la idea de @Arxisos aún más, se me ocurrió esto.

self.showField = function (fieldName) 
{ 
    return ko.dependentObservable(function() 
    { 
     return this.selectedType() ? IsFeatureVisible(this, fieldName) : false; 
    }, this)(); 
}; 
Cuestiones relacionadas