Valentin H
Valentin H

Reputation: 7448

Update view, when a filter on observable array changes

I want to display only a subset from an observable array arrayData Using ko if I was able to apply the filter on the data:

<div class="image-list" data-bind="foreach: arrayData">
   <!-- ko if: type == 0 -->
    viewing only objects with attribute type==0

However, I don't know, how to trigger updating the view, when I want to change the filter e.g. type == 1

If it possible?

P.S:

Currently I use foreach with a copy of the data, which I clear end reset in the model. But for this approach I need one observable array for each filter in the model and lot of copying

Upvotes: 0

Views: 485

Answers (2)

Brian Fitzpatrick
Brian Fitzpatrick

Reputation: 357

I would recommend using ko.utils.arrayFilter to grab the items you want to show. You need to add an observable to hold the value you want to filter on, then use it in 'arrayFilter' to change which items to show.

//ViewModel code below
var self = this;
self.selectedType = ko.observable(0); //starts at 0, when it changes it will kick off the 'filtered' computed.
self.filtered = ko.computed(function(){
  return ko.utils.arrayFilter(arrayData, function(item) {
        if (item.type() == self.selectedType()){
           return item;
        };
    });
})

This will return a list of items from 'arrayData' that match the criteria defined in 'arrayFilter'. Then your foreach data-bind would just bind to this computed, rather than directly to arrayData.

<div class="image-list" data-bind="foreach: filtered">

You can read more about the ko.utils functions here (plenty of other goodies!): http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html

Edit: Thanks to connexo for pointing out the updating the view portion of the question. Totally missed that in my initial read through.

Upvotes: 2

connexo
connexo

Reputation: 56754

Store the value with which you compare type in an observable:

self.selectedType = ko.observable();

and update its contents to your needs in your viewmodel functions.

Then use it to compare:

<!-- ko if: type == selectedType() -->

If you can make use of underscore, you can also apply its filtering directly to your foreach binding:

<div class="image-list" data-bind="foreach: _.filter(arrayData, function() { return type== $root.selectedType() })">

var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });

=> [2, 4, 6]

http://underscorejs.org/#filter

Upvotes: 1

Related Questions