I got a JSON name collection like this:
[{
"name":"Jim",
"prize":"Nokia Mobile"
},
{
"name":"Marry",
"prize":"iPhone"
},
{
"name":"Alice",
"prize":"iPad"
}
]
now I'd like to filter this JSON by a string: var data= "m";
so, this is what I've done:
var data= "m";
collection = _.filter(collection,function(c){
return _.any(c,function(k){
return k.name.toLowerCase().indexOf(data.toLowerCase()) != -1;
});
});
so, in this case, collection return elements which has m in their name.
However, I've got "Cannot call method 'toLowerCase' of undefined".
I tried to put an alert "alert(c.name);" before the last return, and it's return "undefined". It shouldn't be, isn't it?
what need I change to fix this?
See this http://underscorejs.org/#filter
Try this:
var data= "m";
collection = _.filter(collection,function(myObject){
return myObject.name.toLowerCase().indexOf(data.toLowerCase()) != -1;
});
Hope it helps.
EDIT: Seems like your core problem here is misunderstanding of the input and output of the underscore functions any
and filter
. I realised after writing my answer I'm not really even sure what your code should be doing - but reading the docs for filter and any, along with the points below and in the rest of the answers, will surely help you solve your problem in the right way.
You shouldn't use _.any
here - that tells you if any element in an array passes a test (implemented as a function which you pass to it). You shouldn't use _.any
at all here, if you need to test name
, just test name
directly on the object.
_.filter
is all you want - this returns a new array containing all elements from the passed in array which pass the test (likewise, implemented in the function you pass). In this case, all the objects where the name
string contains the data
string. See the code below for clarity on how each element
from collection
is passed and used inside the test function passed to _.filter
.
Another point - if you can't guarantee the integrity of the data coming into collection
, to avoid errors you should check first if the name property is defined - if it's not, fail the test.
var collection = [
{
"name":"Jim",
"prize":"Nokia Mobile"
},
{
"name":"Marry",
"prize":"iPhone"
},
{
"name":"Alice",
"prize":"iPad"
}];
var data = 'm';
collection = _.filter(collection,function(element){
return element.name && element.name.toLowerCase().indexOf(data.toLowerCase()) != -1;
});
Also, you don't need to lowercase data
here - you know it's lowercase - unless that data = 'm'
declaration is just a placeholder for some other, unpredictable, input :-)
You have made it too complicated, simply:
var data = [{
"name":"Jim",
"prize":"Nokia Mobile"
},
{
"name":"Marry",
"prize":"iPhone"
},
{
"name":"Alice",
"prize":"iPad"
}
];
var fiterTerm = "m";
var collection = _.filter(data, function(item){
return item.name.toLowerCase().indexOf(fiterTerm.toLowerCase()) != -1;
});
console.log(collection);
You need to put quotes round your values. And then: _any function with an object as collection passes 2 parameters to the callback function rather than one.
_.any({ name:"Jim", price: "Phone" },function(value,key) {
alert(value+" "+key)
});
Will give you alerts with "Jim name" and then "Phone price". so you do not have to use the .name property on the value parameter.
True your JSON in the example isn't valid, the strings do need quotes as meager pointed out.
If it where valid and you wanted to filter the array using underscore I would use something like this
http://underscorejs.org/#filter
var data = 'm';
var filteredcollection = _.filter(collection, function(item){
return item.name.toLowerCase().indexOf(data) != -1;
});
Hope this helps