parent
e2f2ca61e6
commit
b2b4d3b8c9
|
@ -1,12 +1,11 @@
|
||||||
|
<hr>
|
||||||
<!-- async examples at the top so can see them in action -->
|
<!-- async examples at the top so can see them in action -->
|
||||||
<my-hero></my-hero>
|
<hero-message></hero-message>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<hero-list></hero-list>
|
<hero-list></hero-list>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<!-- #docregion hero-birthday-template -->
|
<!-- #docregion hero-birthday-template -->
|
||||||
<p>The hero's birthday is {{ birthday | date }}</p>
|
<p>The hero's birthday is {{ birthday | date }}</p>
|
||||||
<!-- #enddocregion hero-birthday-template-->
|
<!-- #enddocregion hero-birthday-template-->
|
||||||
|
@ -16,8 +15,7 @@
|
||||||
<!-- #enddocregion format-birthday-->
|
<!-- #enddocregion format-birthday-->
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
<h4>Hero Birthday v.2</h4>
|
||||||
<h4>Hero Birthday 2</h4>
|
|
||||||
<hero-birthday>loading...</hero-birthday>
|
<hero-birthday>loading...</hero-birthday>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
@ -32,15 +30,18 @@
|
||||||
<!-- #docregion chained-parameter-birthday -->
|
<!-- #docregion chained-parameter-birthday -->
|
||||||
<p>
|
<p>
|
||||||
The chained hero's birthday is
|
The chained hero's birthday is
|
||||||
{{ ( birthday | date:'fullDate' ) | uppercase}}
|
{{ birthday | date:'fullDate' | uppercase}}
|
||||||
</p>
|
</p>
|
||||||
<!-- #enddocregion chained-parameter-birthday -->
|
<!-- #enddocregion chained-parameter-birthday -->
|
||||||
|
<!-- #docregion chained-parameter-birthday-parens -->
|
||||||
|
<p>
|
||||||
|
The chained hero's birthday is
|
||||||
|
{{ ( birthday | date:'fullDate' ) | uppercase}}
|
||||||
|
</p>
|
||||||
|
<!-- #enddocregion chained-parameter-birthday-parens -->
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<power-booster>loading...</power-booster>
|
<power-booster>loading...</power-booster>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<power-boost-calculator>loading ..</power-boost-calculator>
|
<power-boost-calculator>loading ..</power-boost-calculator>
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
// #docregion
|
||||||
|
import {Component} from 'angular2/core';
|
||||||
|
import {HeroAsyncMessageComponent} from './hero-async-message.component';
|
||||||
|
import {HeroBirthday} from './hero-birthday2.component';
|
||||||
|
import {HeroListComponent} from './hero-list.component';
|
||||||
|
import {PowerBooster} from './power-booster.component';
|
||||||
|
import {PowerBoostCalculator} from './power-boost-calculator.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-app',
|
||||||
|
templateUrl: 'app/app.component.html',
|
||||||
|
directives:[
|
||||||
|
HeroAsyncMessageComponent,
|
||||||
|
HeroBirthday,
|
||||||
|
HeroListComponent,
|
||||||
|
PowerBooster, PowerBoostCalculator
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
birthday = new Date(1988,3,15); // April 15, 1988
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
import {bootstrap} from 'angular2/platform/browser';
|
||||||
|
import {AppComponent} from './app.component';
|
||||||
|
import {HeroBirthday} from './hero-birthday1.component';
|
||||||
|
|
||||||
|
bootstrap(AppComponent);
|
||||||
|
bootstrap(HeroBirthday); // v.1
|
|
@ -1,5 +1,5 @@
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Pipe} from 'angular2/angular2';
|
import {Pipe} from 'angular2/core';
|
||||||
/*
|
/*
|
||||||
* Raise the value exponentially
|
* Raise the value exponentially
|
||||||
* Takes an exponent argument that defaults to 1.
|
* Takes an exponent argument that defaults to 1.
|
||||||
|
@ -9,13 +9,10 @@ import {Pipe} from 'angular2/angular2';
|
||||||
* {{ 2 | exponentialStrength:10}}
|
* {{ 2 | exponentialStrength:10}}
|
||||||
* formats to: 1024
|
* formats to: 1024
|
||||||
*/
|
*/
|
||||||
@Pipe({
|
@Pipe({name: 'exponentialStrength'})
|
||||||
name: 'exponentialStrength'
|
|
||||||
})
|
|
||||||
export class ExponentialStrengthPipe {
|
export class ExponentialStrengthPipe {
|
||||||
|
|
||||||
transform(value:number, args:string[]) : any {
|
transform(value:number, args:string[]) : any {
|
||||||
return Math.pow(value, parseInt(args[0] || '1', 10));
|
return Math.pow(value, parseInt(args[0] || '1', 10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion
|
|
|
@ -1,7 +1,6 @@
|
||||||
///<reference path="./window.extension.d.ts"/>
|
/// <reference path='./window.extension.d.ts'/>
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Pipe} from 'angular2/angular2';
|
import {Pipe} from 'angular2/core';
|
||||||
|
|
||||||
// #docregion pipe-metadata
|
// #docregion pipe-metadata
|
||||||
@Pipe({
|
@Pipe({
|
||||||
|
@ -12,13 +11,12 @@ import {Pipe} from 'angular2/angular2';
|
||||||
export class FetchJsonPipe {
|
export class FetchJsonPipe {
|
||||||
private fetchedValue:any;
|
private fetchedValue:any;
|
||||||
private fetchPromise:Promise<any>;
|
private fetchPromise:Promise<any>;
|
||||||
|
|
||||||
transform(value:string, args:string[]):any {
|
transform(value:string, args:string[]):any {
|
||||||
if (!this.fetchPromise) {
|
if (!this.fetchPromise) {
|
||||||
this.fetchPromise = window.fetch(value)
|
this.fetchPromise = window.fetch(value)
|
||||||
.then(result => result.json())
|
.then((result:any) => result.json())
|
||||||
.then(json => {
|
.then((json:any) => this.fetchedValue = json);
|
||||||
this.fetchedValue = json;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.fetchedValue;
|
return this.fetchedValue;
|
|
@ -0,0 +1,15 @@
|
||||||
|
// #docregion
|
||||||
|
import {Component} from 'angular2/core';
|
||||||
|
|
||||||
|
// Initial view: "Message: "
|
||||||
|
// After 500ms: Message: You are my Hero!"
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-message',
|
||||||
|
template: 'Message: {{delayedMessage | async}}',
|
||||||
|
})
|
||||||
|
export class HeroAsyncMessageComponent {
|
||||||
|
delayedMessage:Promise<string> = new Promise((resolve, reject) => {
|
||||||
|
setTimeout(() => resolve('You are my Hero!'), 500);
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Version #1
|
||||||
|
// #docregion
|
||||||
|
import {Component} from 'angular2/core'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-birthday',
|
||||||
|
// #docregion hero-birthday-template
|
||||||
|
template: `<p>The hero's birthday is {{ birthday | date }}</p>`
|
||||||
|
// #enddocregion hero-birthday-template
|
||||||
|
})
|
||||||
|
export class HeroBirthday {
|
||||||
|
birthday = new Date(1988,3,15); // April 15, 1988
|
||||||
|
}
|
||||||
|
// #enddocregion
|
|
@ -1,16 +1,24 @@
|
||||||
import {bootstrap, Component} from 'angular2/angular2'
|
// Version #2
|
||||||
// #docregion
|
// #docregion
|
||||||
|
import {Component} from 'angular2/core'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-birthday',
|
selector: 'hero-birthday',
|
||||||
|
// #docregion template
|
||||||
template: `
|
template: `
|
||||||
<p>The hero's birthday is {{ birthday | date:format }}</p>
|
<p>The hero's birthday is {{ birthday | date:format }}</p>
|
||||||
<button (click)="toggleFormat()">Toggle Format</button>
|
<button (click)="toggleFormat()">Toggle Format</button>
|
||||||
`
|
`
|
||||||
|
// #enddocregion template
|
||||||
})
|
})
|
||||||
|
// #docregion class
|
||||||
export class HeroBirthday {
|
export class HeroBirthday {
|
||||||
birthday = new Date(1988,3,15); // April 15, 1988
|
birthday = new Date(1988,3,15); // April 15, 1988
|
||||||
|
|
||||||
|
toggle = true; // start with true == shortDate
|
||||||
|
|
||||||
get format() { return this.toggle ? 'shortDate' : 'fullDate'}
|
get format() { return this.toggle ? 'shortDate' : 'fullDate'}
|
||||||
toggle = true;
|
|
||||||
toggleFormat() { this.toggle = !this.toggle; }
|
toggleFormat() { this.toggle = !this.toggle; }
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion class
|
|
@ -0,0 +1,24 @@
|
||||||
|
// #docregion
|
||||||
|
import {Component} from 'angular2/core';
|
||||||
|
import {FetchJsonPipe} from './fetch-json.pipe';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-list',
|
||||||
|
// #docregion template
|
||||||
|
template: `
|
||||||
|
<h4>Heroes from JSON File</h4>
|
||||||
|
|
||||||
|
<div *ngFor="#hero of ('heroes.json' | fetch) ">
|
||||||
|
{{hero.name}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>Heroes as JSON:
|
||||||
|
{{'heroes.json' | fetch | json}}
|
||||||
|
</p>
|
||||||
|
`,
|
||||||
|
// #enddocregion template
|
||||||
|
pipes: [FetchJsonPipe]
|
||||||
|
})
|
||||||
|
export class HeroListComponent {
|
||||||
|
/* I've got nothing to do ;-) */
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
// #docregion
|
||||||
|
import {Component} from 'angular2/core';
|
||||||
|
import {ExponentialStrengthPipe} from './exponential-strength.pipe';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'power-boost-calculator',
|
||||||
|
template: `
|
||||||
|
<h2>Power Boost Calculator</h2>
|
||||||
|
<div>Normal power: <input [(ngModel)]="power"></div>
|
||||||
|
<div>Boost factor: <input [(ngModel)]="factor"></div>
|
||||||
|
<p>
|
||||||
|
Super Hero Power: {{power | exponentialStrength: factor}}
|
||||||
|
</p>
|
||||||
|
`,
|
||||||
|
pipes: [ExponentialStrengthPipe]
|
||||||
|
})
|
||||||
|
export class PowerBoostCalculator {
|
||||||
|
power = 5;
|
||||||
|
factor = 1;
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Component} from 'angular2/angular2'
|
import {Component} from 'angular2/core';
|
||||||
import {ExponentialStrengthPipe} from './exponential-strength-pipe'
|
import {ExponentialStrengthPipe} from './exponential-strength.pipe';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'power-booster',
|
selector: 'power-booster',
|
|
@ -0,0 +1,3 @@
|
||||||
|
interface Window {
|
||||||
|
fetch(url: string, options? : {}) : Promise<any>
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Pipes</title>
|
||||||
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
|
||||||
|
<script>
|
||||||
|
System.config({
|
||||||
|
packages: {'app': {defaultExtension: 'js'}}
|
||||||
|
});
|
||||||
|
System.import('app/boot');
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h4>Hero Birthday v.1</h4>
|
||||||
|
<hero-birthday>hero-birthday loading...</hero-birthday>
|
||||||
|
|
||||||
|
<my-app>my-app loading ...</my-app>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"description": "Pipes",
|
||||||
|
"files":[
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js",
|
||||||
|
"!**/*.d.ts"],
|
||||||
|
"tags": ["pipe"]
|
||||||
|
}
|
|
@ -1,52 +0,0 @@
|
||||||
import {HeroBirthday as HeroBirthday2} from './hero-birthday';
|
|
||||||
import {PowerBooster} from './power-booster';
|
|
||||||
import {PowerBoostCalculator} from './power-boost-calculator';
|
|
||||||
import {HeroListComponent} from './hero-list-component';
|
|
||||||
|
|
||||||
// #docregion hero-birthday
|
|
||||||
import {bootstrap, Component} from 'angular2/angular2'
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'hero-birthday',
|
|
||||||
// #docregion hero-birthday-template
|
|
||||||
template: `<p>The hero's birthday is {{ birthday | date }}</p>`
|
|
||||||
// #enddocregion hero-birthday-template
|
|
||||||
})
|
|
||||||
export class HeroBirthday {
|
|
||||||
birthday = new Date(1988,3,15); // April 15, 1988
|
|
||||||
}
|
|
||||||
|
|
||||||
bootstrap(HeroBirthday);
|
|
||||||
// #enddocregion hero-birthday
|
|
||||||
|
|
||||||
// #docregion async-message
|
|
||||||
@Component({
|
|
||||||
selector: 'my-hero',
|
|
||||||
template: 'Message: {{delayedMessage | async}}',
|
|
||||||
})
|
|
||||||
class MyHeroAsyncMessageComponent {
|
|
||||||
delayedMessage:Promise<string> = new Promise((resolve, reject) => {
|
|
||||||
setTimeout(() => resolve('You are my Hero!'), 500);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initial view: "Message: "
|
|
||||||
// After 500ms: Message: You are my Hero!"
|
|
||||||
// #enddocregion async-message
|
|
||||||
|
|
||||||
//// Drives the rest of the pipes chapter examples ///
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'my-app',
|
|
||||||
templateUrl: 'app/app.html',
|
|
||||||
directives:[
|
|
||||||
HeroBirthday2,
|
|
||||||
PowerBooster, PowerBoostCalculator,
|
|
||||||
MyHeroAsyncMessageComponent,
|
|
||||||
HeroListComponent]
|
|
||||||
})
|
|
||||||
class AppComponent {
|
|
||||||
birthday = new Date(1988,3,15); // April 15, 1988
|
|
||||||
}
|
|
||||||
bootstrap(AppComponent);
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
// #docregion
|
|
||||||
import {bootstrap, Component,
|
|
||||||
CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/angular2'
|
|
||||||
|
|
||||||
import {FetchJsonPipe} from './fetch-json-pipe'
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'hero-list',
|
|
||||||
template: `
|
|
||||||
<h4>Heroes from JSON File</h4>
|
|
||||||
|
|
||||||
<div *ng-for="#hero of ('heroes.json' | fetch) ">
|
|
||||||
{{hero.name}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>Heroes as JSON:
|
|
||||||
{{'heroes.json' | fetch | json}}
|
|
||||||
</p>
|
|
||||||
`,
|
|
||||||
directives:[CORE_DIRECTIVES],
|
|
||||||
pipes: [FetchJsonPipe]
|
|
||||||
})
|
|
||||||
export class HeroListComponent {
|
|
||||||
/* I've got nothing to do ;-) */
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
// #docregion
|
|
||||||
import {Component, FORM_DIRECTIVES} from 'angular2/angular2'
|
|
||||||
import {ExponentialStrengthPipe} from './exponential-strength-pipe'
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'power-boost-calculator',
|
|
||||||
template: `
|
|
||||||
<h2>Power Boost Calculator</h2>
|
|
||||||
<div>Normal power: <input [(ng-model)]="power"></div>
|
|
||||||
<div>Boost factor: <input [(ng-model)]="factor"></div>
|
|
||||||
<p>
|
|
||||||
Super Hero Power: {{power | exponentialStrength: factor}}
|
|
||||||
</p>
|
|
||||||
`,
|
|
||||||
pipes: [ExponentialStrengthPipe],
|
|
||||||
directives: [FORM_DIRECTIVES]
|
|
||||||
})
|
|
||||||
export class PowerBoostCalculator {
|
|
||||||
power = 5;
|
|
||||||
factor = 1;
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
interface Window {
|
|
||||||
fetch:(url: string, options?: {}) => Promise<any>
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>Pipes</title>
|
|
||||||
<script src="../node_modules/systemjs/dist/system.src.js"></script>
|
|
||||||
<script src="../node_modules/angular2/bundles/angular2.dev.js"></script>
|
|
||||||
<script>
|
|
||||||
System.config({
|
|
||||||
packages: {'app': {defaultExtension: 'js'}}
|
|
||||||
});
|
|
||||||
System.import('app/app');
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<h4>Hero Birthday 1</h4>
|
|
||||||
<hero-birthday>loading...</hero-birthday>
|
|
||||||
<hr>
|
|
||||||
<my-app>loading ...</my-app>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"files":["!**/*.d.ts", "!**/*.js"]
|
|
||||||
}
|
|
|
@ -17,7 +17,7 @@ include ../../../../_includes/_util-fns
|
||||||
|
|
||||||
Welcome, Angular pipes, the simple display-value transformations that we can declare in our HTML!
|
Welcome, Angular pipes, the simple display-value transformations that we can declare in our HTML!
|
||||||
|
|
||||||
[Live Example](/resources/live-examples/pipes/ts/src/plnkr.html)
|
[Live Example](/resources/live-examples/pipes/ts/plnkr.html).
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
|
@ -25,25 +25,16 @@ include ../../../../_includes/_util-fns
|
||||||
|
|
||||||
A pipe takes in data as input and transforms it to a desired output.
|
A pipe takes in data as input and transforms it to a desired output.
|
||||||
We'll illustrate by transforming a component's birthday property into
|
We'll illustrate by transforming a component's birthday property into
|
||||||
a human-friendly date.
|
a human-friendly date:
|
||||||
|
+makeExample('pipes/ts/app/hero-birthday1.component.ts', null, 'app/hero-birthday1.component.ts')
|
||||||
Here's a complete mini-app with a `DatePipe`:
|
|
||||||
<!--
|
|
||||||
All date samples are in my plunker
|
|
||||||
http://plnkr.co/edit/RDlOma?p=preview
|
|
||||||
-->
|
|
||||||
|
|
||||||
+makeExample('pipes/ts/src/app/app.ts', 'hero-birthday')
|
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
Focus on the component's template to see how we applied the built-in `DatePipe`
|
Focus on the component's template.
|
||||||
while binding the `birthday` property.
|
+makeExample('pipes/ts/app/app.component.html', 'hero-birthday-template')(format=".")
|
||||||
+makeExample('pipes/ts/src/app/app.html', 'hero-birthday-template')(format=".")
|
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
Angular [template syntax](./template-syntax.html#pipe) includes a pipe operator ( | ) which we're
|
Inside the interpolation expression we flow the component's `birthday` value through the
|
||||||
using to flow the birthday value on the left through to the `Date` pipe function on the right.
|
[pipe operator](./template-syntax.html#pipe) ( | ) to the [Date pipe](../api/common/DatePipe-class.html)
|
||||||
All pipes work this way.
|
function on the right. All pipes work this way.
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
|
@ -64,25 +55,26 @@ include ../../../../_includes/_util-fns
|
||||||
We add parameters to a pipe by following the pipe name with a colon ( : ) and then the parameter value
|
We add parameters to a pipe by following the pipe name with a colon ( : ) and then the parameter value
|
||||||
(e.g., `currency:'EUR'`). If our pipe accepts multiple parameters, we separate the values with colons (e.g. `slice:1:5`)
|
(e.g., `currency:'EUR'`). If our pipe accepts multiple parameters, we separate the values with colons (e.g. `slice:1:5`)
|
||||||
|
|
||||||
We'll modify our birthday example to give the date pipe a format parameter.
|
We'll modify our birthday template to give the date pipe a format parameter.
|
||||||
The formatted date should display as **<span style="font-family:courier">04/15/88</span>**.
|
After formatting the hero's April 15th birthday should display as **<span style="font-family:courier">04/15/88</span>**.
|
||||||
|
|
||||||
+makeExample('pipes/ts/src/app/app.html', 'format-birthday')(format=".")
|
+makeExample('pipes/ts/app/app.component.html', 'format-birthday')(format=".")
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
The parameter value can be any valid
|
The parameter value can be any valid
|
||||||
[template expression](./template-expression.html#template-expressions)
|
[template expression](./template-expression.html#template-expressions)
|
||||||
such as a string literal or a component property.
|
such as a string literal or a component property.
|
||||||
|
In other words, we can control the format through a binding the same way we control the birthday value through a binding.
|
||||||
|
|
||||||
Let's revise our example to bind the pipe's format parameter
|
Let's write a second component that *binds* the pipe's format parameter
|
||||||
to the component's `format` property.
|
to the component's `format` property. Here's the template for that component:
|
||||||
+makeExample('pipes/ts/src/app/hero-birthday.ts')
|
+makeExample('pipes/ts/app/hero-birthday2.component.ts', 'template', 'app/hero-birthday2.component.ts (template)')(format=".")
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
We also added a button to the template and bound its click event to the component's `toggleFormat` method.
|
We also added a button to the template and bound its click event to the component's `toggleFormat` method.
|
||||||
That method toggles the component's `format` property between a short form
|
That method toggles the component's `format` property between a short form
|
||||||
('shortDate') and a longer form ('fullDate').
|
('shortDate') and a longer form ('fullDate').
|
||||||
|
+makeExample('pipes/ts/app/hero-birthday2.component.ts', 'class', 'app/hero-birthday2.component.ts (class)')
|
||||||
|
:marked
|
||||||
As we click the button, the displayed date alternates between
|
As we click the button, the displayed date alternates between
|
||||||
"**<span style="font-family:courier">04/15/1988</span>**" and
|
"**<span style="font-family:courier">04/15/1988</span>**" and
|
||||||
"**<span style="font-family:courier">Friday, April 15, 1988</span>**".
|
"**<span style="font-family:courier">Friday, April 15, 1988</span>**".
|
||||||
|
@ -90,6 +82,7 @@ include ../../../../_includes/_util-fns
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/pipes/date-format-toggle-anim.gif' alt="Date Format Toggle")
|
img(src='/resources/images/devguide/pipes/date-format-toggle-anim.gif' alt="Date Format Toggle")
|
||||||
:marked
|
:marked
|
||||||
|
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
Learn more about the `DatePipes` format options in the [API Docs](../api/core/DatePipe-class.html).
|
Learn more about the `DatePipes` format options in the [API Docs](../api/core/DatePipe-class.html).
|
||||||
|
@ -100,7 +93,7 @@ figure.image-display
|
||||||
so we can display the birthday in uppercase. The following birthday displays as
|
so we can display the birthday in uppercase. The following birthday displays as
|
||||||
**<span style="font-family:courier">APR 15, 1988</span>**
|
**<span style="font-family:courier">APR 15, 1988</span>**
|
||||||
|
|
||||||
+makeExample('pipes/ts/src/app/app.html', 'chained-birthday')
|
+makeExample('pipes/ts/app/app.component.html', 'chained-birthday')(format=".")
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
If we pass a parameter to a filter, we have to add parentheses
|
If we pass a parameter to a filter, we have to add parentheses
|
||||||
|
@ -108,10 +101,14 @@ figure.image-display
|
||||||
The following example displays
|
The following example displays
|
||||||
**<span style="font-family:courier">FRIDAY, APRIL 15, 1988</span>**
|
**<span style="font-family:courier">FRIDAY, APRIL 15, 1988</span>**
|
||||||
|
|
||||||
+makeExample('pipes/ts/src/app/app.html', 'chained-parameter-birthday')
|
+makeExample('pipes/ts/app/app.component.html', 'chained-parameter-birthday')(format=".")
|
||||||
|
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
p Future improvements in the template compiler may eliminate the need for parentheses.
|
:marked
|
||||||
|
We can add parentheses to alter the evaluation order or
|
||||||
|
to provide extra clarity:
|
||||||
|
+makeExample('pipes/ts/app/app.component.html', 'chained-parameter-birthday-parens')(format=".")
|
||||||
|
:marked
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
|
@ -119,43 +116,39 @@ figure.image-display
|
||||||
|
|
||||||
We can write our own custom pipes.
|
We can write our own custom pipes.
|
||||||
|
|
||||||
Let's make a custom pipe named `ExponentialStrengthPipe`
|
Here's a custom pipe named `ExponentialStrengthPipe` that can boost a hero's powers:
|
||||||
that can boost a hero's powers.
|
|
||||||
|
|
||||||
Create a new file, `exponential-strength-pipe.ts`, and enter the following:
|
|
||||||
<!--
|
|
||||||
The exponential pipe samples are in my plunker
|
|
||||||
http://plnkr.co/edit/8Nnnwf?p=preview
|
|
||||||
-->
|
|
||||||
+makeExample('pipes/ts/src/app/exponential-strength-pipe.ts')
|
|
||||||
|
|
||||||
|
+makeExample('pipes/ts/app/exponential-strength.pipe.ts', null, 'app/exponential-strength.pipe.ts')
|
||||||
:marked
|
:marked
|
||||||
This pipe definition reveals several key points
|
This pipe definition reveals several key points
|
||||||
* We import the `Pipe` decorator from the Angular library (while getting the usual symbols)
|
|
||||||
* A pipe is a class
|
* A pipe is a class decorated with pipe metadata.
|
||||||
* We decorate the class with the `@Pipe` decorator function.
|
|
||||||
|
* The pipe class implements a `transform` method that
|
||||||
|
takes an input value and an optional array of parameter strings and returns the transformed value.
|
||||||
|
|
||||||
|
* There will be one item in the parameter array for each parameter passed to the pipe
|
||||||
|
|
||||||
|
* We tell Angular that this is a pipe by applying the
|
||||||
|
`@Pipe` decorator which we import from the core Angular library.
|
||||||
|
|
||||||
* The `@Pipe` decorator takes an object with a name property whose value is the
|
* The `@Pipe` decorator takes an object with a name property whose value is the
|
||||||
pipe name that we'll use within a template expression. It must be a valid JavaScript identifier.
|
pipe name that we'll use within a template expression. It must be a valid JavaScript identifier.
|
||||||
Our pipe's name is `exponenentialStrength`.
|
Our pipe's name is `exponenentialStrength`.
|
||||||
* The pipe class implements a `transform` method
|
|
||||||
* `transform` takes a value and an optional array of strings.
|
|
||||||
The value can be of any type but the arguments array must be an array of strings.
|
|
||||||
* There will be one item in the array for each parameter passed to the pipe
|
|
||||||
* `transform` returns a modified value that Angular converts to a string.
|
|
||||||
|
|
||||||
Now let's create a component to demonstrate our pipe.
|
|
||||||
+makeExample('pipes/ts/src/app/power-booster.ts')
|
Now we need a component to demonstrate our pipe.
|
||||||
|
+makeExample('pipes/ts/app/power-booster.component.ts',null,'app/power-booster.component.ts')
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/pipes/power-booster.png' alt="Power Booster")
|
img(src='/resources/images/devguide/pipes/power-booster.png' alt="Power Booster")
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
Two things to note:
|
Two things to note:
|
||||||
1. We use the pipe in the template expression exactly as we described in the pipe's comments.
|
1. We use our custom pipe the same way we use the built-in pipes.
|
||||||
We pass the value to transform from the left and give our pipe an exponent parameter of `10`.
|
|
||||||
|
|
||||||
1. We must list our pipe in the @Component decorator's `pipes` array.
|
1. We must list our pipe in the @Component decorator's `pipes` array.
|
||||||
|
|
||||||
.callout.is-critical
|
.callout.is-helpful
|
||||||
header Remember the pipes array!
|
header Remember the pipes array!
|
||||||
:marked
|
:marked
|
||||||
Angular reports an error if we neglect to list our custom pipe.
|
Angular reports an error if we neglect to list our custom pipe.
|
||||||
|
@ -163,18 +156,18 @@ figure.image-display
|
||||||
Angular built-in pipes are pre-registered.
|
Angular built-in pipes are pre-registered.
|
||||||
Custom pipes must be registered manually.
|
Custom pipes must be registered manually.
|
||||||
:marked
|
:marked
|
||||||
If we are inclined to try this in a live-coding tool (such a [plunker](http://plnkr.co/)),
|
If we try the [live code](/resources/live-examples/pipes/ts/plnkr.html) example,
|
||||||
we can probe its behavior by changing the value and the optional exponent in the template.
|
we can probe its behavior by changing the value and the optional exponent in the template.
|
||||||
|
|
||||||
## Power Boost Calculator (extra-credit)
|
## Power Boost Calculator (extra-credit)
|
||||||
It's not much fun updating the template to test our custom pipe.
|
It's not much fun updating the template to test our custom pipe.
|
||||||
We could upgrade the example to a "Power Boost Calculator" that combines
|
We could upgrade the example to a "Power Boost Calculator" that combines
|
||||||
our pipe and two-way data binding with `ng-model`.
|
our pipe and two-way data binding with `ngModel`.
|
||||||
|
|
||||||
+makeExample('pipes/ts/src/app/power-boost-calculator.ts')
|
+makeExample('pipes/ts/app/power-boost-calculator.component.ts', null, '/app/power-boost-calculator.component.ts')
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/pipes/power-boost-calculator.png' alt="Power Boost Calculator")
|
img(src='/resources/images/devguide/pipes/power-boost-calculator-anim.gif' alt="Power Boost Calculator")
|
||||||
:marked
|
:marked
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
|
@ -200,7 +193,7 @@ figure.image-display
|
||||||
It is stateful because the pipe maintains a subscription to the input and its returned values depend on that subscription.
|
It is stateful because the pipe maintains a subscription to the input and its returned values depend on that subscription.
|
||||||
|
|
||||||
In the next example, we bind a simple promise to a view with the async pipe.
|
In the next example, we bind a simple promise to a view with the async pipe.
|
||||||
+makeExample('pipes/ts/src/app/app.ts', 'async-message')
|
+makeExample('pipes/ts/app/hero-async-message.component.ts', null, 'app/hero-async-message.component.ts')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
The Async pipe saves boilerplate in the component code.
|
The Async pipe saves boilerplate in the component code.
|
||||||
|
@ -219,21 +212,36 @@ figure.image-display
|
||||||
|
|
||||||
Here's how we'll decorate our new stateful `FetchJsonPipe` that
|
Here's how we'll decorate our new stateful `FetchJsonPipe` that
|
||||||
makes an HTTP `fetch` request and (eventually) displays the data in the server's response:
|
makes an HTTP `fetch` request and (eventually) displays the data in the server's response:
|
||||||
+makeExample('pipes/ts/src/app/fetch-json-pipe.ts', 'pipe-metadata')
|
+makeExample('pipes/ts/app/fetch-json.pipe.ts', 'pipe-metadata','app/fetch-json.pipe.ts (metadata)')
|
||||||
:marked
|
:marked
|
||||||
Immediately below we have the finished pipe. Its input value is an url to an endpoint that returns a JSON file.
|
Immediately below we have the finished pipe. Its input value is an url to an endpoint that returns a JSON file.
|
||||||
The pipe makes a one-time async request to the server and eventually receives the JSON response.
|
The pipe makes a one-time async request to the server and eventually receives the JSON response.
|
||||||
+makeExample('pipes/ts/src/app/fetch-json-pipe.ts')
|
+makeExample('pipes/ts/app/fetch-json.pipe.ts', null, 'app/fetch-json.pipe.ts')
|
||||||
:marked
|
:marked
|
||||||
Next we use this pipe in two template bindings where we
|
Next we demonstrate this pipe in a test component whose template defines two bindings
|
||||||
1. display hero names in an `ng-for` repeater
|
+makeExample('pipes/ts/app/hero-list.component.ts', 'template', 'app/hero-list.component.ts (template)')
|
||||||
1. chain the fetched results to the built-in `JsonPipe` that renders
|
:marked
|
||||||
the data in JSON format
|
The component renders like this:
|
||||||
|
|
||||||
+makeExample('pipes/ts/src/app/hero-list-component.ts')
|
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/pipes/hero-list.png' alt="Hero List")
|
img(src='/resources/images/devguide/pipes/hero-list.png' alt="Hero List")
|
||||||
|
:marked
|
||||||
|
The first binding is straight forward. An `ngFor` repeater displays the hero names fetched from a json source file.
|
||||||
|
We're piping the literal file name, "heroes.json", through to the custom `fetch` pipe.
|
||||||
|
|
||||||
|
### JsonPipe
|
||||||
|
The second binding uses more pipe chaining.
|
||||||
|
We take the same fetched results and display the raw hero data in JSON format
|
||||||
|
by piping to the built-in `JsonPipe`.
|
||||||
|
|
||||||
|
.callout.is-helpful
|
||||||
|
header Debugging with the json pipe
|
||||||
|
:marked
|
||||||
|
The [JsonPipe](https://angular.io/docs/ts/latest/api/common/JsonPipe-class.html)
|
||||||
|
is an easy way to diagnosis a mysteriously failing data binding.
|
||||||
|
:marked
|
||||||
|
Here's the complete component implementation:
|
||||||
|
+makeExample('pipes/ts/app/hero-list.component.ts', null, 'app/hero-list.component.ts')
|
||||||
|
:marked
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 53 KiB |
Loading…
Reference in New Issue