Angular 6 multi field filter

2019-08-16 17:23发布

I'm currently working on angular 6 app. I have a huge list of articles and want to do some filtering upon it. Right now it works real-time, there is no button to submit your filter options, it all happens as you type. I figure a way, but it has still some issues I can fix, but doesn't like the way I did it. I'm sure, there has to be something more elegant.

For better imagination those articles have category, title, author, tags. I am able to filter them according to category lets say... but I want to do some kind of filtering.

Example: Filter all articles from category 'sports', then filter all articles having substring 'goal' in title from that already filtered array, then filter those whos author is 'john' and then filter all with tag 'hockey'.

I ended up with huge amount of IF statements, which is not the right approach I would say. Can you please recommend me some better way to do this?

1条回答
神经病院院长
2楼-- · 2019-08-16 18:08

This is what you could do to create a multifilter without many if statements.

Step one: Create an object that performs various comparison functions:

let compareFunctions = {
    equal: function(a,b) {
        return a === b;
    },
    in: function(a,b){
        return a.indexOf(b) !== -1
    }
}

Step two: Create a function that has the following parameters:

  1. key - The key of the field of your record you want to filter.
  2. value - The value you want to filter by
  3. compareFn - The comparison function to be used for this field

This function returns a function that executes the condition.

function condition(key, value, comparFn = compareFunctions.equal) {
    return function(data) {
        return comparFn(data[key],value);
    }
}

Step three: Create an array with "condition" functions representing your filter values:

let filterArray = [
    condition('category', 'sports'),
    condition('title', 'goal', compareFunctions.in),
    condition('author', 'john'),
    condition('tags', 'hokey', compareFunctions.in),
]

Step four: Filter your record by calling your array of conditions functions for each entry and evaluating the result of each condition:

let result = dataset.filter(y => {
    let resolved = filterArray.map(x => x(y))
    return resolved.every(x => x === true);
})

Full example code:

let compareFunctions = {
    equal: function(a,b) {
        return a === b;
    },
    in: function(a,b){
        return a.indexOf(b) !== -1
    }
}

function condition(key, value, comparFn = compareFunctions.equal) {
    return function(data) {
        return comparFn(data[key],value);
    }
}

let dataset = [
    {
        category: "sports",
        title: "goal goal goal",
        author: "john",
        tags: ["hokey", "ice-hokey"]
    },
    {
        category: "news",
        title: "bla bla",
        author: "Timo",
        tags: ["news"]
    },
    {
        category: "news",
        title: "blub blub",
        author: "alex",
        tags: ["hokey", "ice-hokey"]
    },
    {
        category: "sports",
        title: "Kölner Haie bla bla",
        author: "Timo",
        tags: ["hokey", "ice-hokey"]
    }
]

let filterArray = [
    condition('category', 'sports'),
    condition('title', 'goal', compareFunctions.in),
    condition('author', 'john'),
    condition('tags', 'hokey', compareFunctions.in),
]

//console.log(filterArray)

let result = dataset.filter(y => {
    let resolved = filterArray.map(x => x(y))
    return resolved.every(x => x === true);
})

console.log(result)
查看更多
登录 后发表回答