1

I have an observableArray in my knockout application as shown below:

self.Parents = ko.observableArray([
    {
      Father: 'Father-A',
      Mother: 'Mother-A',
      Children: ko.observableArray([
        {Name: 'Child-A1'}, 
        {Name: 'Child-A2'}, 
        {Name: 'Child-A3'}])
    },
    {
      Father: 'Father-B',
      Mother: 'Mother-B',
      Children: ko.observableArray([
        {Name: 'Child-B1'}, 
        {Name: 'Child-B2'}, 
        {Name: 'Child-B3'}])
    }]);

And I have computed observable on Parents variable as shown below:

ko.computed(function(){
    alert('Record Updated');
    console.log(self.Parents());
});

Now when I add/remove Children to any of the Parent, I believe above computed function should be called as Parent variable is indirectly getting updated when I add/remove child. But it is not working. As a solution of below fiddle, Record Updated alert should be displayed.

Fiddle - Code Snippet

So how can I achieve this ?

Note: Here please take a note that this is just a sample I have created. In actual scenario, Parents object is passed to the third party grid library. And if any change occurs in Parent/Child that grid should be updated. That's the reason why I have written self.Parents() in computed function and not Children

ConfusedDeveloper
  • 6,389
  • 4
  • 21
  • 36

2 Answers2

1

You can use ko.toJs to create a dependency on every observable in an object.

ko.computed(function() {
   alert("Children Array changed");
   return ko.toJS(self.Parents());
});

You can do your operations inside the computed property. But logic inside a computed property seems wrong, so you create a subscription to that computedToJS property:

  self.isDirty = ko.observable(false);

  self.computedToJS = ko.computed(function() {
    return ko.toJS(self.Parents());
  });

  self.computedToJS.subscribe(function(value){
    self.isDirty(true);
    // Do all your stuff here.
  });

Mind you, this gets triggered for all the observables. If you were to change the Father property to an observable and update the property, then the computed gets triggered again.

Here's an updated fiddle

You can go through this blog post on creating dirty flags in knockout using ko.toJS


Alternatively, you could create a ParentViewModel and add a subscribe to the Children observableArray which is available from Knockout 3.0+. You can go through this question for an example.

adiga
  • 34,372
  • 9
  • 61
  • 83
0

I have fixed the solution my self.

After removing child row, below line of code will notify parents that child data has been changed:

self.Parents.valueHasMutated()
ConfusedDeveloper
  • 6,389
  • 4
  • 21
  • 36