2014-11-19 5 views
14

Ho un viewmodel che contiene un osservabile, che è inizializzato con un oggetto. questo oggetto stesso contiene osservabili.Knockout Iscriviti a qualsiasi modifica nell'oggetto osservabile complesso

il mio obiettivo è quello di ricevere una notifica ogni volta che i cambiamenti di oggetto (o: quando un qualsiasi osservabile che i cambiamenti degli oggetti)

jsfiddle

complesso oggetto:

var ns = ns || {}; 

ns.ComplexObj = function (item) { 
    var self = this; 

    if (!item) { 
     item = {}; 
    } 

    self.id = item.Id || ''; 
    self.company = ko.observable(item.Company || ''); 
    self.email = ko.observable(item.Email || ''); 

    self.company.subscribe(function() { 
     console.log('debug: company changed'); 
    }); 

    return self; 
}; 

ViewModel

ns.mainvm = function() { 
    var simpleObject = ko.observable('i am pretty simple'); 

    simpleObject.subscribe(function (newValue) { 
     document.getElementById('simpleSubscribtionFeedback').innerText = newValue; 
    }); 

    var complexObject = ko.observable(ns.ComplexObj()); 
    complexObject.subscribe(function (newValue) { 
     // i would like to react to any change in complex object 
     document.getElementById('complexSubscribtionFeedback').innerText = 'i dont get executed :('; 
    }); 

    return { 
     simpleObject: simpleObject, 
     complexObject: complexObject 
    }; 
}; 

vincolante

var container = document.getElementById('wrapper'); 
if (container) { 
    ko.applyBindings(ns.mainvm, container); 
} else { 
    console.warn("container for binding ko not found"); 
} 

v'è alcuna possibilità di abilitare reagire a cambiamenti di un oggetto complesso? ogni aiuto è apprezzato.

ho già provato le soluzioni dirtyFlag (collegamento nei commenti), da rpniemeyer. il problema con una bandiera sporca sull'oggetto complesso è che, quando passa a "true" e sto agganciando la sottoscrizione a quel flag, questo è ok solo per la prima volta. per reagire a ulteriori cambiamenti, avrei bisogno di impostare dirtyFlag su false di nuovo (dopo aver fatto le mie cose nell'abbonamento). che porterebbe in un ciclo di abbonamento.

+0

[Questo post] (https://roysvork.wordpress.com/2014/01/12/tracking-changes-to-complex-viewmodels-with-knockout-js/) potrebbe iniziare. – Michael

+0

grazie per il tuo commento! ho modificato la mia domanda in fondo. –

+1

Questo plugin sembra fare esattamente quello che hai: https://github.com/ZiadJ/knockoutjs-reactor – Domysee

risposta

29

È possibile utilizzare il seguente trucco:

ko.computed(function() { 
    return ko.toJSON(complexObject); 
}).subscribe(function() { 
    // called whenever any of the properties of complexObject changes 
}); 

Vedi http://jsfiddle.net/xcajt4qn/3/

Il motivo per cui questo funziona è ko.toJSON sarà ricorsivamente leggere tutte le proprietà nell'oggetto, rendendo il calcolato dipendono da tutte le proprietà .

+2

bello, grazie mille! –

+3

Sei arrabbiato per aver trovato questo trucco. Ma anche fantastico. – kernel

+4

Si noti che questo verrà anche chiamato ogniqualvolta cambiano le proprietà * non * -osservabili dell'oggetto, che potrebbero non essere desiderate. – tloflin