Reputation: 16934
I have a simple model object with one array property.
Example:
{name: 'Foo', tags = ['fun', 'cool', 'geek']};
I add more one of these models to an obervableArray
in my view model.
//pseudo code
oa.add({name: 'Foo', tags: ['fun', 'cool', 'geek']});
oa.add({name: 'Bar', tags: ['sad', 'dorky', 'uncool']});
oa.add({name: 'Qwerty', tags: ['keys', '101', 'geek']});
Now when I filter an item based on a tag I would like to display a message that there are no more items with a certain tag.
Filter code:
// self = this;
self.filter = ko.observable('');
self.filterItems = ko.dependentObservable (function() {
var filter = this.filter();
if (!filter) {
return this.items();
} else {
return ko.utils.arrayFilter(this.items(), function(item) {
try {
if (compareAssociativeArrays(item.tags, filter)) {
return true;
}
} catch (e) {}
self.items.remove(item);
});
}
}, this);
Is it possible to data-bind a given length of items with an indexOf a tag value ?
UPDATE
I did come up with a solution, but not sure if best. With it I can modify and retrieve totals as well:
self.hasGeek = ko.computed(function () {
var sum = 0;
var item;
for (var i=0; i<self.items().length; i++) {
var item = self.items()[i];
if (item.tags().indexOf('geek') != -1) {
sum++;
}
}
return (sum > 0) ? true : false;
});
Upvotes: 0
Views: 1887
Reputation: 114792
I am not sure about your exact structure, but I would setup a computed observable to represent your filtered items. Then, you can include a section that has its visibility controlled by the length of the filtered items computed observable.
Would be like: http://jsfiddle.net/rniemeyer/aVtpc/
Tag Filter: <input data-bind="value: tagFilter" />
<hr/>
<div data-bind="visible: !filteredItems().length">
No items found
</div>
<ul data-bind="foreach: filteredItems">
<li data-bind="text: name"></li>
</ul>
js:
var ViewModel = function() {
this.tagFilter = ko.observable();
this.items = ko.observableArray([
{name: 'Foo', tags: ['fun', 'cool', 'geek']},
{name: 'Bar', tags: ['sad', 'dorky', 'uncool']},
{name: 'Qwerty', tags: ['keys', '101']}
]);
this.filteredItems = ko.computed(function() {
var filter = this.tagFilter();
if (!filter) {
return this.items();
}
return ko.utils.arrayFilter(this.items(), function(item) {
return ko.utils.arrayFirst(item.tags, function(tag) {
return tag === filter;
});
});
}, this);
};
ko.applyBindings(new ViewModel());
Upvotes: 1
Reputation: 22298
Quick psuedo code off my head ... After you filter down the oa, perhaps using a computed function, you can do something like this:
<span data-bind="text: filterOa().length"></span>
<!-- ko: foreach filterOa -->
<span data-bind="text: name"></span>
<!-- /ko -->
<!-- if: filterOa().length === 0 -->
You got nothing
<!-- /ko -->
Upvotes: 0