Search code examples
javascriptknockout.jsko.observablearray

knockout observablearray of observables


I am having problems with a Knockout ObservableArray that is made up of objects with observable properties. My view model is fairly complicated but I have created the simple test below which will illustrate the problem.

My problem is that when I change the value of an observable property in one of the objects in the ObservableArray that value is changed for ALL objects in the array.

I have a department viewModel which has an observable array of employees in that department. I then create 5 instances of the object personVM that gets pushed onto the employees ObservableArray. Each instance of personVM gets a unique firstName.

Here are the models and the code to load them up.

var theDepartmentVM = {
        employees: ko.observableArray(), 
        departmentName: ko.observable()
};

var personVM= {
    firstName: ko.observable()
    }

$(document).ready(function (){
    departmentVM.departmentName = "SomeDepartment";
    for (i=1; i<=5; i++){
        var person = Object.create(personVM);
        personVM.firstName("EMP - " + i.toString());
        departmentVM.employees.push(personVM);
    }
    ko.applyBindings(departmentVM);
});

This adds five name (EMP-1, EMPT-2, etc.). Then I display the names with the following markup:

<div data-bind="foreach: employees">
   <label data-bind="text: firstName"></label>
</div>

My output is the name "EMP-5" five times. It's always the last value I added to the array.

I think the problem is that I have five instances of personVM but the firstName object in each instance points to the same observable. Is this correct?

What do I need to do to get the desired result?


Solution

  • Try this

    http://jsfiddle.net/r9sqjojL/2/

    <div data-bind="foreach: employees">
       <label data-bind="text: firstName"></label>
    </div>
    var departmentVM = {
            employees: ko.observableArray(), 
            departmentName: ko.observable()
    };
    
    var personVM = function() {
            this.firstName = ko.observable();
    }
    departmentVM.departmentName = "SomeDepartment";
    for (i=1; i<=5; i++){
            var person = new personVM();
            person.firstName("EMP - " + i.toString());
            departmentVM.employees.push( person );
    }
    ko.applyBindings(departmentVM);