我有一个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
管道仅在管道输入参数更改时默认更改,而不是在数据更改时更改。 将Pure设置为false,您将使其成为&#34; noture&#34;因此管道将始终更新。
答案 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中:
答案 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/orderby和https://plnkr.co/edit/DHLVc0?p=info