带对象数组的Angular2排序管道

时间:2016-02-03 11:46:12

标签: sorting pipe angular

如何使用对象数组

在angular2中创建排序管道

原始问题:

我有一个TODO列表,(Todo []),我想在每次做出一些更改时对其进行排序。我希望完成的待办事项显示在列表的底部。 Todo对象有一个名为.completed的属性,它存储一个布尔值,它会告诉我们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类创建一个名为Todos的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

Pipe Unpure

管道仅在管道输入参数更改时默认更改,而不是在数据更改时更改。 将Pure设置为false,您将使其成为&#34; noture&#34;因此管道将始终更新。

3 个答案:

答案 0 :(得分:1)

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放入组件模板中。我不知道它是完整的代码还是截断的代码......

希望它可以帮到你, 亨利

答案 1 :(得分:1)

您需要更改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

答案 2 :(得分:1)

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

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

此管道允许在呈现页面后向阵列添加更多项目,并仍然动态地对数组中的新项目进行排序。

我有write up on the process here

这是一个有效的演示:http://fuelinteractive.github.io/fuel-ui/#/pipe/orderbyhttps://plnkr.co/edit/DHLVc0?p=info