Search code examples
javascripthtmlknockout.jsko.observablearray

Update Knockoutjs table


I have a table bound to knockoutjs using foreach.

<table>
<thead>
    <tr>
        <th>ID</th>
        <th>BALANCE</th>
        <th>GENDER</th>
        <th>AGE</th>
    </tr>
</thead>
<tbody>
    <!-- ko foreach: data -->
    <tr>
        <!-- ko foreach: Object.keys($data) -->
        <td>
            <label data-bind="text: $parent[$data]" />
        </td>
        <!-- /ko -->
    </tr>
    <!-- /ko -->
</tbody>
</table>

Table rows iterate an observableArray (about 2000 items).

After table is rendered, I need to edit a row but table do not render the row changed.

How can I do this whithout clear observableArray and reload it again?

Here JSFIDDLE

Thank you


Solution

  • You need to make your data array properties observable so knockout would observe the changes. I'd suggest you to use knockout mapping to do the job of creating observables for you, like this:

    var foo = new MyVM();
    var mapping = {
        create: function(options) {
            return ko.mapping.fromJS(options.data);
        }
    };
    
    ko.mapping.fromJS(myJS, mapping, foo.data);
    

    But you need to change your markup so it won't just iterate through object properties, but explicitly specify which property should be used:

    <tbody>
        <!-- ko foreach: data -->
        <tr>            
            <td>
                <label data-bind="text: _id" />
            </td>
            <td>
                <label data-bind="text: balance" />
            </td>
            <td>
                <label data-bind="text: gender" />
            </td>
            <td>
                <label data-bind="text: age" />
            </td>            
        </tr>
        <!-- /ko -->
    </tbody>
    

    Here is working demo. Of course you can make observables yourself, then just rewrite your code, so every property of each item in data array would be an observable.

    Edit:

    Well, since we don't know the actual properties, I'd suggest the following code to make observables:

    var foo = new MyVM();
    for (var i=0, n = myJSON.length; i < n; i++) {
        for (var prop in myJSON[i])
            if (myJSON[i].hasOwnProperty(prop))
                myJSON[i][prop] = ko.observable(myJSON[i][prop]);
    }
    foo.data(myJSON);
    

    And in your view model function:

    self.changeRow = function (){
        if(typeof self.data() != "undefined"){
            self.data()[0]["gender"]("male");
        }
    };
    

    See updated demo.