Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Observable array where each item in array contains an array - how to make the inner array observable

Tags:

knockout.js

Issue: I have Json coming back from the server. The Json is an array of businesses where each business can have multiple contacts. I want to make the contacts an observable array also, so that html elements bound to the contacts get updated upon deletion and the array gets updated upon editing.

I've setup the following jsFiddle - http://jsfiddle.net/rdotlee/GCwjX/1/.

Here is my view model from the jsFiddle.

    var businessViewModel =
{
    allBusinesses: ko.observableArray([
                                        { name: "Biz1", id: 1, Contacts: [{ name: "Joe", email: "test@test", phone: "555-111-1111" }, { name: "Smith", email: "smith@test", phone: "777-111-2223"}] },
                                        { name: "Biz2", id: 2, Contacts: [{ name: "Joe", email: "test@test", phone: "555-222-1111" }, { name: "Smith", email: "smith@test", phone: "555-111-2222"}] }
                                      ]),

    businessId: ko.observable(1)

};

businessViewModel.selectedBusiness = ko.dependentObservable(function () {
    var biz = this.allBusinesses()[0];

    for (var i = 0; i < this.allBusinesses().length; i++) {
        if (this.allBusinesses()[i].id == this.businessId()) {
            biz = this.allBusinesses()[i];
            break;
        }
    }
    return biz;
}, businessViewModel);

businessViewModel.removeContact = function (contact) {
    ko.utils.arrayRemoveItem(this.selectedBusiness().Contacts, contact);
    ko.applyBindings(businessViewModel, $("#sectionBusinesses")[0]);
} .bind(businessViewModel);

What is the cleanest / recommended way to do what I need?

Thanks,

like image 587
RDotLee Avatar asked Jul 09 '26 18:07

RDotLee


1 Answers

First off, I'm not sure why you're calling ko.applyBindings every time a contact is removed. You'll generally only ever want to call applyBindings once, any more than that usually causes problems.

I would recommend using the ko.mapping plugin, which will make the whole process rather painless.

I've also updated your removeContact to work with the updated ViewModel and changed your selectedBusiness a little too.

Here's the fiddle: http://jsfiddle.net/GCwjX/5/ and the code:

var jsonData = {
    allBusinesses: [{
        name: "Biz1",
        id: 1,
        Contacts: [{
            name: "Joe",
            email: "test@test",
            phone: "555-111-1111"},
        {
            name: "Smith",
            email: "smith@test",
            phone: "777-111-2223"}]},
    {
        name: "Biz2",
        id: 2,
        Contacts: [{
            name: "Joe",
            email: "test@test",
            phone: "555-222-1111"},
        {
            name: "Smith",
            email: "smith@test",
            phone: "555-111-2222"}]}]
};
var businessViewModel = {
    allBusinesses: ko.observableArray(),
    businessId: ko.observable(1)
};

businessViewModel.selectedBusiness = ko.dependentObservable(function() {
    var biz = this.allBusinesses()[0];
    biz = ko.utils.arrayFirst(this.allBusinesses(), function(item) { 
        return (item.id() === parseInt(this.businessId())); 
    }, this);
    return biz;
}, businessViewModel);

businessViewModel.removeContact = function(contact) {
    this.selectedBusiness().Contacts.remove(contact);
}.bind(businessViewModel);

ko.mapping.fromJS(jsonData, {}, businessViewModel);
ko.applyBindings(businessViewModel);​
like image 164
MHollis Avatar answered Jul 12 '26 00:07

MHollis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!