# CHAPTER 7. Pipes

## Pied piper

때로는 기존 데이터가 뷰에 표시 할 데이터가 아닐 경우가 있다. 우리는 종종 필터를 변환하고, 필터를 걸고, 필터를 제한하는 등의 작업을 원한다. AngularJS 1.x에는 '필터'라고하는 이름이 매우 유용하게 사용되었다. <br>

파이프는 HTML 또는 응용 프로그램 코드에서 사용할 수 있다. 예를 들고 우리가 그것을 어떻게 사용할 수 있는지 보자.

## Json

JsonPipe는 개발 응용 프로그램에서는 별로 유용하지 않지만 응용 프로그램을 디버깅 할 때는 매우 유용하다. 기본적으로 이 파이프는 JSON.stringify ()를 데이터에 적용한다. 구성 요소에 일부 데이터가 있는 경우 pony 배열을 예로 들자면, 내부에 무엇이 있는지 신속하게 확인하려는 경우, 당신은 다음과 같은 것을 시도 할 수 있다.

```markup
<p>{% raw %}{{ ponies }}{% endraw %}</p>
```

운이 좋으면 \[object object]가 표시 될 것이다. 하지만 JsonPipe는 우리를 구하기 위해 여기에 있고 어떤 식 으로든 HTML에서 사용할 수 있다.

```markup
<p>{% raw %}{{ ponies | json }}{% endraw %}</p>
```

그리고 그것은 개체의 JSON 표현을 표시한다.

```markup
<p>[ { "name": "Rainbow Dash" }, { "name": "Pinkie Pie" } ]</p>
```

파이프를 사용하려면 데이터 다음에 파이프 (|) 문자를 추가 한 다음 사용할 파이프의 이름을 추가해야 한다. 표현식이 평가되고 결과가 파이프를 통과할것이다. 여러 파이프를 차례로 연결할 수 있다.

```markup
<p>{% raw %}{{ ponies | slice:0:2 | json }}{% endraw %}</p>
```

우리는 슬라이스 파이프로 돌아갈 것이지만 슬라이스 파이프를 연결 한 다음 json을 연결하는 것을 볼 수 있다. "

"보간 표현식이나 속성 표현식에서는 사용할 수 있지만 이벤트 문에서는 사용할 수 없다.

```markup
<p [textContent]="ponies | json"></p>
```

의존성 삽입을 통해 코드에서 사용할 수도 있다.

```javascript
import { Component } from '@angular/core';
// you need to import the pipe you want to use
import { JsonPipe } from '@angular/common';
@Component({
  selector: 'ns-ponies',
  template: `<p>{% raw %}{{poniesAsJson}}{% endraw %}</p>`
})
export class PoniesComponent {
  ponies: Array<any> = [{ name: 'Rainbow Dash' }, { name: 'Pinkie Pie' }];
  poniesAsJson: string;
  // inject the Pipe you want
  constructor(jsonPipe: JsonPipe) {
   // and then call the transform method on it
   this.poniesAsJson = jsonPipe.transform(this.ponies);
  }
}
```

그러나 조심 해야한다 : 파이프는 @NgModule (또는 @Component)의 provider에 추가되어야 한다. 이것은 모든 파이프에서 동일하므로 보간법을 사용하여 HTML 예제를 보도록 하자.

```markup
<p>{% raw %}{{ ponies | slice:0:2 | json }}{% endraw %}</p>
```

이 예제는 조랑말 목록의 처음 두 요소를 표시한다. slice는 배열과 문자열로 작동하므로 문자열을 자를 수도 있다.

```markup
<p>{% raw %}{{ 'Ninja Squad' | slice:0:5 }}{% endraw %}</p>
```

'Ninja'만 표시될 것이다. 슬라이스 파이프에 하나의 인덱스 n만을 줄 수 있으며 n에서 끝까지 요소를 가져올것이다.

```markup
<p>{% raw %}{{ 'Ninja Squad' | slice:3 }}{% endraw %}</p>
<!-- will display 'ja Squad' -->
```

음수를 지정하면 뒤에서 부터 자를 것이다.

```markup
<p>{% raw %}{{ 'Ninja Squad' | slice:-5 }}{% endraw %}</p>
<!-- will display 'Squad' -->
```

우리가 보았 듯이, 파이프에게 종료 인덱스를 줄 수 있다 :이 인덱스까지 요소를 가져옵니다. 이 인덱스가 음수이면 인덱스까지 요소를 취하지만 끝에서부터 시작한다.

```markup
<p>{% raw %}{{ 'Ninja Squad' | slice:2:-2 }}{% endraw %}</p>
<!-- will display 'nja Squ' -->
```

임의의 표현식에서 slice를 사용할 수 있으므로 NgFor에서도 사용할 수 있다.

```javascript
import { Component } from '@angular/core';
@Component({
  selector: 'ns-ponies',
  template: `<div *ngFor="let pony of ponies | slice:0:2">{% raw %}{{pony.name}}{% endraw %}</div>`
})
export class PoniesComponent {
  ponies: Array<any> = [
   { name: 'Rainbow Dash' },
   { name: 'Pinkie Pie' },
   { name: 'Fluttershy' }
  ];
}
```

이 구성 요소는 컬렉션에 슬라이스 파이프를 적용 했으므로 첫 번째 두 조랑말에 대해 두 개의 div 요소를 만든다. 파이프 인수는 물론 동적 값이 될 수 있습니다.

```javascript
import { Component } from '@angular/core';
@Component({
  selector: 'ns-ponies',
  template: `<div *ngFor="let pony of ponies | slice:0:size">{% raw %}{{pony.name}}{% endraw %}</div>`
})
export class PoniesComponent {
  size: number = 2;
  ponies: Array<any> = [
   { name: 'Rainbow Dash' },
   { name: 'Pinkie Pie' },
   { name: 'Fluttershy' }
  ];
}
```

이 기능을 사용하여 사용자가 보고 싶은 요소의 수를 선택할 수 있는 동적 디스플레이를 만들 수 있다.

이 파이프의 이름이 충분히 명확 해지면서이 파이프는 문자열을 대문자로 변환 한다.

```markup
<p>{% raw %}{{ 'Ninja Squad' | uppercase }}{% endraw %}</p>
<!-- will display 'NINJA SQUAD' -->
```

이 파이프의 이름이 충분히 명확 해지면서이 파이프는 문자열을 소문자로 변환 한다.

```markup
<p>{% raw %}{{ 'Ninja Squad' | lowercase }}{% endraw %}</p>
<!-- will display 'ninja squad' -->
```

이 파이프는 숫자의 서식을 지정할 수 있다. {integerDigits} {minFractionDigits} - {maxFractionDigits} 형식의 문자열 하나가 필요하지만 모든 부분은 선택 사항 이다. 각 부분은 다음을 나타낸다. • 정수 부분에 원하는 수의 개수 • 소수 부분에서 원하는 숫자의 수 • 소수 부분에서 원하는 숫자의 수 파이프가 없는 것부터 시작하는 몇 가지 예이다.

```markup
<p>{% raw %}{{ 12345 }}{% endraw %}</p>
<!-- will display '12345' -->
```

숫자 파이프를 사용하면 숫자가 필요하지 않은 경우에도 정수 부분이 그룹화 된다.

```markup
<p>{% raw %}{{ 12345 | number }}{% endraw %}</p>
<!-- will display '12,345' -->
```

integerDigits 매개 변수는 필요한 경우 정수 부분을 0으로 왼쪽에 채워 준다.

```markup
<p>{% raw %}{{ 12345 | number:'6.' }}{% endraw %}</p>
<!-- will display '012,345' -->
```

minFractionDigits는 소수 부분의 최소 크기이므로 도달 할 때까지 오른쪽에 0을 채워 준다.

```markup
<p>{% raw %}{{ 12345 | number:'.2' }}{% endraw %}</p>
<!-- will display '12,345.00' -->
```

maxFractionDigits는 소수 부분의 최대 크기이다. 그것을 원한다면 minFractionDigits를 0으로 지정해야 한다. 숫자가 그 보다 소수 이상이면 반올림된다.

```markup
<p>{% raw %}{{ 12345.13 | number:'.1-1' }}{% endraw %}</p>
<!-- will display '12,345.1' -->
<p>{% raw %}{{ 12345.16 | number:'.1-1' }}{% endraw %}</p>
<!-- will display '12,345.2' -->
```

파이프 (백분율과 통화는 물론)는 브라우저의 국제화 API를 사용하며 이 API는 현재 모든 브라우저에서 사용할 수 없다. 이는 알려진 문제이며 일부 브라우저 (Safari / iOS 등)에서이 API에 대해 polyfill을 사용하도록 해야 한다.\ <br>

숫자와 동일한 원칙에 따라 백분율은 백분율을 표시 할 수 있다.

```markup
<p>{% raw %}{{ 0.8 | percent }}{% endraw %}</p>
<!-- will display '80%' -->
<p>{% raw %}{{ 0.8 | percent:'.3' }}{% endraw %}</p>
<!-- will display '80.000%' -->
```

상상할 수 있듯이 파이프는 원하는 통화로 금액을 형식화 할 수 있다. 적어도 하나의 매개 변수를 지정해야 한다.

• 통화를 나타내는 ISO 문자열 ( 'EUR', 'USD'...) • 선택적으로 기호 ( '€', '$') 또는 ISO 문자열을 사용할지 여부를 나타내는 부울 플래그. 기본적으로, 플래그는 false이며 심볼은 사용되지 않는다. • 선택적으로 number와 동일한 구문을 사용하여 금액을 형식화하는 문자열

```markup
<p>{% raw %}{{ 10.6 | currency:'EUR' }}{% endraw %}</p>
<!-- will display 'EUR10.60' -->
<p>{% raw %}{{ 10.6 | currency:'USD':true }}{% endraw %}</p>
<!-- will display '$10.60' -->
<p>{% raw %}{{ 10.6 | currency:'USD':true:'.3' }}{% endraw %}</p>
<!-- will display '$10.600' -->
```

날짜 파이프는 날짜 값을 원하는 형식의 문자열로 포맷이다. 날짜는 Date 개체 또는 밀리 초를 나타낸다. 지정된 형식은 'dd / MM / yyyy', 'MM-yy'또는 'short', 'longDate'등과 같이 미리 정의 된 기호 이름 중 하나 일 수 있다.

```markup
<p>{% raw %}{{ birthday | date:'dd/MM/yyyy' }}{% endraw %}</p>
<!-- will display '16/07/1986' -->
<p>{% raw %}{{ birthday | date:'longDate' }}{% endraw %}</p>
<!-- will display 'July 16, 1986' -->
```

물론 날짜의 시간 부분을 표시 할 수도 있다.

```markup
<p>{% raw %}{{ birthday | date:'HH:mm' }}{% endraw %}</p>
<!-- will display '15:30' -->
<p>{% raw %}{{ birthday | date:'shortTime' }}{% endraw %}</p>
<!-- will display '3:30 PM' -->
```

비동기 파이프를 사용하면 비동기 적으로 가져온 데이터를 표시 할 수 있다. 내부적으로 비동기 데이터가 Promise 또는 Observable에서 온 것인지 여부에 따라 PromisePipe 또는 ObservablePipe를 사용한다. Promise가 무엇인지 이제는 알고 있어야 한다. 그렇지 않으면 ES6 장으로 돌아가서 Observable를 확인하도록 하라.\ <br>

비동기 파이프는 데이터가 최종적으로 사용 가능할 때까지 (즉, 약속이 확정 될 때까지) 빈 문자열을 반환한다. 일단 해결되면 해결 된 값이 반환된다. 더 중요한 것은 데이터를 사용할 수있게 되면 변경 감지 검사를 트리거하게 된다.

```javascript
import { Component } from '@angular/core';
@Component({
  selector: 'ns-greeting',
  template: `<div>{% raw %}{{ asyncGreeting | async }}{% endraw %}</div>`
})
export class GreetingComponent {
  asyncGreeting = new Promise(resolve => {
   // after 1 second, the promise will resolve
   window.setTimeout(() => resolve('hello'), 1000);
  });
}
```

비동기 파이프가 asyncGreeting 변수에 적용된 것을 볼 수 있다. 1초 후에 값이 바인딩 되면 트리거를 탈 것이다.

```markup
<div>hello</div>
```

더욱 흥미로운 것은 소스가 Observable 인 경우 사용자가 다른 구성 요소를 탐색 할 때와 같이 구성 요소가 파괴 될 때 파이프가 구독 취소 부분 자체를 처리한다는 것이다.

물론 파이프를 직접 만들 수도 있고 때로는 매우 유용하다. AngularJS 1.x에서는 맞춤 필터를 자주 사용하였다. 예를 들어, 우리는 우리의 애플 리케이션의 몇 가지 (3 일 전 agoor 12초 등) 사용자가 한 작업 경과 얼마나 많은 시간을 표시 하나를 만들었다. Angular 2에서 우리가 어떻게 할 것인지 보자.

먼저 새로운 클래스를 만들어야 하고 그것은 PipeTransform 인터페이스를 구현해야 한다. 이 인터페이스는 무거운 물건을 들여다 보는 transform () 메소드를 필요로 한다.

```javascript
import { PipeTransform, Pipe } from '@angular/core';
export class FromNowPipe implements PipeTransform {
  transform(value, args) {
   // do something here
  }
}
```

Now 함수의 Moment.js를 사용하여 날짜 이후 얼마나 많은 시간이 경과했는지 표시한다. 원하는 경우 NPM을 사용하여 Moment.js를 설치할 수 있다.

```javascript
npm install moment
```

SystemJS 구성에 추가하여라.

```javascript
map: {
  '@angular': 'node_modules/@angular',
  'rxjs': 'node_modules/rxjs',
  'moment': 'node_modules/moment/moment'
}
```

TypeScript를 사용할 때 인터페이스도 필요하다.

```javascript
typings install --save --ambient moment-node
```

```javascript
import { PipeTransform, Pipe } from '@angular/core';
import * as moment from 'moment';
export class FromNowPipe implements PipeTransform {
  transform(value, args) {
   return moment(value).fromNow();
  }
}
```

이제 우리는 앱에 파이프를 등록해야 한다. 이를 위해 우리가 사용할 수있는 특별한 데코레이터가 있다 : @Pipe

```javascript
import { PipeTransform, Pipe } from '@angular/core';
import * as moment from 'moment';
@Pipe({ name: 'fromNow' })
export class FromNowPipe implements PipeTransform {
  transform(value, args) {
   return moment(value).fromNow();
  }
}
```

선택한 이름은 템플릿에서 파이프를 사용할 수있는 이름이 된다. 템플릿에서 파이프를 사용하려면 마지막으로해야 할 일은 @NgModule의 선언에 파이프를 추가하는 것이다.

```javascript
@NgModule({
  imports: [BrowserModule],
  declarations: [PonyRacerAppComponent, RacesComponent, FromNowPipe],
  bootstrap: [PonyRacerAppComponent]
})
export class AppModule {
}
```

## slice

목록의 일부만 표시하려면 slice를 사용하면 된다. 자바 스크립트에서 슬라이스 메서드처럼 작동하며 시작 인덱스와 선택적으로 종료 인덱스라는 두 개의 인수를 취한다.<br>

인수를 파이프에 전달하려면 콜론 :을 추가하고 첫 번째 인수 다음에 콜론 (:) 및 두 번째 인수 등을 추가해야 한다.

## Reference URL

* [Become a NINJA with Angular 2](https://books.ninja-squad.com/public/samples/Become_a_ninja_with_Angular2_sample.pdf)
* [Learn Angular 2](http://learnangular2.com/)
* [Angular 2 Component](https://www.tutorialspoint.com/angular2/)
* [An Introduction to Angular 2](http://angular-tips.com/blog/2015/05/an-introduction-to-angular-2/)
