Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Observing properties of an array that is being observed in KnockoutJS

I'm working on an ASP.Net MVC application. My action is returning a view with a model that is an array of objects (a class with properties like Name, ID, IsViewable).

var model = @Model.ToJson(); // done via extension call

I want to observe this array, so whenever it changes I can update a table that has been bound to a template.

var viewModel = {
    accounts = ko.observableArray(model)
}

This works just fine for adding and deleting elements from the array. However, I also want the template to update when a property in one of the accounts changes (ie, Name or ID).

On the KnockoutJS website, it says: Of course, you can make those properties observable if you wish, but that’s an independent choice. This is what I cannot figure out how to do.

I tried something like this with no avail:

var viewModel = {
    accounts = ko.oservableArray([])
}

for(var i = 0; i < model.length; i++) {
    ko.observableArray(model[i]);
    viewModel.accounts.push(model[i]);
}

I can post the template and the table if it's needed.

like image 464
harryfino Avatar asked Jan 21 '11 19:01

harryfino


People also ask

What is an observable array?

ObservableArray is an array that allows listeners to track changes when they occur.

What are observables in knockout?

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 you declare a ViewModel property as observable?

You just need to declare ViewModel property with function ko. observable() to make it Observable.

How do you clear a knockout observable array?

To clear an observableArray you can set the value equal to an empty array.


2 Answers

You should look into the knockout.mapping plugin. I think it does everything you are looking to do.

like image 82
Sergei Golos Avatar answered Nov 07 '22 06:11

Sergei Golos


I ended up getting this to work, so I thought I would share with anyone that might have having the same problem.

You need to wrap your array items in a JavaScript class. Then in the constructor, set each property to obserable:

var model = @Model.ToJson();

var viewModel = {
    accounts = ko.observableArray(ko.utils.arrayMap(model, function(account) {
        return new AccountWrapper(account);
    }))
};

function AccountWrapper(account) {
    this.Property1 = ko.observable(account.Propery1);
    this.Property2 = ko.observable(account.Propery2);
    this.Property3 = ko.observable(account.Propery3);
}

ko.applyBindings(viewModel);

And if you want to modify one of the items directly to see the change, you could do something like:

viewModel.accounts()[3].Name('My Name Changed');

And you can still get notified when items are added or remove:

viewModel.accounts.remove(viewModel.accounts()[4]);
like image 36
harryfino Avatar answered Nov 07 '22 05:11

harryfino