user3587180
user3587180

Reputation: 1397

How to make obseravble array notify its dependencies when a property of an object inside the observable array gets updated?

I have the below array bound to a template

function Customer(id, name){
   this.Id = ko.obserable(id);
   this.Name = ko.obserable(name);
}

var customer1 = new Customer(1, "a");
var customer2 = new Customer(2, "b");

var customers = [customer1, customer2];

var oa = ko.observableArray(customers);

oa.subscribe(function(newValues){
   //How to force trigger this when a customer property gets updated?
});

When I update a customer name on the view, the array has the updated data, but it does not notify it's subscribers. How do I get around that and force notify its subscribers?

Upvotes: 1

Views: 39

Answers (1)

user3297291
user3297291

Reputation: 23372

You can use computed values to automatically track changes in a list of values. Every observable you unwrap inside the computed function will create a dependency.

The only downside: you won't know which change caused the update. If that's what you need, you need to subscribe to the individual Name observables.

Here's an example that uses a custom equality comparer to keep things tidy. You can also only have hash return a string and unwrap oa inside the subscriber method manually.

function Customer(id, name){
   this.Id = ko.observable(id);
   this.Name = ko.observable(name);
   this.toString = () => `(${this.Id()}) ${this.Name()}`;
}

var customer1 = new Customer(1, "a");
var customer2 = new Customer(2, "b");

var customers = [customer1, customer2];

var oa = ko.observableArray(customers);

var oaHash = ko.pureComputed(() => ({ 
  hash: oa().map(c => c.Name()).join("||"),
  newValues: oa()
}));

oaHash.equalityComparer = (a, b) => a === b || a && b && a.hash === b.hash;

oaHash.subscribe(function ({ newValues }) {
  console.log(
    "Something changed, I now contain:",
    newValues.map(c => c.toString()).join(", ")
  );
});

customer1.Name("Jane");
oa.push(new Customer(3, "c"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

Upvotes: 1

Related Questions