【问题标题】:Filter array in template Angular2模板Angular2中的过滤器数组
【发布时间】:2017-05-31 04:59:30
【问题描述】:

我正在尝试制作简单的模板,但遇到了小问题。我想在我的待办事项列表中打印未完成任务的数量,但无法在模板中过滤它们。我有这个:

<span class="todo-count"><strong>{{todos.length}}</strong> left</span>

但我想过滤此待办事项以仅计算状态已完成设置为 false 的待办事项:

<span class="todo-count"><strong>{{todos.filter(t => !t.complete).length}}</strong> left</span>

但这不起作用。我怎样才能做到这一点?

【问题讨论】:

    标签: angular filtering angular2-filtering


    【解决方案1】:

    我编写了一个简单的 Angular 管道,它允许您将对象或回调函数作为过滤器传递。

    请看下面的例子:

    home.component.ts

    @Component({
      selector: 'app-home',
      templateUrl: './home.component.html',
    })
    export class HomeComponent {
      array = [
        {type: 'log', name: 'Log 1'},
        {type: 'log', name: 'Log 2'},
        {type: 'log', name: 'Log 3'},
        {type: 'log', name: 'Log 4'},
        {type: 'event', name: 'Event 1'},
        {type: 'event', name: 'Event 2'},
        {type: 'event', name: 'Event 3'},
        {type: 'event', name: 'Event 4'}
      ];
    
      complexFilter = (item, index) => item.type === 'event' && index % 2 !== 0;
    }
    

    home.component.html

    <h1>All items</h1>
    <div *ngFor="let item of array">
      {{item.name}}
    </div>
    
    <h1>Only logs</h1>
    <div *ngFor="let item of array | dynamicFilter: { type: 'log'}">
    {{item.name}}
    </div>
    
    <h1>Complex filter</h1>
    <div *ngFor="let item of array | dynamicFilter: complexFilter">
      {{item.name}}
    </div>
    

    输出将是

    All items
    Log 1
    Log 2
    Log 3
    Log 4
    Event 1
    Event 2
    Event 3
    Event 4
       
    Only logs
    Log 1
    Log 2
    Log 3
    Log 4
    
    Complex filter
    Event 2
    Event 4
    

    如您所见,您可以在模板中提供简单的过滤器对象或复杂的过滤器回调函数。

    你可以找到dynamicFilter管道here的源代码。

    【讨论】:

    • 伟大的管道解决方案 Mir Milad!!!
    【解决方案2】:

    最正确的方法是使用 Angular 管道:

    模板

    <span class="todo-count"><strong>{{ (todos | filter : filterFunction).length }}</strong> left</span>
    

    管道

    import {
        Injector,
        Pipe,
        PipeTransform
    } from '@angular/core';
    @Pipe({
      name: 'filter'
    })
    export class FilterPipe implements PipeTransform {
    
        public constructor(private readonly injector: Injector) {
        }
    
        transform(value: Array<any>, callback: any): any {
            return value.filter(callback);
        }
    }
    

    组件控制器中的filterFunction

    filterFunction(t): boolean {
      return !t.complete;
    }
    

    你可以在Don't Use Functions Inside Angular Templates and What to Use Instead 看到为什么不在 Angular 模板中使用方法。简而言之,这是因为 Angular 中的变化检测机制。 Angular 在运行函数函数之前无法检测函数的结果是否改变。

    需要考虑的是,即使我们有相同的输入数据,该函数也会运行

    【讨论】:

    • angular.io/guide/pipes#no-filter-pipe 也许我错了(我不是专家),但角度文档不是说“最正确的方法”是在组件本身中做到这一点?据我了解,该管道仍将在大多数 ChangeDetection 周期中执行...
    • 是的,但有时您需要在模板上执行此操作。
    • 如果是纯管道,则管道在属性更改时执行
    • 是的。但是请注意,当管道的参数之一是数组时,您需要跳过更多的箍。如果您只是推入阵列,它不会检测到变化。您将需要重新分配整个数组。上面的链接不再有效,但这解释了它angular.io/guide/…
    • 很好的解释。阅读以下链接也会很有用。 medium.com/showpad-engineering/…
    【解决方案3】:

    让它成为一个应用你标准的函数:

    <span class="todo-count"><strong>{{filterValue()}}</strong> left</span>
    

    在你的控制器中

          filterValue() : number 
          { 
              return todos.filter(...);
           }
    

    【讨论】:

    • 谢谢,我已经这样做了。如果可以直接在模板中进行操作,我只是在犹豫。可能不会。
    • 以这种方式调用模板中的方法是一种不好的做法,因为 angular 不会注意到值的变化,如果您将 console.log(...) 添加到 filterValue 函数,您会注意到因为该函数被多次调用,而不是一两次
    【解决方案4】:

    我使用 lodash 来解决这类问题。

    你可以这样安装... https://medium.com/@gtsopour/importing-lodash-into-angular-2-typescript-application-94590365f46d#.bsepr3agd

    然后使用它的过滤器函数过滤视图中的数组... https://lodash.com/docs/4.17.4#filter

    【讨论】:

    • 只要你能在本地完成简单任务就使用另一个库是你能做的最糟糕的事情之一
    猜你喜欢
    • 2017-04-18
    • 2016-03-28
    • 2021-03-31
    • 1970-01-01
    • 2023-03-14
    • 2014-10-20
    • 2014-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多