Reputation: 179
I have a search/filter field that I would like to be able to filter on any value of the collection. The data I have is as follows:
exports.administrators = [
{
id: 1,
firstName: "User1",
lastName: "Tester",
phone: "781-000-0000",
email: "[email protected]",
privileges: "view-only"
}, {
id: 2,
firstName: "Mickey",
lastName: "Mouse",
phone: "781-123-4567",
email: "[email protected]",
privileges: "all"
}, {
id: 3,
firstName: "Snow",
lastName: "White",
phone: "781-890-1234",
email: "[email protected]",
privileges: "all"
}, {
id: 4,
firstName: "Anakin",
lastName: "Skywalker",
phone: "888-874-9084",
email: "[email protected]",
privileges: "view-only"
}, {
id: 5,
firstName: "Obi-one",
lastName: "Kenobi",
phone: "908-765-5432",
email: "[email protected]",
privileges: "all"
}, {
id: 6,
firstName: "Master",
lastName: "Yoda",
phone: "876-654-2134",
email: "[email protected]",
privileges: "view-only"
}, {
id: 7,
firstName: "Han",
lastName: "Solo",
phone: "781-456-3209",
email: "[email protected]",
privileges: "all"
}, {
id: 8,
firstName: "Neo",
lastName: "TheOne",
phone: "781-000-0000",
email: "[email protected]",
privileges: "all"
}];
The View will fire an event based on the keyup event:
AdministratorView.prototype.events = {
'click .sub-content th.sort, .sub-content th.sort-up, .sub-content th.sort-down': 'sortTable',
'click .light-btn': 'showAdd',
'keyup #filter-find': 'filterAdministrators'
};
I have also abstracted the function that I want to perform the filtering:
App.Utils.filterCollection = function(collection, filterValue) {
if (filterValue !== "") {
return _.filter(collection.models, function(data) {
var values;
values = _.values(data.attributes);
_.each(values, function(value) {
if (!isNaN(value)) {
value = value.toString();
}
return value.indexOf(filterValue) > 0;
});
});
}
};
The problem I have is:
Thanks for all the help in advance.
Cheers,
Kianosh
Updated function:
I have updated the function with some input from @dbaseman
App.Utils.filterCollection = function(collection, filterValue) {
var filteredCollection;
if (filterValue === "") {
[];
}
return filteredCollection = collection.filter(function(data) {
return _.some(_.values(data.toJSON()), function(value) {
value = !isNaN(value) ? value.toString() : value;
return value.indexOf(filterValue) >= 0;
});
});
};
However I am still getting an empty (or undefined) value from the function. I am stomped!!
Update #2 Found a partial solution. Here is the jsFiddle - http://jsfiddle.net/kianoshp/YWSSp/. It filters correctly, however when I blank out the filter field I expect the original data set to be displayed. However now I get a blank table. Working on solution but any help/hint would be helpful.
Update #3 Final solution is here in the jsFiddle --> http://jsfiddle.net/kianoshp/YWSSp/77/ thanks to @dbaseman
Upvotes: 1
Views: 2689
Reputation: 5046
I've taken the answer McGarnagle provided and added some improvements. The below code allows you to search inside Models that have properties consisting of objects.
Backbone.Collection.prototype.filterValues = function(filterValue) {
if (filterValue === ""){
return this.models;
}
function collectionFilter(data) {
if(data.toJSON){
data = data.toJSON();
}
return _.some(_.values(data), function(value) {
if(_.isObject(value)){
return collectionFilter(value);
}
if (_.isNumber(value)){
value = value.toString();
}
if (_.isString(value)){
value = value.toLowerCase();
return value.indexOf(filterValue) !== -1;
}
return false;
});
}
return this.filter(collectionFilter);
};
Upvotes: 2
Reputation: 102733
I don't think there's a more elegant way, except for minor improvements:
collection.filter
_.some
to check if any value matchesAs far as problems, there are two as far as I could tell:
_.values
on a Backbone model (that's what filter
returns when called on a Backbone collection). You have to call filter on the JSON representation, using model.toJSON()
.indexOf
on the value. I think you meant to check if it's a string (`typeof value == 'string').Here's the modified function (Demo).
Backbone.Collection.prototype.filterValues = function(filterValue) {
if (filterValue == "") return [];
return this.filter(function(data) {
return _.some(_.values(data.toJSON()), function(value) {
if (_.isNumber(value)) value = value.toString();
if (_.isString(value)) return value.indexOf(filterValue) != -1;
return false;
});
});
}
Upvotes: 2