VaticanUK
VaticanUK

Reputation: 1197

knockout.js table filter doesn't update

I've been battling with what seems like it should be a really simple Knockout.js task for a number of hours, and after reading multiple websites and questions on SO, I'm still stumped!

Here is the fiddle: http://jsfiddle.net/PL8UW/

Essentially I have a table with a "status" column that is bound to a knockout viewmodel.

I also have an observable object that should allow you to filter on various statuses

If i bind the table directly to the data object everything shows, but if I bind to the computed, then nothing shows.

HTML:

<form>
    <input id="foo" type="checkbox" checked /> Foo
    <input id="bar" type="checkbox" checked /> Bar
</form>
<div id="tableDiv">
    <table>
        <thead>
            <tr>
                <th>Id</th>
                <th>Status</th>
            </tr>
        </thead>
        <tbody data-bind="foreach: filteredData">
            <tr>
                <td><span data-bind="html: id"></span></td>
                <td><span data-bind="html: status"></span></td>
            </tr>
        </tbody>
    </table>
</div>

javascript: var data = [ {"id": 1, "status": "foo"}, {"id": 2, "status": "bar"}, {"id": 3, "status": "foo"}, {"id": 4, "status": "foo"}, {"id": 5, "status": "bar"}];

var viewModel = { 
    tableData: ko.observableArray(data),
    filter: ko.observable({'foo': ko.observable(true), 'bar': ko.observable(true)}),
    filteredData: ko.computed(function() {
        return ko.utils.arrayFilter(viewModel.tableData, function(item) {
            return viewModel.filter[item.Status];
        });
    })    
};

ko.applyBindings(viewModel, document.getElementById('tableDiv'));

$('input[type=checkbox]').click(function () {
    viewModel.filter[this.id] = this.checked;
});

Upvotes: 0

Views: 369

Answers (1)

nemesv
nemesv

Reputation: 139778

You have numerous smaller, bigger errors in your fiddle which are coming from two fundamental problem (beside the fact that your design your storing the filter and little bit complicated and you are mixing the jQuery event handlers with Kncokout viewmodels):

So here is a fixed version of your code with comments:

var viewModel = { 
    tableData: ko.observableArray(data),
    filter: ko.observable({'foo': ko.observable(true), 'bar': ko.observable(true)}),
    filteredData: ko.computed(function() {
        // missing () after viewModel.tableData
        return ko.utils.arrayFilter(viewModel.tableData(), function(item) {
            //missing () after filter and at the end
            //typo: Satus should be status
            return viewModel.filter()[item.status]();
        });
        //deferEvaluation was needed to refernce viewModel inside the computed
    }, null, {deferEvaluation: true}) 
};

ko.applyBindings(viewModel, document.getElementById('tableDiv'));

$('input[type=checkbox]').click(function () {
    //missing () after filter missing () to set the observable value
    viewModel.filter()[this.id](this.checked);
});

Demo JSFiddle.

Here is a different solution using the checked binding for handling the filter:

Demo JSFiddle.

Upvotes: 1

Related Questions