blogscot
blogscot

Reputation: 41

Data binding Checkboxes using Knockout Observable Arrays

I'm trying to reimplement a student attendance example from the Udacity JavaScript Design Patterns course. So far I've managed to recreate the table and correctly populate it with some student data, however it appears when I change a checkbox value this isn't updated in the model.

For example, when I display

    debugVM.studentList()[0].days();

in the console the output displays the initial attendance data instead of the current state of the checkboxes. A JSFiddle for this can be found here.

index.html

 <table>
  <thead>
    <tr>
      <th>Student</th>
      <!-- ko foreach: attendance -->
      <th data-bind="html: $data"></th>
      <!-- /ko -->
    </tr>
  </thead>
  <tbody data-bind="foreach: studentList">
    <tr>
      <td data-bind="html: name, click: $parent.debugStudent"></td>
      <!-- ko foreach: days -->
      <td>
      <input type="checkbox" data-bind="value: $data, checkedValue: $data, checked: $data" />
      </td>
      <!-- /ko -->
    </tr>
  </tbody>
</table>

app.js

var Student = function(student){

  this.name = ko.observable(student.name);
  this.days = ko.observableArray(student.days);
};


var ViewModel = function() {
  var self = this;

  this.attendance = ko.observableArray([1,2,3,4,5,6,7,8,9,10,11,12]);
  this.studentList = ko.observableArray([]);

  students.forEach(function(student) {
    self.studentList.push(new Student(student));
  });

  self.debugStudent = function() {
    console.log(self.studentList()[0].days());
  };
};
var debugVM = new ViewModel();

ko.applyBindings(debugVM);

Upvotes: 0

Views: 281

Answers (1)

Max Brodin
Max Brodin

Reputation: 3938

From the knockout documentation

Key point: An observableArray tracks which objects are in the array, not the state of those objects

In your case this means that days should be not observable array, but array of observables.

For example you can add new viewModel Day:

var Day = function(isChecked) {
    this.isChecked = ko.observable(isChecked);
}

And set the days property like this

this.days = [];
for (var i = 0; i< student.days.length; i++) {
   this.days.push(new Day(student.days[i] == 1));
}

See working fiddle

Upvotes: 2

Related Questions