【问题标题】:Angular 11 : Filter List of Objects with List of Objects via PipeAngular 11:通过管道过滤对象列表和对象列表
【发布时间】:2021-09-26 09:39:06
【问题描述】:

我有一个 FormControl 和页面顶部,我可以在其中选择对象(我称之为“标签”)以过滤其下方的其他对象列表

例如,我会像这样选择两个对象:

[
    {
        "id": "4",
        "index": 4,
        "isActive": false,
        "picture": "https://via.placeholder.com/20x20",
        "name": "Interest 4"
    },
    {
        "id": "5",
        "index": 5,
        "isActive": false,
        "picture": "https://via.placeholder.com/20x20",
        "name": "Interest 5"
    }
]

然后尝试根据我的列表(我称之为“帖子”)对 post.postTags 属性进行过滤。

{
    "id": "RMjImD7Iy327rZOIBDfm",
    "createdDate": "07/17/2021 20:31:02",
    "posterId": "GI2Xs9YDV2UOh8M1J6zISvDt7wb2",
    "posterName": "example@email.com",
    "title": "New post with example email",
    "bodyText": "The quick, brown fox jumps over a lazy dog. DJs flock by when MTV ax quiz prog. Junk MTV quiz graced by fox whelps. Bawds jog, flick quartz, vex nymphs. Waltz, bad nymph, for quick jigs vex! Fox nymphs grab quick-jived waltz. Brick quiz whangs jumpy veldt fox. Bright vixens jump; dozy fowl quack. Quick wafting zephyrs vex bold Jim. Quick zephyrs blow, vexing daft Jim. Sex-charged fop blew my junk TV quiz. How quickly daft jumping zebras vex. Two driven jocks help fax my big quiz. Quick, Baz, get my woven flax jodhpurs! \"Now fax quiz Jack!\" my brave ghost pled.",
    "posterPicture": "../../../../../assets/images/user/wip-avatar.png",
    "postTags": [
        {
            "id": "4",
            "index": 4,
            "isActive": false,
            "picture": "https://via.placeholder.com/20x20",
            "name": "Interest 4"
        },
        {
            "picture": "https://via.placeholder.com/20x20",
            "id": "7",
            "name": "Interest 7",
            "isActive": false,
            "index": 7
        },
        {
            "id": "2",
            "name": "Interest 2",
            "isActive": false,
            "index": 2,
            "picture": "https://via.placeholder.com/20x20"
        }
    ]
}

列表 console.log 的屏幕截图

我当前的 filterPipe 看起来像这样:

但到目前为止无法弄清楚正确的逻辑。 我希望逻辑能够:

  • 过滤在帖子 postTags 字段中拥有任何(一个或多个)选定标签的帖子。
  • 如果没有选择标签,则返回原始列表。

【问题讨论】:

    标签: angular typescript list filter pipe


    【解决方案1】:

    如果你想在没有选择标签的情况下返回原始数组,你可以使用像这样的三元运算符。

    return term.length > 0 ? otherStuffHere : items
    

    如果otherStuffHereitems 可以为空或未定义,您可以通过添加一些空值合并来改善这一点,如果需要返回默认值。

    return (term.length > 0 ? otherStuffHere : items) ?? []
    

    这基本上意味着:如果(term ? otherStuffHere : items) 为空或未定义,请改用[]。 (check this out) 仅当您使用 angular 12 或更大时。否则,请使用|| 而不是??

    所以你有了问题第二部分的答案 (Return original list if no tags are selected.)


    至于你问题的第一部分,事情变得更有趣了。

    您基本上想要的是检查是否至少有一个条件为真(该项目的至少一个标签在标签列表中)以使一个项目在您的过滤列表中。

    Javascript 在数组原型中实现了some() 方法,只做你想做的事。 docs here.

    在你的情况下,过滤器方法应该是这样的:

    items.filter(item => 
        item.postTag.some(pTag => term.some(t => t.id === pTag.id))
    );
    

    另一种方法是这样

    items.filter(item => 
        item.postTag.some(pTag => term.map(t => t.id).include(pTag.id))
    );
    

    您可以将term.map(t => t.id) 保留在一个变量中,将第二个代码示例更改为:

    const termIds = term.map(t => t.id);
    
    items.filter(item => 
        item.postTag.some(pTag => termIds.include(pTag.id))
    );
    

    请注意,这非常重要。我的箭头函数不包含返回,因为我不使用大括号。 Some reading here。这也是您在代码中遇到的一个问题。

    items.filter(item => {
        item.postTags.filter(tag => tag === term);
    });
    

    总是会返回[],一个空数组。

    代码中的另一个问题是tag === term,它比较对象的引用,而不是它们的值。这就是我比较他们 id 上的项目的原因。


    因此,作为您问题的最终答案,您的 transofrm 方法(如果我是正确的)应该如下所示:

    transform(items: any[], term: any[]): any[] {
        return (term.length > 0 ?
            items.filter(item => 
                item.postTag.some(pTag => term.map(t => t.id).include(pTag.id))
            ) :
            items ) ?? [];
    }
    

    【讨论】:

    • 感谢 Paul 的快速回复。您的解决方案有效:)
    猜你喜欢
    • 2017-06-14
    • 2015-03-24
    • 2022-01-12
    • 1970-01-01
    • 2011-01-10
    • 2013-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多