angular 2 添加新项目到列表时,自定义管道不重新排序列表

angular 2 when adding new item to list, custom pipe not reordering list

我实现了一个 orderby 管道,它在 DOM 加载时工作正常。但是当我向列表中添加一个新项目时,我的管道没有被激活,并且已添加到列表中的新项目不是顺序的 - 但添加到列表中的最后一个位置。

管道:

import { PipeTransform, Pipe } from '@angular/core';

import { ITeam } from './team';

@Pipe({
    name: "LeagueFilter"
})

export class LeagueFilterPipe implements PipeTransform {
    transform(value: any[], filterBy: string): any[] {
        filterBy = filterBy ? filterBy.toLocaleLowerCase() : null

        for (let i = 0; i < value.length - 1; i++) {
            for (let j = 0; j < value.length - 1; j++) {
                if (value[j][filterBy] < value[j + 1][filterBy]) {
                    let temp = value[j]
                    value[j] = value[j + 1]
                    value[j + 1] = temp
                }
            }
        }
        return value;
    }
}

Html:

<div class="container">
    <div class="row">
        <div class="col-sm-offset-1 col-sm-4">
            <h2>
                {{leagueTable}}
            </h2>

            <table class="table table-responsive">
                <thead>
                    <tr>
                        <th>#</th>
                        <th>Team</th>
                        <th>Points</th>
                    </tr>
                </thead>
                <tbody>
                    <tr *ngFor="let team of teams | LeagueFilter:'points'; let i = index">
                        <td>{{i+1}}</td>
                        <td>{{team.name}}</td>
                        <td>{{team.points}}</td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
            <div class="row">
            <fieldset class="col-sm-offset-1 col-lg-3">
                <legend>Add Team</legend>
                <label for="name">Name&nbsp;&nbsp;</label>
                <input type="text" name="" value="" [(ngModel)] = "newTeam.name" />
                <br/>
                <label for="name">Points</label>
                <input type="text" name="" value="" [(ngModel)] = "newTeam.points" />
                <button type="submit" (click)="addTeam()">Add</button>
            </fieldset>
        </div>
</div>

组件:

import { Component } from '@angular/core';
import { ITeam } from './team';

@Component({
    selector: 'league-list',
    moduleId:module.id,
    templateUrl: 'league-list.component.html',
    styleUrls: ['league-list.component.css']
})
export class LeagueListComponent {
    leagueTable: string = "La Liga"
    teams: ITeam[] = [
        { name: "Barcelona", points: 84 },
        { name: "Real Madrid", points: 85 },
        { name: "Valencia", points: 78 },
        { name: "Sevilla", points: 80 },
        { name: "Villareal", points: 62 },
    ]
    newTeam:ITeam = { name:"", points:null };
    addTeam():void{
        this.teams.push(this.newTeam)

    }
}

管道仅在值更改时由 Angular 执行(或管道参数,如果有的话)

您的示例中没有参数,值也没有改变。 Angulars 变化检测不检查数组的内容,仅当引用发生变化时(到不同的数组实例,对象相同。顺便说一句。)

你能做什么

  • 使管道不纯净
@Pipe({
    name: "LeagueFilter",
    pure: false
})

这样管道将在每次更改检测时执行 运行,这可能会变得昂贵。管道应该注意不要做不必要的工作,例如缓存结果并使用 IterableDiffer(就像在 NgFor 中使用的那样)来显式检查数组的变化。

  • 修改后创建数组副本
this.teams.push(this.newTeam);
this.teams = this.teams.slice();

如果数组很大并且经常发生变化,这也会变得昂贵

  • 引入一个人工管道参数
this.teams.push(this.newTeam);
this.teamsChanged++;
transform(value: any[], filterBy: string, teamsChanged:any /*ignored*/): any[] {
<tr *ngFor="let team of teams | LeagueFilter:'points':teamsChanged; let i = index">

此附加参数将导致每次修改 teamsChanged 时调用管道。