我无法将此代码从angualr1转换为angular2,有什么帮助吗?
ng-repeat="todo in todos | orderBy: 'completed'"
这是我在Thierry Templier回答后所做的事情:
html模板:
*ngFor="#todo of todos | sort"
组件文件:
@Component({
selector: 'my-app',
templateUrl: "./app/todo-list.component.html",
providers: [TodoService],
pipes: [ TodosSortPipe ]
})
管道文件:
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;
}
}
我确定错误在@Pipe中,即时尝试对Todos数组进行排序,由todo.completed属性排序。首先是todo.completed = false,而不是todo.complete = true。
老实说,我不太了解转换方法以及如何在该方法和sort方法中传递参数。
比如,什么是args:string参数? a和b,它们是什么?他们来自哪里?
答案 0 :(得分:64)
有关完整讨论,请参阅https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe。这句话是最相关的。 基本上,对于应该大力缩小的大型应用程序,过滤和排序逻辑应该移动到组件本身。
&#34;我们中的一些人可能并不关心如何积极地缩小这一点。那是我们的 选择。但Angular产品不应该阻止其他人 积极地缩小。因此,Angular团队决定这样做 Angular中发布的所有东西都会安全缩小。
Angular团队和许多经验丰富的Angular开发人员 建议您将过滤和排序逻辑移动到组件中 本身。该组件可以公开filteredHeroes或sortedHeroes 属性并控制执行时间和频率 支持逻辑。您将放入管道的任何功能 并且可以在过滤/排序中编写并在整个应用程序中共享 服务并注入组件。&#34;
答案 1 :(得分:60)
我修改了@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;
}
}
使用它:
*ngFor="let myObj of myArr | sort:'fieldName'"
希望这有助于某人。
答案 2 :(得分:35)
您可以为此实现一个利用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;
}
}
然后如下所述使用此管道。不要忘记将管道指定到组件的pipes
属性中:
@Component({
(...)
template: `
<li *ngFor="list | sort"> (...) </li>
`,
pipes: [ ArraySortPipe ]
})
(...)
这是带有字符串值的数组的简单示例,但您可以进行一些高级排序处理(基于对象数组的对象属性,基于排序参数,...)。
以下是这方面的一个问题:https://plnkr.co/edit/WbzqDDOqN1oAhvqMkQRQ?p=preview。
希望它可以帮到你, 亨利
答案 3 :(得分:8)
更新了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;
}
}
在您的控制器中:
@Component({
pipes: [OrderByPipe]
})
或在您的
中 declarations: [OrderByPipe]
你的HTML中的:
<tr *ngFor="let obj of objects | orderBy : ObjFieldName: OrderByType">
ObjFieldName:您要排序的对象字段名称;
OrderByType:boolean; true:降序; false:升序;
答案 4 :(得分: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)
}
}
此管道接受排序函数(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']
}
如果我们想对一组对象进行排序,我们可以给它一个比较器函数。
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
}
}
Angular 2具有纯净和不纯净管道的概念。
纯管道使用对象标识优化更改检测。这意味着只有在输入对象更改标识时才会运行管道,例如,如果我们向数组添加新项目。它不会下降到物体。这意味着,如果我们更改嵌套属性:this.cats[2].name = "Fluffy"
,则管道将不会重新运行。这有助于Angular快速发展。角度管道默认是纯净的。
另一方面,不纯的管道将检查对象属性。这可能会使它慢得多。因为它不能保证管道功能将做什么(例如,它可能根据一天中的时间进行不同排序),每次发生异步事件时都会运行一个不纯的管道。这将如果数组很大,请大大减慢你的应用程序。
上面的管道是纯净的。这意味着它只会在数组中的对象不可变时运行。如果更改了猫,则必须用新的猫对象替换整个猫对象。
this.cats[2] = {name:"Tomy"}
我们可以通过设置纯属性来将上面的内容更改为不纯的管道:
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)
}
}
此管道将下降到对象中,但速度会变慢。请谨慎使用。
答案 5 :(得分:7)
我已经创建了一个可以满足您需求的OrderBy管道。它还支持能够对可枚举对象的多个列进行排序。
<li *ngFor="#todo in todos | orderBy : ['completed']">{{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
答案 6 :(得分:3)
这适用于您传递给它的任何字段。 (重要:它只会按字母顺序排序,因此如果您传递日期,则会将其命名为字母而不是日期)
/*
* Example use
* Basic Array of single type: *ngFor="let todo of todoService.todos | orderBy : '-'"
* Multidimensional Array Sort on single column: *ngFor="let todo of todoService.todos | orderBy : ['-status']"
* Multidimensional Array Sort on multiple columns: *ngFor="let todo of todoService.todos | orderBy : ['status', '-title']"
*/
import {Pipe, PipeTransform} from "@angular/core";
@Pipe({name: "orderBy", pure: false})
export class OrderByPipe implements PipeTransform {
value: string[] = [];
static _orderByComparator(a: any, b: any): number {
if (a === null || typeof a === "undefined") { a = 0; }
if (b === null || typeof b === "undefined") { b = 0; }
if (
(isNaN(parseFloat(a)) ||
!isFinite(a)) ||
(isNaN(parseFloat(b)) || !isFinite(b))
) {
// Isn"t a number so lowercase the string to properly compare
a = a.toString();
b = b.toString();
if (a.toLowerCase() < b.toLowerCase()) { return -1; }
if (a.toLowerCase() > b.toLowerCase()) { return 1; }
} else {
// Parse strings as numbers to compare properly
if (parseFloat(a) < parseFloat(b)) { return -1; }
if (parseFloat(a) > parseFloat(b)) { return 1; }
}
return 0; // equal each other
}
public transform(input: any, config = "+"): any {
if (!input) { return input; }
// make a copy of the input"s reference
this.value = [...input];
let value = this.value;
if (!Array.isArray(value)) { return value; }
if (!Array.isArray(config) || (Array.isArray(config) && config.length === 1)) {
let propertyToCheck: string = !Array.isArray(config) ? config : config[0];
let desc = propertyToCheck.substr(0, 1) === "-";
// Basic array
if (!propertyToCheck || propertyToCheck === "-" || propertyToCheck === "+") {
return !desc ? value.sort() : value.sort().reverse();
} else {
let property: string = propertyToCheck.substr(0, 1) === "+" || propertyToCheck.substr(0, 1) === "-"
? propertyToCheck.substr(1)
: propertyToCheck;
return value.sort(function(a: any, b: any) {
let aValue = a[property];
let bValue = b[property];
let propertySplit = property.split(".");
if (typeof aValue === "undefined" && typeof bValue === "undefined" && propertySplit.length > 1) {
aValue = a;
bValue = b;
for (let j = 0; j < propertySplit.length; j++) {
aValue = aValue[propertySplit[j]];
bValue = bValue[propertySplit[j]];
}
}
return !desc
? OrderByPipe._orderByComparator(aValue, bValue)
: -OrderByPipe._orderByComparator(aValue, bValue);
});
}
} else {
// Loop over property of the array in order and sort
return value.sort(function(a: any, b: any) {
for (let i = 0; i < config.length; i++) {
let desc = config[i].substr(0, 1) === "-";
let property = config[i].substr(0, 1) === "+" || config[i].substr(0, 1) === "-"
? config[i].substr(1)
: config[i];
let aValue = a[property];
let bValue = b[property];
let propertySplit = property.split(".");
if (typeof aValue === "undefined" && typeof bValue === "undefined" && propertySplit.length > 1) {
aValue = a;
bValue = b;
for (let j = 0; j < propertySplit.length; j++) {
aValue = aValue[propertySplit[j]];
bValue = bValue[propertySplit[j]];
}
}
let comparison = !desc
? OrderByPipe._orderByComparator(aValue, bValue)
: -OrderByPipe._orderByComparator(aValue, bValue);
// Don"t return 0 yet in case of needing to sort by next property
if (comparison !== 0) { return comparison; }
}
return 0; // equal each other
});
}
}
}
答案 7 :(得分:3)
建议您使用带角度的lodash,然后管道将是下一个:
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]);
}
}
并在html中使用
*ngFor = "#todo of todos | orderBy:'completed'"
并且不要忘记将管道添加到您的模块
@NgModule({
...,
declarations: [OrderByPipe, ...],
...
})
答案 8 :(得分:3)
这是 angular 4 中AngularJs orderby 管道的良好替代品。简单易用。
这是github URL以获取更多信息 https://github.com/VadimDez/ngx-order-pipe
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'orderBy'
})
export class OrderPipe implements PipeTransform {
transform(value: any | any[], expression?: any, reverse?: boolean): any {
if (!value) {
return value;
}
const isArray = value instanceof Array;
if (isArray) {
return this.sortArray(value, expression, reverse);
}
if (typeof value === 'object') {
return this.transformObject(value, expression, reverse);
}
return value;
}
/**
* Sort array
*
* @param value
* @param expression
* @param reverse
* @returns {any[]}
*/
private sortArray(value: any[], expression?: any, reverse?: boolean): any[] {
const isDeepLink = expression && expression.indexOf('.') !== -1;
if (isDeepLink) {
expression = OrderPipe.parseExpression(expression);
}
let array: any[] = value.sort((a: any, b: any): number => {
if (!expression) {
return a > b ? 1 : -1;
}
if (!isDeepLink) {
return a[expression] > b[expression] ? 1 : -1;
}
return OrderPipe.getValue(a, expression) > OrderPipe.getValue(b, expression) ? 1 : -1;
});
if (reverse) {
return array.reverse();
}
return array;
}
/**
* Transform Object
*
* @param value
* @param expression
* @param reverse
* @returns {any[]}
*/
private transformObject(value: any | any[], expression?: any, reverse?: boolean): any {
let parsedExpression = OrderPipe.parseExpression(expression);
let lastPredicate = parsedExpression.pop();
let oldValue = OrderPipe.getValue(value, parsedExpression);
if (!(oldValue instanceof Array)) {
parsedExpression.push(lastPredicate);
lastPredicate = null;
oldValue = OrderPipe.getValue(value, parsedExpression);
}
if (!oldValue) {
return value;
}
const newValue = this.transform(oldValue, lastPredicate, reverse);
OrderPipe.setValue(value, newValue, parsedExpression);
return value;
}
/**
* Parse expression, split into items
* @param expression
* @returns {string[]}
*/
private static parseExpression(expression: string): string[] {
expression = expression.replace(/\[(\w+)\]/g, '.$1');
expression = expression.replace(/^\./, '');
return expression.split('.');
}
/**
* Get value by expression
*
* @param object
* @param expression
* @returns {any}
*/
private static getValue(object: any, expression: string[]) {
for (let i = 0, n = expression.length; i < n; ++i) {
const k = expression[i];
if (!(k in object)) {
return;
}
object = object[k];
}
return object;
}
/**
* Set value by expression
*
* @param object
* @param value
* @param expression
*/
private static setValue(object: any, value: any, expression: string[]) {
let i;
for (i = 0; i < expression.length - 1; i++) {
object = object[expression[i]];
}
object[expression[i]] = value;
}
}
答案 9 :(得分:2)
我们知道过滤器和顺序是从ANGULAR 2中删除而我们需要自己编写,这里有一个关于plunker和detailed article的好例子
它既使用过滤器也使用orderby,这里是订单管道的代码
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'orderBy' })
export class OrderrByPipe implements PipeTransform {
transform(records: Array<any>, args?: any): any {
return records.sort(function(a, b){
if(a[args.property] < b[args.property]){
return -1 * args.direction;
}
else if( a[args.property] > b[args.property]){
return 1 * args.direction;
}
else{
return 0;
}
});
};
}
答案 10 :(得分:1)
您可以将其用于对象:
lift
答案 11 :(得分:1)
在package.json中,添加类似的内容(对于Angular 2,此版本是可以的):
"ngx-order-pipe": "^1.1.3",
在您的打字稿模块中(并导入数组):
import { OrderModule } from 'ngx-order-pipe';
答案 12 :(得分:0)
<!-- const cars=['Audi','Merc','BMW','Volvo','Tesla'] -->
<ul>
<li *ngFor="let car of cars">{{car}}</li>
</ul>
/*
*ngFor="let c of oneDimArray | sortBy:'asc'"
*ngFor="let c of arrayOfObjects | sortBy:'asc':'propertyName'"
*/
import { Pipe, PipeTransform } from '@angular/core';
import { orderBy } from 'lodash';
@Pipe({ name: 'sortBy' })
export class SortByPipe implements PipeTransform {
transform(value: any[], order = '', column: string = ''): any[] {
if (!value || order === '' || !order) { return value; } // no array
if (!column || column === '') { return sortBy(value); } // sort 1d array
if (value.length <= 1) { return value; } // array with only one item
return orderBy(value, [column], [order]);
}
}
答案 13 :(得分:0)
orderby Pipe将支持,但 Angular (更高版本)将不支持。请找到他讨论的细节以提高其性能过时的速度。
https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe
答案 14 :(得分:0)
在当前版本的Angular2中,不支持orderBy和ArraySort管道。您需要为此编写/使用一些自定义管道。
答案 15 :(得分:-1)
Component template:
todos| sort: ‘property’:’asc|desc’
Pipe code:
import { Pipe,PipeTransform } from "angular/core";
import {Todo} from './todo';
@Pipe({
name: "sort"
})
export class TodosSortPipe implements PipeTransform {
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 {`enter code here`
return 0;
}
});
return array;
}
}
答案 16 :(得分:-1)
对于Angular 5+版本,我们可以使用ngx-order-pipe package
安装软件包
$ npm install ngx-order-pipe --save
导入应用模块
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { OrderModule } from 'ngx-order-pipe';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
OrderModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
在任何地方使用
<ul>
<li *ngFor="let item of (dummyData | orderBy:'name') ">
{{item.name}}
</li>
</ul>