Reputation: 15
I'm trying to create a search pipe for Angular 2. It should take a nested object and filter out the objects matching a search term. I have a basic version working but I have run into two problems.
Problem one is, that I now have to hard code key names or use what seems to me like a dirty hack with JSON.stringify
.
What is a more elegant way to filter the object, matching the term with any value exept a list of hardcoded ones like _id
and url
?
Problem two is, that if the string term
contains a space, I would like to split it and filter the obj
with both terms.
I can split it using terms = term.split(' ');
.
But how do I achive filtering with multiple terms?
My current code:
import {Pipe} from 'angular2/core';
@Pipe({
name: "search"
})
export class SearchPipe{
transform(obj: any, [term]) {
if (obj != null && term) {
return obj.filter( el => {
//var test = JSON.stringify(el);
//return test.toLowerCase().includes(term.toLowerCase()); //trows a compile error but seems to work.
return el.name.toLowerCase().includes(term.toLowerCase()) || el.place.toLowerCase().includes(term.toLowerCase()) || el.title.toLowerCase().includes(term.toLowerCase()) ;
});
} else {
return obj;
}
}
}
Expected input format:
[
{
"_id": "56ffbe512ba199777d51c6ae",
"picture": "http://placehold.it/36x36",
"name": "Melissa Reeves",
"company": "Orbixtar",
"place": "Greenwich, Belarus",
"title": "voluptate est ipsum",
"location": {
"lat": -78.926961,
"lng": 90.157653
},
"url": "http://lol.lol"
},
{
"_id": "56ffbe5119cf66e94b3800b4",
"picture": "http://placehold.it/36x36",
"name": "Chelsea Lindsay",
"company": "Squish",
"place": "Vowinckel, Belarus",
"title": "anim ea exercitation",
"location": {
"lat": 66.547582,
"lng": 162.720388
},
"url": "http://lol.lol"
}
]
If the term is "term1"
I would like it to return objects that contains "term1".
If on the otherhand term is "term1 term2 term3"
I would like for it to return all objects that contain all terms but not necessarily in that specific order.
As an exaple.
The term "Melissa"
should return the first object.
The term "Melissa Belarus"
should also return only the first object.
Even though the second object matches one of the keys.
Upvotes: 1
Views: 1909
Reputation: 24945
Try this (untested)
@Pipe({
name: "search"
})
export class SearchPipe{
transform(obj: any, [term]) {
if (obj != null && term) {
return obj.filter( el => {
var test = JSON.parse(JSON.stringify(el));
delete test['url'];
delete test['_id'];
var testString = JSON.stringify(test);
Object.keys(test).forEach(k => {
testString = testString.replace(k, '');
});
let terms = term.replace(/[\s]+/gm, " ").replace(/^[\s]|[\s]$/gm, "").split(' ');
let containCount = 0;
terms.forEach(t => {
if(testString.toLowerCase().indexOf(t.toLowerCase()) > -1)
{
++containCount;
}
});
return (containCount == terms.length);
});
} else {
return obj;
}
}
}
Upvotes: 1