2012-04-13 7 views
25

¿Hay alguna forma en que pueda decirle al complemento de mapeo de desactivación que se suscriba a todos los cambios de propiedad llame a cierta función?KnockoutJS suscríbase a cambios de propiedad con el complemento de mapeo

Soy consciente de que puedo suscribir de forma manual para el evento de cambio de propiedad de esta manera:

var viewModel = { 
    name: ko.observable('foo'), 
} 

// subscribe manually here 
viewModel.name.subscribe(function(newValue){ 
    // do work 
}) 

me gustaría ser capaz de suscribirse de forma genérica sin embargo, desde mi punto de vista los modelos pueden variar, yo no quiero codificar los nombres de las propiedades. Creé una función que hace esto, pero puede que no sea el mejor enfoque. Funciona en todos los navegadores, excepto en IE7 y versiones posteriores.

Aquí me tomo un modelo de vista como un argumento y tratar de reflejar en él la suscripción de las propiedades:

function subscribeToKO(data) { 

     $.each(data, function (property, value) { 
      if (getType(value) == "Object") 
       data[property] = subscribeToKO(value); 
      else if (getType(value) == "Array") { 
       $.each(value, function (index, item) { 
        item = subscribeToKO(item); 
       }); 
      } 
      else { 
       if (value.subscribe) { 
        value.subscribe(function (newValue) { 
         // do work           
        }); 
       } 
      } 
     }); 
     return data; 
    } 

Como he dicho esto funciona, pero desde que estoy usando el pluging mapeo Tenía la esperanza de que había una gancho que podría usar para proporcionarle una función que se suscribirá genéricamente a los cambios de propiedad.

Algo así como:

mapping = { 
    create: function(options){ 
     options.data.subscribe(function(newValue){ 
      // do work ??? 
     }); 
    } 
} 

ko.mapping.fromJS(viewModel, mapping); 

¿Alguna idea?

Respuesta

9

Aquí hay un enfoque genérico basado en Ryan Niemeyer's dirty flag.
Haga clic aquí para el JsFiddle.

HTML:

<ol> 
<li> 
    Telephone : <input data-bind="value: telephone"/> 
</li> 
<li> 
    Address : <input data-bind="value: address"/> 
</li> 
</ol>​ 

Javascript:

var model = { 
    telephone: ko.observable('0294658963'), 
    address: ko.observable('167 New Crest Rd') 

}; 
// knockout extension for creating a changed flag (similar to Ryan's dirty flag except it resets itself after every change) 
ko.changedFlag = function(root) { 
    var result = function() {}; 
    var initialState = ko.observable(ko.toJSON(root)); 

    result.isChanged = ko.dependentObservable(function() { 
     var changed = initialState() !== ko.toJSON(root); 
     if (changed) result.reset(); 
     return changed; 
    }); 

    result.reset = function() { 
     initialState(ko.toJSON(root)); 
    }; 

    return result; 
}; 
// add changed flag property to the model 
model.changedFlag = new ko.changedFlag(model); 
// subscribe to changes 
model.changedFlag.isChanged.subscribe(function(isChanged) { 
    if (isChanged) alert("model changed"); 
}); 
ko.applyBindings(model);​ 
3

Este pequeño práctico plugin es bastante cerca de lo que hizo pero viene con varias opciones y puede trabajar sobre un conjunto mucho más amplio de requisitos sin que requiere el plugin Mapping:

https://github.com/ZiadJ/knockoutjs-reactor

Básicamente le permite escribir este tipo de código:

ko.watch(viewModel, function(target, trigger) { 
    // do work 
}); 
Cuestiones relacionadas