Yarin
Yarin

Reputation: 183559

Trouble binding tables to Knockout collection

I can't understand why these Knockout table bindings aren't working:

Javascript:

$(function () {

    var FileObject = function(id, name) {
        this.id = id;
        this.name = name;
    };

    var FilesModel = function() {

        this.filesSelected = ko.observable(false);  
        this.myFiles = ko.observableArray([new FileObject(1, 'test_1')]);
        this.myFiles.push(new FileObject(2, 'test_2'));
    };

    var filesModel = new FilesModel();
    window.filesModel = filesModel;
    ko.applyBindings(filesModel);

    filesModel.myFiles().push(new FileObject(3, 'test_3')); // This never shows

    alert(filesModel.myFiles().length); // Shows 3 items

});

HTML:

<h3>TABLE 1</h3>
<table> 
<tbody data-bind="foreach: myFiles">
    <tr>
        <td>FILE:</td>
        <td data-bind="text: name"></td>
    </tr>    
</tbody>
</table>

<h3>TABLE 2</h3>
<table>
<tbody data-bind="foreach: myFiles()">
    <tr>
        <td>FILE:</td>
        <td data-bind="text: name"></td>
    </tr>    
</tbody>
</table>

In both of these tables, the first 2 files will show, but the 3rd file doesn't. What am I missing?

Upvotes: 0

Views: 48

Answers (2)

Ross
Ross

Reputation: 2468

You're really close. Two main things to point out:

  1. Status isn't an observable, and you're attempting to unwrap it with text: status().
  2. You're pushing the new FileObject into an unwrapped array, meaning you're bypassing the observable altogether. Push new items directly into the observable array, you'll have better luck.

I've put together a jsbin example based on your original source.

Specifically, this:

filesModel.myFiles().push(new FileObject(3, 'test_3')); // This never shows

Should be:

filesModel.myFiles.push(new FileObject(3, 'test_3')); // Now it does

Upvotes: 2

rwisch45
rwisch45

Reputation: 3702

In your HTML, you were trying to data-bind status(), but status is not an observable. One approach is to make your FileObject members observables. Also, your third FileObject was never showing because your syntax was wrong. Instead of filesModel.myFiles().push, it should be just filesModel.myFiles.push

See updated fiddle

$(function () {
    var FileObject = function(id, name, size, status, progress) {
        this.id = ko.observable(id);
        this.name = ko.observable(name);
        this.status = ko.observable(status);
    };

    var FilesModel = function() {

        this.filesSelected = ko.observable(false);  
        this.myFiles = ko.observableArray([new FileObject(1, 'test_1')]);
        this.myFiles.push(new FileObject(2, 'test_2', 3, 'status'));
    };

    var filesModel = new FilesModel();
    window.filesModel = filesModel;
    ko.applyBindings(filesModel);

    filesModel.myFiles.push(new FileObject(3, 'test_3')); // This never shows

    alert(filesModel.myFiles().length); // Shows 3 items

});

Upvotes: 1

Related Questions