Нокаут Подпишитесь на любое изменение наблюдаемого сложного объекта

У меня есть viewmodel, который содержит наблюдаемый, который инициализируется объектом. этот объект сам содержит наблюдаемые.

моя цель - уведомляться всякий раз, когда этот объект изменяется (или: когда любое наблюдаемое в этом объекте изменяется)

jsfiddle

сложный объект:

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
   };
};

связывания

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

есть ли возможность реагировать на изменения на сложном объекте? любая помощь приветствуется.

Я уже пробовал решения dirtyFlag (ссылка в комментариях), от rpniemeyer. проблема с грязным флагом на сложном объекте заключается в том, что когда он переключается на "true", и я подключаюсь к подписке этого флага, это только нормально в первый раз. чтобы отреагировать на дальнейшие изменения, мне нужно снова установить dirtyFlag в false (после выполнения моих действий в подписке). который приведет к циклу подписки.

Ответы

Ответ 1

Вы можете использовать следующий трюк:

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

См. http://jsfiddle.net/xcajt4qn/3/

Причина, по которой это работает, ko.toJSON будет рекурсивно читать все свойства объекта, поэтому вычисление зависит от всех свойств.