Dan Andreasson
Dan Andreasson

Reputation: 16202

Advanced AngularJS live Search

I have the following data

persons = [
 {
   "age":20,
   "parameter1":94,
   "name":"Foobarin"
 },
 {
   "age":33,
   "parameter1":49,
   "name":"Johan"
 }
]

I want to create an advanced live search which recognizes patterns. An examples could be "foo a20 p94" which would get me the first object. a20 - Search where age is 20 p94 - Search where parameter1 is 94 and then if there is any other text which does not have any set prefix then test that against the name value.

All the values (except name which is case-insensitive) is of type integer. I want to limit the prefixes to predefined such as a, p and not age20. The data-sets is around 400.

I've created a basic live search which searches all variables in the object, but now I do not know where to continue. Any ideas?

Upvotes: 1

Views: 898

Answers (1)

Emissary
Emissary

Reputation: 10138

It's not foolproof but as a first-pass this is what I'd start with, I'll try to talk through it in pseudo.

First declare a propertyMatrix, a simple object-map which can point "prefixes" to the actual property names which exist within person. The searchPersons function accepts a single string (query) value and consists of two main parts:

  • The query string is split on whitespace characters into an array of "tokens". Each token is also an array of exactly 2 length, containing each token name and token value. At this stage it attempts find the predetermined prefix - if no such entry exists the token name: name is assumed.

  • A filter is then applied to the persons array. For each person we iterate over the tokens array and make an appropriate comparison, if any single check fails we return false (thus excluding the person from the results).

var propertyMatrix = {
        'a': 'age',
        'p': 'parameter1'
}, 
searchPersons = function(query){

    var tokens = query.split(/\s+/).map(function(t){
        t = t.toLowerCase();
        var i = t.match(/\d+$/), p;
        if(i && i.length) {
            p = t.substring(0, t.indexOf(i));
            if(p in propertyMatrix)
                return [propertyMatrix[p], parseInt(i, 10)];
        }
        return ['name', t];
    }), 

    result = persons.filter(function(p){
        for(var i=0, l=tokens.length; i<l; i++){
            var token = tokens[i][0], value = tokens[i][1];
            if(!(token in p)) return false;
            if(token === 'name'){
                if(p.name.toLowerCase().indexOf(value)<0) return false;
            } else if(p[token] !== value) return false;
        }
        return true;
    });

    return result;

};

fiddle

Upvotes: 1

Related Questions