3

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,

2

1 Answer 1

1

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);​
Sign up to request clarification or add additional context in comments.

1 Comment

Hi @MHollis - thanks for your help and the updated JsFiddle. The reason I was calling applyBindings a second time was to try and make knockout apply the bindings again to see the contact was removed, I realized it wasn't the recommended way to go, but was troubleshooting. I will do some research on the mappings they are not clear to me yet. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.