[angular] OrderBy 파이프 문제
이 코드를 Angualr 1에서 Angular 2로 번역 할 수 없습니다.
ng-repeat="todo in todos | orderBy: 'completed'"
이것은 Thierry Templier의 답변에 따라 내가 한 일입니다.
구성 요소 템플릿 :
*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;
}
}
Todo
속성별로 정렬 된 배열을 정렬하려고 합니다 completed
. 먼저 todo.completed = false
다음 todo.complete = true
.
나는 그 transform
방법과 그 방법과 방법에서 인수를 전달하는 방법을 잘 이해하지 못합니다 sort
.
args: string
논쟁 은 무엇입니까 ? 무엇 a
과 b
그들이 어디에서 온?
답변
파이프가 사용자 지정 개체를 각도 4로 정렬 할 수 있도록 @Thierry Templier의 응답을 수정했습니다.
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'"
바라건대 이것은 누군가를 도울 것입니다.
답변
전체 토론 은 https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe 를 참조 하십시오 . 이 인용문은 가장 관련성이 있습니다. 기본적으로 적극적으로 축소해야하는 대규모 앱의 경우 필터링 및 정렬 논리가 구성 요소 자체로 이동해야합니다.
“우리 중 일부는 이것을 공격적으로 축소하는 데 신경 쓰지 않을 수 있습니다. 그것이 우리의 선택입니다. 그러나 Angular 제품은 다른 사람이 공격적으로 축소하는 것을 막아서는 안됩니다. 따라서 Angular 팀은 Angular에 제공된 모든 것이 안전하게 축소 될 것이라고 결정했습니다.
Angular 팀과 경험 많은 Angular 개발자는 필터링 및 정렬 논리를 구성 요소 자체로 이동할 것을 강력히 권장합니다. 구성 요소는 filterHeroes 또는 sortedHeroes 속성을 노출하고 지원 논리를 실행할시기와 빈도를 제어 할 수 있습니다. 파이프에 넣고 앱 전체에서 공유 할 수있는 모든 기능을 필터링 / 정렬 서비스로 작성하고 구성 요소에 삽입 할 수 있습니다. “
답변
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 ]
})
(...)
문자열 값이있는 배열에 대한 간단한 샘플이지만 일부 고급 정렬 처리를 수행 할 수 있습니다 (정렬 매개 변수를 기반으로하는 객체 배열의 경우 객체 속성을 기반으로 함).
여기에 대한 plunkr가 있습니다 : https://plnkr.co/edit/WbzqDDOqN1oAhvqMkQRQ?p=preview .
도움이 되었기를 바랍니다, Thierry
답변
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 : 부울; 참 : 내림차순; 거짓 : 오름차순;
답변
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는 순수하고 불순한 파이프의 개념을 가지고 있습니다.
순수 파이프는 객체 ID를 사용하여 변경 감지를 최적화합니다. 이는 입력 객체가 ID를 변경하는 경우 (예 : 배열에 새 항목을 추가하는 경우)에만 파이프가 실행됨을 의미합니다. 물체로 내려 가지 않습니다. 즉, 중첩 된 속성을 변경 this.cats[2].name = "Fluffy"
하면 파이프가 다시 실행되지 않습니다. 이것은 Angular가 빠르도록 도와줍니다. 각도 파이프는 기본적으로 순수합니다.
반면에 불순한 파이프 는 객체 속성을 확인합니다. 이것은 잠재적으로 훨씬 느리게 만듭니다. 파이프 함수가 수행 할 작업을 보장 할 수 없기 때문에 (예를 들어 시간에 따라 다르게 정렬 될 수 있음) 비동기 이벤트가 발생할 때마다 불순한 파이프가 실행됩니다. 배열이 큰 경우 앱 속도가 상당히 느려집니다.
위의 파이프는 순수합니다. 즉, 배열의 개체가 변경 불가능할 때만 실행됩니다. 고양이를 변경하는 경우 전체 고양이 개체를 새 개체로 바꿔야합니다.
this.cats[2] = {name:"Tomy"}
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)
}
}
이 파이프는 물체로 내려가지만 속도가 느려집니다. 주의해서 사용하십시오.
답변
필요한 작업을 수행하는 OrderBy 파이프를 만들었습니다. 또한 개체 열거 형의 여러 열에서 정렬 할 수 있도록 지원합니다.
<li *ngFor="#todo in todos | orderBy : ['completed']">{{todo.name}} {{todo.completed}}</li>
이 파이프는 페이지를 렌더링 한 후 배열에 더 많은 항목을 추가 할 수 있도록하며 업데이트 된 배열을 동적으로 정렬합니다.
그리고 여기에 작동하는 데모가 있습니다 : http://fuelinteractive.github.io/fuel-ui/#/pipe/orderby 및 https://plnkr.co/edit/DHLVc0?p=info
답변
각도와 함께 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, ...],
...
})