Angular 2 OrderBy Pipe

91 angular2-template angular-pipe angular

我无法将此代码从angualr1转换为angular2,任何帮助?

ng-repeat="todo in todos | orderBy: 'completed'"
Run Code Online (Sandbox Code Playgroud)

这就是我按照Thierry Templier的回答所做的事情:

html模板:

*ngFor="#todo of todos | sort"
Run Code Online (Sandbox Code Playgroud)

组件文件:

@Component({
    selector: 'my-app',
    templateUrl: "./app/todo-list.component.html",
    providers: [TodoService],
    pipes: [ TodosSortPipe ]

})
Run Code Online (Sandbox Code Playgroud)

管道文件:

import { Pipe } from "angular2/core";
import {Todo} from './todo';

@Pipe({
  name: "sort"
})
export class TodosSortPipe {
  transform(array: Array<Todo>, args: string): Array<Todo> {
    array.sort((a: any, b: any) => {
      if (a < b) {
        return -1;
      } else if (a > b) {
        return 1;
      } else {
        return 0;
      }
    });
    return array;
  }
}
Run Code Online (Sandbox Code Playgroud)

我确定错误在@Pipe中,我试图对Todos数组进行排序,由todo.completed属性排序.第一个todo.completed = false,而不是todo.complete = true.

老实说,我不太了解转换方法以及如何在该方法和sort方法中传递参数.

比如,什么是args:string参数?a和b,它们是什么?它们来自哪里?

Vit*_*zeu 69

有关完整的讨论,请参阅https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe.这句话是最相关的.基本上,对于应该大力缩小的大型应用程序,过滤和排序逻辑应该移动到组件本身.

"我们中的一些人可能并不在意这样做.这是我们的选择.但是Angular产品不应该阻止其他人积极地缩小.因此,Angular团队决定Angular中的所有东西都会安全地缩小.

Angular团队和许多经验丰富的Angular开发人员强烈建议您将过滤和排序逻辑移动到组件本身.组件可以公开filteredHeroes或sortedHeroes属性,并控制执行支持逻辑的时间和频率.您放入管道并在应用程序中共享的任何功能都可以写入过滤/排序服务并注入组件."

  • 你应该如何以一种"控制执行支持逻辑的时间和频率"的方式将逻辑"移入组件本身"?有没有很好的例子可供遵循? (6认同)
  • 仅供参考:该链接目标消失了。 (2认同)

Sal*_*Sal 69

我修改了@Thierry Templier的响应,因此管道可以在角度4中对自定义对象进行排序:

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

@Pipe({
  name: "sort"
})
export class ArraySortPipe  implements PipeTransform {
  transform(array: any, field: string): any[] {
    if (!Array.isArray(array)) {
      return;
    }
    array.sort((a: any, b: any) => {
      if (a[field] < b[field]) {
        return -1;
      } else if (a[field] > b[field]) {
        return 1;
      } else {
        return 0;
      }
    });
    return array;
  }
}
Run Code Online (Sandbox Code Playgroud)

并使用它:

*ngFor="let myObj of myArr | sort:'fieldName'"
Run Code Online (Sandbox Code Playgroud)

希望这有助于某人.


Thi*_*ier 38

您可以为此实现一个利用sort数组方法的自定义管道:

import { Pipe } from "angular2/core";

@Pipe({
  name: "sort"
})
export class ArraySortPipe {
  transform(array: Array<string>, args: string): Array<string> {
    array.sort((a: any, b: any) => {
      if (a < b) {
        return -1;
      } else if (a > b) {
        return 1;
      } else {
        return 0;
      }
    });
    return array;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后使用此管道,如下所述.不要忘记将管道指定到pipes组件的属性中:

@Component({
  (...)
  template: `
    <li *ngFor="list | sort"> (...) </li>
  `,
  pipes: [ ArraySortPipe ]
})
(...)
Run Code Online (Sandbox Code Playgroud)

它是具有字符串值的数组的简单示例,但您可以进行一些高级排序处理(基于对象数组的对象属性,基于排序参数,...).

以下是这方面的一个问题:https://plnkr.co/edit/WbzqDDOqN1oAhvqMkQRQ?p = preview .

希望它对你有帮助,蒂埃里

  • `pipes:[..]`声明不再有效(不再需要) (4认同)

Guo*_*jun 9

更新了OrderByPipe:修复了不排序的字符串.

创建一个OrderByPipe类:

import { Pipe, PipeTransform } from "@angular/core";
@Pipe( {
name: 'orderBy'
} )
export class OrderByPipe implements PipeTransform {
transform( array: Array<any>, orderField: string, orderType: boolean ): Array<string> {
    array.sort( ( a: any, b: any ) => {
        let ae = a[ orderField ];
        let be = b[ orderField ];
        if ( ae == undefined && be == undefined ) return 0;
        if ( ae == undefined && be != undefined ) return orderType ? 1 : -1;
        if ( ae != undefined && be == undefined ) return orderType ? -1 : 1;
        if ( ae == be ) return 0;
        return orderType ? (ae.toString().toLowerCase() > be.toString().toLowerCase() ? -1 : 1) : (be.toString().toLowerCase() > ae.toString().toLowerCase() ? -1 : 1);
    } );
    return array;
  }
}
Run Code Online (Sandbox Code Playgroud)

在你的控制器中:

@Component({
pipes: [OrderByPipe]
})
Run Code Online (Sandbox Code Playgroud)

或在你的

 declarations: [OrderByPipe]
Run Code Online (Sandbox Code Playgroud)

在你的HTML中:

<tr *ngFor="let obj of objects | orderBy : ObjFieldName: OrderByType">
Run Code Online (Sandbox Code Playgroud)

ObjFieldName:要排序的对象字段名称;

OrderByType:boolean; true:降序; 错误的:提升;


sup*_*ary 8

Angular没有开箱即用的orderBy过滤器,但如果我们决定需要一个,我们可以轻松制作一个.然而,我们需要注意一些与速度和缩小有关的警告.见下文.

一个简单的管道看起来像这样.

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

@Pipe({
  name: 'sort'
})
export class SortPipe implements PipeTransform {
  transform(ary: any, fn: Function = (a,b) => a > b ? 1 : -1): any {
    return ary.sort(fn)
  }
}
Run Code Online (Sandbox Code Playgroud)

这个管道接受一个sort函数(fn),并给它一个默认值,它将以合理的方式对一个基元数组进行排序.如果我们愿意,我们可以选择覆盖此排序功能.

它不接受属性名称作为字符串,因为属性名称可能会缩小.当我们缩小代码时它们会改变,但是缩小器不够智能,也不能缩小模板字符串中的值.

排序基元(数字和字符串)

我们可以使用它来使用默认比较器对数字或字符串数​​组进行排序:

import { Component } from '@angular/core';

@Component({
  selector: 'cat',
  template: `
    {{numbers | sort}}
    {{strings | sort}}
  `
})
export class CatComponent
  numbers:Array<number> = [1,7,5,6]
  stringsArray<string> = ['cats', 'hats', 'caveats']
}
Run Code Online (Sandbox Code Playgroud)

对对象数组进行排序

如果我们想对一组对象进行排序,我们可以给它一个比较器函数.

import { Component } from '@angular/core';

@Component({
  selector: 'cat',
  template: `
    {{cats | sort:byName}}
  `
})
export class CatComponent
  cats:Array<Cat> = [
    {name: "Missy"},
    {name: "Squoodles"},
    {name: "Madame Pompadomme"}
  ]
  byName(a,b) {
    return a.name > b.name ? 1 : -1
  }
}
Run Code Online (Sandbox Code Playgroud)

警告 - 纯粹与不纯净的管道

Angular 2具有纯净和不纯的管道概念.

纯管道使用对象标识优化变更检测.这意味着只有在输入对象更改标识时才会运行管道,例如,如果我们向数组添加新项目.它不会下降到物体.这意味着如果我们更改嵌套属性:this.cats[2].name = "Fluffy"例如,管道将不会重新运行.这有助于Angular快速发展.角管默认是纯的.

另一方面,不纯的管道将检查对象属性.这可能会使它慢得多.因为它不能保证管道功能将做什么(例如,它可能基于一天中的时间进行不同排序),每次异步事件发生时都会运行不纯的管道.如果阵列很大,这将大大减慢您的应用程序.

上面的管道是纯净的.这意味着它只会在数组中的对象不可变时运行.如果更改了cat,则必须用新的cat对象替换整个cat对象.

this.cats[2] = {name:"Tomy"}
Run Code Online (Sandbox Code Playgroud)

我们可以通过设置pure属性将上面的内容更改为不纯的管道:

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

@Pipe({
  name: 'sort',
  pure: false
})
export class SortPipe implements PipeTransform {
  transform(ary: any, fn: Function = (a,b) => a > b ? 1 : -1): any {
    return ary.sort(fn)
  }
}
Run Code Online (Sandbox Code Playgroud)

此管道将下降到对象中,但速度会变慢.谨慎使用.


Cor*_*haw 7

我已经创建了一个OrderBy管道,可以满足您的需求.它还支持能够对可枚举对象的多个列进行排序.

<li *ngFor="#todo in todos | orderBy : ['completed']">{{todo.name}} {{todo.completed}}</li>
Run Code Online (Sandbox Code Playgroud)

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

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

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


小智 5

推荐你使用 lodash 和 Angular,那么你的管道将是下一个:

import {Pipe, PipeTransform} from '@angular/core';
import * as _ from 'lodash'
@Pipe({
    name: 'orderBy'
})
export class OrderByPipe implements PipeTransform {

    transform(array: Array<any>, args?: any): any {
        return _.sortBy(array, [args]);
    }

}
Run Code Online (Sandbox Code Playgroud)

并在 html 中使用它,例如

*ngFor = "#todo of todos | orderBy:'completed'"
Run Code Online (Sandbox Code Playgroud)

并且不要忘记将 Pipe 添加到您的模块中

@NgModule({
    ...,
    declarations: [OrderByPipe, ...],
    ...
})
Run Code Online (Sandbox Code Playgroud)