zAPF
zAPF

Reputation: 15

How do I filter a javascript object when making a search pipe with angular 2?

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

Answers (1)

Ankit Singh
Ankit Singh

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

Related Questions