Boone
Boone

Reputation: 1054

Knockout observableArray not updating with multiple view models

I have multiple view models contained in one master view model. I am trying to insert an item into an array in viewmodel A from viewmodel B. In my log I see the item getting added to the array but it is not updating the UI.

http://jsfiddle.net/U7rXA/

-----HTML

    <form data-bind="submit: RolesVM.addRole">
    <select name="app" data-bind="options:ApplicationsVM.applications,optionsText:'name', value: RolesVM.application"><option></option></select></td>
    <input data-bind='value: RolesVM.role, valueUpdate: "afterkeydown"'/> 
    <button>Add Role</button>
</form>

<ul data-bind="foreach: ApplicationsVM.applications">
    <span data-bind="text:name"></span>
    <ul data-bind="foreach: roles">
        <li data-bind="text:name"></li>
    </ul>
</ul>

-----JS

        function MasterVM(applicationsVM, rolesVM) {
        this.ApplicationsVM = applicationsVM;
        this.RolesVM = rolesVM;
    }
    function ApplicationsVM() {
        var self = this;
        self.applications = ko.observableArray([]);

        self.Populate = function () {
            var allData = jQuery.parseJSON('[{ "name": "app 1", "roles": [{ "name": "role 1" }] }, { "name": "app 2", "roles": [{ "name": "role 1" }] }]');
            var mappedApplications = $.map(allData, function (item) {return new Application(item);});
            self.applications(mappedApplications);
        };
    }
    function RolesVM() {
        var self = this;
        self.application = ko.observable();
        self.role = ko.observable();

        self.addRole = function () {
            self.application().roles().push(self.role());
            console.log(self.application().roles());
        };
    }

    function Application(data) {
        this.name = data.name;
        this.roles = ko.observableArray($.map(data.roles, function(item) { return new Role(item.name); }));
    }

    function Role(data) {
        this.name = data;
    }

    var applicationsVM = new ApplicationsVM();
    applicationsVM.Populate();
    var rolesVM = new RolesVM();
    ko.applyBindings(new MasterVM(applicationsVM, rolesVM));

Upvotes: 1

Views: 1867

Answers (1)

RP Niemeyer
RP Niemeyer

Reputation: 114792

You will want to call push on the observableArray directly and not the underlying array. This is what notifies any subscribers that it has changed. So, you would wan to do:

self.application().roles.push(self.role());

rather than:

self.application().roles().push(self.role());

Upvotes: 4

Related Questions