带有对象数组的 Angular2 排序管道



如何在 angular2 中制作带有对象数组的排序管道

原始问题:

有一个待办事项列表(Todo[ ](,每次进行一些更改时,我都想对其进行排序。我希望完成的待办事项显示在列表底部。Todo 对象有一个名为 .done 的属性,它存储一个布尔值,它会告诉我们 todo 是否完成。

创建管道:

在 Angular2 中,"OrderBy"管道不存在。所以我们必须构建它:

import { Pipe, PipeTransform } from "angular2/core";
//Todo is the interface for our todo object
import {Todo} from './todo';
@Pipe({
  name: "sort",
  //set to false so it will always update, read below the code.
  pure: false
})
export class TodosSortPipe implements PipeTransform {
  transform(array: Todo[], args: any): Todo[] {
    //watch the console to see how many times you pipe is called
    console.log("calling pipe");
    /* javascript is async, so could be that the pipe is called before
    that the todos list is created, in this case we do nothing
    returning the array as it is */
    if (isBlank(array)) return null;
    array.sort((a, b) => {
      if (a.completed < b.completed) {
        return -1;
      //.completed because we want to sort the list by completed property
      } else if (a.completed > b.completed) {
        return 1;
      } else {
        return 0;
      }
    });
    return array;
  }
}

如果您不了解排序方法,请检查MDN:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

管道完成,让我们转到组件。

创建组件:

AppComponent 类创建一个名为 Todo 的待办事项数组,从带有服务的模拟中获取对象。

import {Component, OnInit} from 'angular2/core';
import {Todo} from './todo';
import {TodoService} from './todo.service';
import {TodosSortPipe} from './sort-pipe.component'
@Component({
    //name of the html element
    selector: 'my-app',
    //view of the selector,  " ` " is alt + 9
    templateUrl: "./app/todo-list.component.html",
    providers: [TodoService],
    pipes: [ TodosSortPipe ]
})
export class AppComponent implements OnInit{
    public todos: Todo[];
    public edited = false;
    public changes = 0;
    //creating an istance of todoService
    constructor(private _todoService: TodoService) { };
    //getting the todos list from the service
    getTodos() {
        this._todoService.getTodos().then(todos => this.todos = todos);
    }
   (...)
   editTodo(todo: Todo): void {
        //slice is very important, read below the code
        this.todos = this.todos.slice();
        this.saveTodos();
    }
}

模板实现

这是管道调用:

<li *ngFor="#todo of todos | sort; #i=index">
 (...)
</li>

演示:

有关所有代码的完整示例:https://plnkr.co/edit/VICRMVNhqdqK9V4rJZYm?p=preview在github上观看:https://github.com/AndreaMiotto/Angular2-TodoApp

管道不纯

默认情况下,管道

仅在管道输入参数更改时更改,而不会在数据更改时更改。将纯设置为假,您将使其"不纯",因此您的管道将始终更新。

也许值todos在开始时null,因为它是使用 HTTP 异步加载的。

为了防止出现此类用例,您可以在管道中添加以下内容:

@Pipe({
  name: "sort"
})
export class TodosSortPipe implements PipeTransform {
  transform(array: Todo[], args: any): Todo[] {
    if (array == null) {
      return null;
    }
    (...)
  }
}

然后将接收值todos,并且将使用此非空值再次调用管道的transform方法...

此外,您的<li>标签似乎没有结束。组件模板中必须包含有效的 HTML。我不知道它是完整的代码还是截断的代码......

希望对您有所帮助,蒂埃里

我创建了一个支持单维和多维数组的 OrderBy 管道。它还支持能够对多维数组的多列进行排序。

<li *ngFor="#todo of todos | orderBy : ['completed']; #i=index">
    {{i}}) {{todo.name}} - {{todo.completed}}
</li>

此管道确实允许在呈现页面后向数组添加更多项,并且仍然使用新项动态对数组进行排序。

我在这里写了一篇关于这个过程的文章。

这是一个工作演示:http://fuelinteractive.github.io/fuel-ui/#/pipe/orderby 和 https://plnkr.co/edit/DHLVc0?p=info

您需要更改 html 模板,以便管道可以容纳异步代码。

更改此行:

<li *ngFor="#todo of todos | sort; #i=index">
   (...)
</li>

对此:

<li *ngFor="#todo of todos | async | sort; #i=index">
   (...)
</li>

我把你的管道代码复制到这个 Plunker 中:

https://plnkr.co/edit/RBpZilgxIyRDLwktNZN1?p=preview

最新更新