Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout Subscribe to any change in observable complex object

Tags:

knockout.js

I have a viewmodel which contains an observable, which is initialized with an object. this object itself contains observables.

my goal is to be notified whenever that object changes (or: when any observable in that object changes)

jsfiddle

complex object:

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

binding

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

is there any possiblity to react on changes on a complex object? any help is appreciated.

i already tried the dirtyFlag solutions (link in the comments), from rpniemeyer. the problem with a dirty flag on the complex object is, that when it switches to "true" and i'm hooking into the subscription of that flag, thats only ok for the first time. to react to further changes, i would need to set the dirtyFlag to false again (after doing my stuff in the subscription). which would lead into a subscription loop.

like image 229
chris vietor Avatar asked Nov 19 '14 13:11

chris vietor


People also ask

What is a Knockout observable?

Knockout. js defines an important role when we want to detect and respond to changes on one object, we uses the observable. An observable is useful in various scenarios where we are displaying or editing multiple values and require repeated sections of the UI to appear and disappear as items are inserted and deleted.

How do I set observable value in Knockout?

To create an observable, assign the ko. observable function to the variable. A default value can be specified in the constructor of the call. Knockout then converts your variable into a function and tracks when the value changes, in order to notify the UI elements associated with the variable.

How do you clear observable in Knockout?

It can be like this. var model = { "xId": ko. observable(0), "xName": ko. observable(null), "Type": ko.

What is Ko computed in Knockout JS?

ko. computed( evaluator [, targetObject, options] ) — This form supports the most common case of creating a computed observable. evaluator — A function that is used to evaluate the computed observable's current value. targetObject — If given, defines the value of this whenever KO invokes your callback functions.


1 Answers

You can use the following trick:

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

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

The reason why this works is ko.toJSON will recursively read all the properties in the object, therefore making the computed depend on all the properties.

like image 133
sroes Avatar answered Sep 24 '22 03:09

sroes