I am passing an array to new collection. Is it possible to filter the array by passing second parameter and check on the attr of the object in the array and create collection only if it pass the filter test.
collection = new Backbone.Collection([{name:'xy',age:24},{name:'y',age:35}])
Can I create a collection only for the object less than 30 years.
You can use _.filter on your array before passing into the collection
collection = new Backbone.Collection(
_.filter([{name:'xy',age:24},{name:'y',age:35}],
function(item) { return item.age < 30; }));
Or you can move your custom filtering logic into your collection initialize
where you will get the models
array what you can modify/filter
var Under30 = Backbone.Collection.extend({
initialize: function(models, options) {
for(var i = models.length - 1; i > 0; i-- ){
if (models[i].age > 30){
models.splice(i,1);
}
}
}
});
var collection = new Under30([{name:'xy',age:24}, {name:'y',age:35}]);
console.log(collection.models.length); // will be 1
Demo JSFiddle.
You can extend this with supplying the filter predicate in the options parameter
var FilteredCollection = Backbone.Collection.extend({
initialize: function(models, options) {
for(var i = models.length - 1; i > 0; i-- ){
if (options.filter && options.filter(models[i])){
models.splice(i,1);
}
}
}
});
And use it with
var collection = new FilteredCollection(
[{name:'xy',age:24}, {name:'y',age:35}],
{
filter: function(item) {
return item.age > 30;
}
}
);
console.log(collection.models.length); // will be 1
You're interested in validation before creating the collection, just like the answer before - we'll create a function that lets you reuse that strategy to validate any collection based on a condition you'd like.
//A collection that validates the correctness of the given elements
// based on a predicate (condition). If the items do not _all_ pass
// the condition - the collection will not be created and an error will
// be thrown.
function validatingCollection(predicate){
return function(arr){
//first we assert an array is passed if it's possible to assert
if(Array.isArray && !Array.isArray(arr)){
throw new Error("Can only pass array to filteredCollection");
}
//for older browsers - use _.every
// now we validate they all pass the condition
if(!arr.every(predicate){
throw new Error("Validation error, not all elements pass");
}
//they all pass, create the collection
return new Backbone.Collection(arr);
};
};
Now, we can create such a collection, that validates that every element has age of at least 30:
var ageValidated = validatedCollection(function(obj){ return obj.age < 30; });
//create a new age validatedcollection
try{
var collection = new ageValidated([{name:'xy',age:24},{name:'y',age:35}]);
}catch(e){
// the above throws an error because of the object with age 24
}
//however - this works, and creates a new collection
var collection = new ageValidated([{name:'xy',age:32},{name:'y',age:35}]);
If you just want to filter the elements you don't like - instead of throwing an error if not all of them pass validation you can do something like this :
collection = new Backbone.Collection([{name:'xy',age:24},
{name:'y',age:35}].filter(function(obj){
return obj.age < 30;
});
Alternatively, you can create your own filtered collection constructor for reuse as such
function filteredCollection(predicate){
return function(arr){
//first we assert an array is passed if it's possible to assert
if(Array.isArray && !Array.isArray(arr)){
throw new Error("Can only pass array to filteredCollection");
}
return new Backbone.Collection(arr.filter(predicate));
};
};
Which lets us do :
var ageFilter = filteredCollection(function(obj){ return obj.age < 30; });
//create a new age collection
var collection = new ageFilter([{name:'xy',age:24},{name:'y',age:35}]);
The other answer suggests _.filter
over the native Array.filter , this might be beneficial if you have to support old browsers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With