From e78a04522bb8491efb5c812787bafffba43ce15f Mon Sep 17 00:00:00 2001 From: Deborah Kurata Date: Wed, 27 Jan 2016 14:49:02 -0800 Subject: [PATCH] docs(cookbook/a1-a2): new Angular-1 map to Angular-2 cookbook chapter --- .../cb-a1-a2-quick-reference/e2e-spec.js | 110 +++ .../cb-a1-a2-quick-reference/ts/.gitignore | 1 + .../ts/app/app.component.css | 15 + .../ts/app/app.component.html | 112 +++ .../ts/app/app.component.ts | 40 + .../ts/app/date.pipe.ts | 14 + .../cb-a1-a2-quick-reference/ts/app/main.ts | 5 + .../ts/app/movie-list.component.css | 57 ++ .../ts/app/movie-list.component.html | 78 ++ .../ts/app/movie-list.component.ts | 48 ++ .../ts/app/movie.service.ts | 43 + .../cb-a1-a2-quick-reference/ts/app/movie.ts | 12 + .../ts/example-config.json | 0 .../ts/images/hero.png | Bin 0 -> 8577 bytes .../ts/images/ng-logo.png | Bin 0 -> 10234 bytes .../ts/images/villain.png | Bin 0 -> 19344 bytes .../cb-a1-a2-quick-reference/ts/index.html | 35 + .../cb-a1-a2-quick-reference/ts/plnkr.json | 9 + public/docs/ts/latest/cookbook/_data.json | 6 +- .../cookbook/a1-a2-quick-reference.jade | 795 ++++++++++++++++++ public/docs/ts/latest/guide/_data.json | 2 +- 21 files changed, 1380 insertions(+), 2 deletions(-) create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/e2e-spec.js create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/.gitignore create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.css create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.html create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.ts create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/app/date.pipe.ts create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/app/main.ts create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.css create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.html create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.ts create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie.service.ts create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie.ts create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/example-config.json create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/images/hero.png create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/images/ng-logo.png create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/images/villain.png create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/index.html create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/plnkr.json create mode 100644 public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/e2e-spec.js b/public/docs/_examples/cb-a1-a2-quick-reference/e2e-spec.js new file mode 100644 index 0000000000..4ab84e3947 --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/e2e-spec.js @@ -0,0 +1,110 @@ +describe('Angular 1 to 2 Quick Reference Tests', function () { + + beforeAll(function () { + browser.get(''); + }); + + it('should display no poster images after bootstrap', function () { + testImagesAreDisplayed(false); + }); + + it('should display proper movie data', function () { + // We check only a few samples + var expectedSamples = [ + {row: 0, column: 0, element: 'img', attr: 'src', value: 'images/hero.png', contains: true}, + {row: 0, column: 2, value: 'Celeritas'}, + {row: 1, column: 3, value: 'Dec 17, 2015'}, + {row: 1, column: 5, value: '$14.95'}, + {row: 2, column: 4, value: 'PG-13'}, + {row: 2, column: 7, value: '100%'}, + {row: 2, column: 0, element: 'img', attr: 'src', value: 'images/ng-logo.png', contains: true}, + ]; + + // Go through the samples + var movieRows = getMovieRows(); + for (var i = 0; i < expectedSamples.length; i++) { + var sample = expectedSamples[i]; + var tableCell = movieRows.get(sample.row) + .all(by.tagName('td')).get(sample.column); + // Check the cell or its nested element + var elementToCheck = sample.element + ? tableCell.element(by.tagName(sample.element)) + : tableCell; + + // Check element attribute or text + var valueToCheck = sample.attr + ? elementToCheck.getAttribute(sample.attr) + : elementToCheck.getText(); + + // Test for equals/contains + if (sample.contains) { + expect(valueToCheck).toContain(sample.value); + } else { + expect(valueToCheck).toEqual(sample.value); + } + } + }); + + it('should display images after Show Poster', function () { + testPosterButtonClick("Show Poster", true); + }); + + it('should hide images after Hide Poster', function () { + testPosterButtonClick("Hide Poster", false); + }); + + it('should display no movie when no favorite hero is specified', function () { + testFavoriteHero(null, "Please enter your favorite hero."); + }); + + it('should display no movie for Magneta', function () { + testFavoriteHero("Magneta", "No movie, sorry!"); + }); + + it('should display a movie for Mr. Nice', function () { + testFavoriteHero("Mr. Nice", "Excellent choice!"); + }); + + function testImagesAreDisplayed(isDisplayed) { + var expectedMovieCount = 3; + + var movieRows = getMovieRows(); + expect(movieRows.count()).toBe(expectedMovieCount); + for (var i = 0; i < expectedMovieCount; i++) { + var movieImage = movieRows.get(i).element(by.css('td > img')); + expect(movieImage.isDisplayed()).toBe(isDisplayed); + } + } + + function testPosterButtonClick(expectedButtonText, isDisplayed) { + var posterButton = element(by.css('movie-list tr > th > button')); + expect(posterButton.getText()).toBe(expectedButtonText); + + posterButton.click().then(function () { + testImagesAreDisplayed(isDisplayed); + }) + } + + function getMovieRows() { + return element.all(by.css('movie-list tbody > tr')); + } + + function testFavoriteHero(heroName, expectedLabel) { + var movieListComp = element(by.tagName('movie-list')); + var heroInput = movieListComp.element(by.tagName('input')); + var favoriteHeroLabel = movieListComp.element(by.tagName('h3')); + var resultLabel = movieListComp.element(by.css('span > p')); + + heroInput.clear().then(function () { + sendKeys(heroInput, heroName || '').then(function () { + expect(resultLabel.getText()).toBe(expectedLabel); + if (heroName) { + expect(favoriteHeroLabel.isDisplayed()).toBe(true); + expect(favoriteHeroLabel.getText()).toContain(heroName); + } else { + expect(favoriteHeroLabel.isDisplayed()).toBe(false); + } + }) + }) + } +}); diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/.gitignore b/public/docs/_examples/cb-a1-a2-quick-reference/ts/.gitignore new file mode 100644 index 0000000000..2cb7d2a2e9 --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/.gitignore @@ -0,0 +1 @@ +**/*.js diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.css b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.css new file mode 100644 index 0000000000..a556b81138 --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.css @@ -0,0 +1,15 @@ +/* route-link anchor tags */ +nav a {padding: 5px; text-decoration: none; font-family: Arial, Helvetica, sans-serif; } +nav a:visited, a:link {color: #444;} +nav a:hover {color: white; background-color: #1171a3; } +nav a.router-link-active {color: white; background-color: #52b9e9; } + +.active {font-style: italic;} +.shazam {font-weight: bold;} + +img {height: 100px;} + +table td { + padding: 4px; + border: 1px solid #e0e0e0; +} \ No newline at end of file diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.html b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.html new file mode 100644 index 0000000000..e0be283708 --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.html @@ -0,0 +1,112 @@ + +

{{title}}

+ +

Routed Movies

+ + + +
+ +

Example Snippets

+ + +
+ + [ngClass] active +
+ +
+ + [ngClass] active and boldly important +
+ +
+ + [class.active] +
+ +

+ +Angular Docs + + +

+
+ + + + +

Image toggle event type was {{eventType}}

+
+ +

+
+ + + +
+ +

+ +
+ + color preference #1 +
+ +
+ + color preference #2 +
+ +

Movie as JSON

+ +
{{movie | json}}
+ + +

Movie Titles via local variable

+ + + + + + +
{{movie.title}}
+ +

Sliced Movies with pipes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{movie.title | uppercase}}{{movie.title | lowercase}}{{movie.releaseDate | date}}{{movie.price | currency:'USD':true}}{{movie.starRating | number}}{{movie.starRating | number:'1.1-2'}}{{movie.approvalRating | percent: '1.0-2'}}
diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.ts b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.ts new file mode 100644 index 0000000000..d15652f5c9 --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.ts @@ -0,0 +1,40 @@ +import {Component} from 'angular2/core'; +import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS} from "angular2/router"; + +import {MovieListComponent} from './movie-list.component'; +import {MovieService} from './movie.service'; +import {IMovie} from './movie'; +import {StringSafeDatePipe} from './date.pipe'; + +@Component({ + selector: 'my-app', + templateUrl: 'app/app.component.html', + styleUrls: ['app/app.component.css'], + directives: [MovieListComponent, ROUTER_DIRECTIVES], + pipes: [StringSafeDatePipe], + providers: [MovieService, ROUTER_PROVIDERS] +}) +@RouteConfig([ + {path: '/movies', name: 'Movies', component: MovieListComponent, useAsDefault: true} +]) +export class AppComponent { + + angularDocsUrl = "https://angular.io/"; + colorPreference = 'red'; + eventType = ''; + isActive = true; + isImportant = true; + movie: IMovie = null; + movies: IMovie[] = []; + showImage = true; + title: string = "A1-A2 Quick Ref Cookbook"; + toggleImage(event:UIEvent) { + this.showImage = !this.showImage; + this.eventType = (event && event.type) || 'not provided'; + } + + constructor(movieService: MovieService) { + this.movies = movieService.getMovies(); + this.movie = this.movies[0]; + } +} \ No newline at end of file diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/date.pipe.ts b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/date.pipe.ts new file mode 100644 index 0000000000..d95d797ee2 --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/date.pipe.ts @@ -0,0 +1,14 @@ +import {Injectable, Pipe} from 'angular2/core'; +import {DatePipe} from 'angular2/common'; + +@Injectable() +// #docregion date-pipe +@Pipe({name: 'date', pure: true}) +export class StringSafeDatePipe extends DatePipe { + transform(value: any, args: any[]): string { + value = typeof value === 'string' ? + Date.parse(value) : value + return super.transform(value, args); + } +} +// #enddocregion date-pipe \ No newline at end of file diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/main.ts b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/main.ts new file mode 100644 index 0000000000..ec4c9d12d6 --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/main.ts @@ -0,0 +1,5 @@ +// #docregion +import {bootstrap} from 'angular2/platform/browser'; +import {AppComponent} from './app.component'; + +bootstrap(AppComponent); diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.css b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.css new file mode 100644 index 0000000000..70b0405200 --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.css @@ -0,0 +1,57 @@ +div { + font-family:Arial, Helvetica, sans-serif; + margin:20px; +} + +table { + font-family:Arial, Helvetica, sans-serif; + color:#666; + font-size:14px; + text-shadow: 1px 1px 0px #fff; + margin:20px; + border:#ccc 1px solid; + + -moz-border-radius:3px; + -webkit-border-radius:3px; + border-radius:3px; +} +table th { + padding:21px 25px 22px 25px; + border-top:1px solid #fafafa; + border-bottom:1px solid #e0e0e0; + border-left: 1px solid #e0e0e0; + font-weight: bold; +} +table th:first-child { + text-align: left; + padding-left:20px; + border-left: 0; +} +table tr { + text-align: center; + padding-left:20px; +} +table td:first-child { + text-align: left; + padding-left:20px; + border-left: 0; +} +table td { + padding:18px; + border-top: 1px solid #ffffff; + border-bottom:1px solid #e0e0e0; + border-left: 1px solid #e0e0e0; +} +table tr:last-child td { + border-bottom:0; +} +table tr:last-child td:first-child { + -moz-border-radius-bottomleft:3px; + -webkit-border-bottom-left-radius:3px; + border-bottom-left-radius:3px; +} +table tr:last-child td:last-child { + -moz-border-radius-bottomright:3px; + -webkit-border-bottom-right-radius:3px; + border-bottom-right-radius:3px; +} \ No newline at end of file diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.html b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.html new file mode 100644 index 0000000000..d89cc0e3fb --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.html @@ -0,0 +1,78 @@ + +
+

Movie List

+
Who is your favorite hero?
+
+ + + + + + +

+ Excellent choice! +

+

+ No movie, sorry! +

+

+ Please enter your favorite hero. +

+
+ +
+
+ + +

+ + Your favorite hero is: {{favoriteHero}} + +

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + TitleHeroRelease DateRatingPriceStar ratingApproval rating
+ + {{movie.title}}{{movie.hero}}{{movie.releaseDate | date}}{{movie.mpaa | uppercase}}{{movie.price | currency:'USD':true}}{{movie.starRating | number:'1.1-2'}}{{movie.approvalRating | percent: '1.0-0'}}
+
\ No newline at end of file diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.ts b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.ts new file mode 100644 index 0000000000..a4a9c69e41 --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.ts @@ -0,0 +1,48 @@ +// #docplaster +// #docregion import +import {Component} from 'angular2/core'; +import {ROUTER_DIRECTIVES} from "angular2/router"; +// #enddocregion import +import {MovieService} from './movie.service'; +import {IMovie} from './movie'; +import {StringSafeDatePipe} from './date.pipe'; + + +// #docregion component +@Component({ + selector: 'movie-list', + templateUrl:'app/movie-list.component.html', +// #enddocregion component +// #docregion style-url + styleUrls: ['app/movie-list.component.css'], +// #enddocregion style-url +// #docregion date-pipe + pipes: [StringSafeDatePipe] +// #enddocregion date-pipe +}) +// #enddocregion component +// #docregion class +export class MovieListComponent { +// #enddocregion class + favoriteHero: string; + showImage: boolean = false; + movies: IMovie[]; + +// #docregion di + constructor(movieService: MovieService) { +// #enddocregion di + this.movies = movieService.getMovies(); +// #docregion di + } +// #enddocregion di + + toggleImage(): void { + this.showImage = !this.showImage; + } + + checkMovieHero(value: string): boolean { + return this.movies.filter(movie => movie.hero === value).length > 0 ; + } +// #docregion class +} +// #enddocregion class \ No newline at end of file diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie.service.ts b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie.service.ts new file mode 100644 index 0000000000..2b6538d985 --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie.service.ts @@ -0,0 +1,43 @@ +import {Injectable} from 'angular2/core'; +import {IMovie} from './movie'; + +@Injectable() +export class MovieService { + getMovies() : IMovie[] { + return [ + { + hero: "Celeritas", + imageurl: "images/hero.png", + movieId: 1, + mpaa: "pg-13", + releaseDate: "2015-12-19T00:00:00", + title: "Celeritas Reigns", + price: 12.95, + starRating: 4.925, + approvalRating: .97 + }, + { + hero: "Mr. Nice", + imageurl: "images/villain.png", + movieId: 2, + mpaa: "pg-13", + releaseDate: "2015-12-18T00:00:00", + title: "No More Mr. Nice Guy", + price: 14.95, + starRating: 4.6, + approvalRating: .94 + }, + { + hero: "Angular", + imageurl: "images/ng-logo.png", + movieId: 3, + mpaa: "pg-13", + releaseDate: "2015-12-17T00:00:00", + title: "Angular to the Rescue", + price: 15.95, + starRating: 4.98, + approvalRating: .9995 + } + ]; + } +} \ No newline at end of file diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie.ts b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie.ts new file mode 100644 index 0000000000..f7e8c0a7db --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie.ts @@ -0,0 +1,12 @@ +/* Defines the movie entity */ +export interface IMovie { + approvalRating: number; + hero: string; + imageurl: string; + movieId: number; + mpaa: string; + price: number; + releaseDate: string; + starRating: number; + title: string; +} \ No newline at end of file diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/example-config.json b/public/docs/_examples/cb-a1-a2-quick-reference/ts/example-config.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/images/hero.png b/public/docs/_examples/cb-a1-a2-quick-reference/ts/images/hero.png new file mode 100644 index 0000000000000000000000000000000000000000..b60c3ecc30cef985cca79fe5311994b7de11c45e GIT binary patch literal 8577 zcmZ{KS5OmN&?o{TT|x~Iq+^f(3B3!_i(u#_Ac0V&6ObY(5JK;vH|a>P(h)=NO;DN; zx(a+0r3mWf|7Y&QeYg)hJ7;Hh&+ggTHhW^8>1)zZvQZKd5z%OCsTmRx-J!k(FgfWh zm((L{yc)D|UOL@Y1sIy~SGp3mT&@l!%D9UTLeT7zZpL<_G419P%l>v0 zR8>%A5K{P`ZwP0?u7;{AiP+8uYHBp~3nQ&3y4R%N^RlrT8Ppap#?A3Ff|j|0fJo9D z17JCqSO%BeK8lh`HaS8T$NFvD#(*8!m7ueE&p%%|h;*!y8$MEiCi+5&v_QfHrT9OQ+5`rI1LFL=$>`TH%}^ z*x6p0H8A7%{cf{ybY?O!KfmRB`8~71DuAdi>ng$?SST=jH)Q zu;+;jm1?GI^IW~}pvnxB&+7-dT5}>ga-+K4AsP%apA+6LT&_H>|NB~#?~qFRBd=hg zN^`M=;S5IVzg`*+CHJq>yl5SrE)!ww?p5to_uf>=bsOQ#hHvhJm%(YE3$3%@;e*+g9AMYpt2JpNDe~=e^-40k3ZkqUgR^QNJmK z^_c~9T#NJXJzJ{GkZQmZrNjl!)a?d)g2oj2KnPkZAEw z)+i@bBJMg?v_=*epGWdR_;aknD>mvc>A zGU0hy$Q%F~mqNwRz?8l@a;8W&Kh+Dij#nRXE7}=)kxgUXrt2lu?^bfKK~>vo**~ZC zUbe7ZJ;&0pivc=@3SW+>Dxrii=Vd;EkhxGV&Q zhYB~b`)e*&hzxMMB}ul2{&WwA_s-pn(}XJeWam~qJWRVknL;BKFzhL9vz65%s-ws( z@ywl_;5n!CCmA&5Wi*QKQ+_zz`m-#=pNB#KztNgyL zDY@1kGv_!vFv`Y?uLKnyNN@B+cy!9#rs1jC1F}?+&rmtp2fG!k!*uBpsI&*i=d8U8 zJdzb(A_;mK-ZuFcG!tF|QD+}ygl1t3{pg06+{?fOLX&nw*7G)uFLfhT|7)%4tFIv1 zJ*|wU$7FIwMx!2g5@-MKSz789MO-mcDi+R_`l4&fY7=R_I7_W;Nt!njfn0&bjVM>20K1jDHn2dQm@M z3(PM(wJ(S_x01zFTjUwOcnTUY#eH!H`aerDXwn=XBbKMtk% zZIk<4Pu{7~=dtj_nV5Aw)@yl-%*_q56`zxY2@cZ&=i@_X?^ur^Ywx0O<)*{Hk z@%*qi$ zK%ib9Z!yez5D8SlS7xZcKR}0O>6(nIcNzX0>U2QLjGF!Wi5_dktgpzYnE@hM#Y-&2Eq}eF>Nj96 zuN|42yq{g0)3VI*!8CfzmdwLq`;sLCT+#gJ#IxYEGta}~RcsR2;(+>-YunE>^?T#( z=FUM!r0iwF)3wPutw}{DKMNek7VQA*fF|a&ykW4k)N81nx@0zZLsvCtFKrN0TOcrT7+jwJG!ncZ^;WD@C4-uip(;-AbQ+PQpTeUqaP^*E;|D>)*yOxu zS;Q$Z;xbH`Bp@t(6{|A(`*A&UE!jgtZC$_9I8k5zFWq$5FXf3cVcvi`;Et4;19E=8;-uU7cL&NHPJTPif6E z>Pxl$R*izA2SPJH-EO*c+l`&WZidk!8;_ri7x#(ZlsO1B@EplK{h=PT^!$odxc@Bu z5cqZDnBV|MQ8|gh-!t>~d08ZAhgPz6TE>j|Q@{Ka7xCpG>XF>a6`g7Z1TCb|cI8TC zFC-0qT;k`2f%m*0*(ow&-Rkd#XGF51zc5GfCcH2S*7)(PzLLD_)H}@JSibs;S4L3Z zZ>zSPP65`e0~O8fBeAk+T+n7 ztEhO@GJL?xin{+S&)`&l<15)<)6+_u?3usQ-YO55@M}e+ED!q;L)U=`Pw>O;E>&^# znrv+_)`qqr7tjHHIQC^3*Gq4^i~LtYCnv01HAvp;=A2nf(klK7-m6~Eb$x6_brnzB zOYz2Wv^Yn{z@B&dVNO5sdIkCR6(fsyYI~0>{3ecmJ{vLozVA;n2tWEpkmgLfK%)9^ zs12ws5%t-Y>K|L8V{;QbveE>XwJ`CT+?y)6JxBlZe!Z(pyF1n;COo$C5*iRKEE3!v z^QS!zZsJah7m6Q?-F=M>dVf!*3sgC2z?QxV+`|ss#KY?<12p$26L(BbDe_g~3@xnv zN{j5Fqw3tHv*Tvjt~7`5glXE^PCR228&wsy&yK_)o4MO23?c5_O4vW&6$ou-sOXBW zxbd-)-qjy~4ehlho83q?AG3|`Y=wHK2B3*fwVwQp;wG>+Tl3)uQOXm#9AI_7Leyx z<0Q_oXm9aHe1zwmKu7B&q8<|${@LR97_&wOr1{csLuW|Nz`M$+lGe|9;;h5))W@fP z;^(iVJi?Sko_5yti2*46GImUkcYk$^Lt%_Oouo;;&g@KjCp;*5OE$d>J;RS2L1`hK z^YGu5=bzg$-8Vwhe17*ZeyLl;uk(!Wvv-(hZmh@H%R@!u5&=#XNGl)zi!*9ZjrHGqLN;<71CD+b_Vs!-msQ^ar0X9GwTT{Gdo6Y zn8#Y=S<_B2DzNakr_}+z)^bxlf?%8XFLz=vm~7j;*1SIY&;u9L*$ar5C;v2p<3H1F z_>{v-5kg11rBnDsl2O~t6-4z8jgjIFNzcxCJeP|CSL3h7z9iRIn+aYABbx#GDGx^N zF~t9-{?=@}6dDLc$t-O`5u24b?9u6W>=odiFGyN!F@Q;-9pQuBci*e&qpcJ~I9ngv zA{F=-7Oq_uKdIq!jv=cy4t+wp{zHQx&Djs?1V-N#9)i%T}ENvC=bF`n36PFcou9ID`&%kxB=ew6@)zzG??Ct>&|txYeX^ilu@$lOioyDpNx{}j1-v+o zTzJm(^H!+q4Nctbh-gpFwEE&Z$IOb{e%2c3Im(2?1$W6L1cpy1mI1`xc9hfdBvk9+#8l*Yc*l(Cj`e(Fph0Jr4Mw;4Tnrk~AZ_Dg!nGVyf% z&D&$>Hf~-lYGf}Y_iK8M^SU~9s|vJ94*_J7GCP#yeYC$bd0jhTlsAd!?GvE{v4-D0{d4NFQrHm@8Q}I~mEXe{%RmTyetMPsuMy^apJ;+U+;<4@A%4 z;UGI=FbuNYygFv8(L-a04Bn296|fM$T$VCD(NCyr5=0E-^`YAaLO;s?XaNSumx>gB zNZfKv-a{8Wn%?kyjLhmD{opGgE`y7+m=vdmqw)+JG=KDFSr{ahUdd%jQeRTK<>g+E zzxnid*v$Tc{4bH_SH6UwOu6pBxQ=T5$*;D!$9pid=W5phtSWj=&*K|H_>Y2OKD&00 zKGJwqSRwLP0V-f{^W*(rvq^*1EufEIgfVkql7oUxhI*GJ)obh}lR*^g_11*83AvbgSSwU$yD`nP||(sCLk&>g{cPF@Te6s?2VH||BBFSiglb^cp-MyVKt!){t|Vhq;EO)Afo2jg&;82$=woY%h5pUFUb8M@ znW)wYT9a|0eOA($u8l3S<_cD2YAc%}E}M`YpH`%m2q1Hv7zcZCWSU`0(FS)PLsd^o=KIkzz8P6FcCNMsgFrcAB@BB zuAIZ7f=KFS{jmWpb<*-P3n|z~sA{}72WKY2_*0I*%qaAAnk8CEooN?%7D`J1?#@qN z@KbHwk2mcxg(YiJSgATkwySUA76Siq6q}z^*K?2yIKwcJnNL6%fH!b;}9c2i$ zmu=-o@dWohAI>yt@iD&XOsK-ggU&YYZ{Xkf$5W`6GcSAm22*sWXFTeM7N` zc02OO`?;f9eHjJlR|HyYlrxYDVLySJB-a-E+adi^Spy#*$(Pi2*Oj z+%0j>w&vbtK)MP1=`v4JaD#nJrB@it>H9qWq{(C$uEAY2WAHDo~0HS8hN z@17~8q<n+LR<277R3N%&IZGq^BX&lO`sU&|LL!!P|HT z2$eg-+Yf!RJ=0A9(GvpRFZtZMG<<5_GWunR=XXpLa|Yz5zfyMo7YG{h97!!RK1Un( z2as=HqzCZ+Xn33u_ZcY4TL z98Suk2|Nll@m)!?jx-Fwbx+fa9jW_yFe_9zWb7E)w?9c4Q07o>hrMzicby%JW`)dg!YP`=`}bhsMgp_ zP<89AD4}X|gc!A^9`lI<1GFm#138YGG@cvl^otlyT>J+>5Zx&I8x@o5is5B!_E*SW z;_mHUhPVc^ZH3pevW>&*oU~E_LljTezuMmQsNS)csh*5GZ>}T4Nj%{;1MVi|Pth0k z9Mv?i*l_lTO3qkJ3l!n*BMUy=ya$|O2&?+DL&x%pKk|Qt9&z4q=mQ3 z<7%1aybLk9A0z!#-hm@O_pX(=sn(r*pkUh31^5&1oE02t;yK77BEM^YDWW6Zte=V?z9&pve0H|@~dg;crjsGk+LFCH$2j}C7FhK(Qy zm4U)T651UeyeQeiNo#A9DJQPe*wnw|TZ(Db>0sjIhw_%nQRxB^n` z1ZqrTHa~-4=IyYIq1PaqbbuAp?J)0=vM{VuxQHP6Ea98oG$Y0V198 z&wiy6-TI6=bZ%Asf4G_;8jr03=Q?#@cn|-b5qb^7NvpBpWK7L3oni`ACjO@p|MTj= z;ah9?O8nbm@OCNYIdC_KXwn7; zjsqxHv+%-|r=2wq?h{p zW7T}%SI#1P;*g`hPYF!?I&6~3ywtNBr&62Dyg@fTclhIiTI^~Eda#C|+uGEBPqsC+ zl9?Bh2rj0wf1@YMq0S@*(fH|a&}bRcV`wiyrr7jsvr-ugO-$^rh)zO|^SIUyya&3f zcs}1`(a3mFR?v7Y_<81wyq(;iDz0~$H$ote$#~MKp%}AJodNqvM`@GzPXeJx5MZgj zzeV{!wd&umk=uEXZ9KLOjRCLWO&V%5i73^iO zS)r%%KNjNow%6>7|4q{5{lNOj#Zqpv4E4|;zVocpc#~=}%E^6BOA2TqUVlFa*V5!2 zmu7ACC>$wI+hgZWO5xVMXRTM18S3GrcImveePz}8jZf3GHpTSm4T~CYzcykbg&G=m zXM4oZE?irO2%TJ(2H_unysx}xvUp-0%5X}q&tiGIF3<2~)|_<;1P4-6;=n{?7M-_y z+#04v`&44lW4gykDml5%aWcWNkpRO9rFd!!$7B`za9E)yD|$XAaSCdWn^9c{U6{w~ zU71fA49#!;ey; z;D2E?|A7@ogsu8ZAM9kbN1e;Q@4xa+nyA8I3A~j2RFO}Lo`D%D|1T=;x#TR*74AK= z{grq7AweFkZjQG1ba!{~KohB>T+j|EF1tXkXGlLcE+c0LA9th&m!qc-m)SE_Hy1CY z4;sSt%+Jov#hy#e(;eyJAu;*8>Q)T@|A;{$(GGI literal 0 HcmV?d00001 diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/images/ng-logo.png b/public/docs/_examples/cb-a1-a2-quick-reference/ts/images/ng-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7929242740ed3bfa668b534f4311981b57e8788a GIT binary patch literal 10234 zcmaJ{g;P}D+uvn@rI$ufK%`k&y1NAw1f(13mQE>YC8WEhYw2D>>6DgO8l)S^cfY?s z;Jq{Fo|!wJ^PKa1o}4o`^1X@zJ`NQQ006*Od?TxlnwwE$01FfK)+d6ZCL9hM8JYKr zGBPjUyEs|e*joSqUW-}Do*zEUk%y0Wc>3gxa!yhDB)~WWFJLdJ(bb+=Vm=!J^y0m< zk0_CpB_aaK#pMP93-aDnM3~XBl$b!?5WY9#j4CNHm!DPg^Y%X8+Pd!VSY5O_cD-Kk z&1rxE7*uIt92m)HFVmQjU?0KX+Mx;)wGRMHuR!1r0H^L=X{XdtwB(hfb6V#(mrND#FTr|6ZvKkrqZB^1S--iy?|qJ~E9%>3yGz zS&aT>QI0?Pg4)P|IgNhbdZxz0pgq@hgqLqv9KBheLLUaDfy$2vr)V7>#nch9Q~gi& z+~H{ifGCDWT)_%2qKt^tJ_vyu(Wwi-xv-f-a2uE08IHa#(^6PydEWBr6s;Ae9P4Q7 zFq-S@!kr+97L+HEkTkGaw+CY#EPZRl4~VvUd`VE+yBT=?>`w;z+&j8^@w3nVwkc@3Q0E3*rUDxSPZ|imM zND3@muWE+&>V zxITgZB--~Rcv5|?Lp2b&bs{9HCR<`X)Z8wp*5++r6`0Xe;OhNU8u`R|psJT?7teB; z1K=CNdb6C1wz(r7m`?~K_I|%~xq7!90>N0%p!gwND|nrQ@o-n=9C;Hz_U-P)4)L?M zR@nb2qwUu1uqOfm3_!905LqtJEr^a2q=g_CL=&h%y9qKOB$!1bj{pw_Lb#=1^LRLt zMDrL|!AkEzf2HWHfy|O%L3~)?FjBY~`zR1>g8nsR#{{z-cut6JO2;i5v`MG=2A4Z< z8Tv*@J-q&<;TsMYTuP}Q@t!PrQNj5IcxsI-svoeTLX~73B*_Zc z)D+YXOK7Iqr&(+MIRA<%e4*oLFP)s6G+)RVpgl;T>+dW*blcb!1AawB3)wPMLFRjmUgS*wbC0uCkDN3Yr?I}6|Aw|Wo*kS z=O<05OoUktB`Gx4Ni(nrpmIS9h`KLgqAeRO0D%*BVAKV?drXX=1R4nnzvr) zkM)x8x#~Y$v@Dd8@@=b!G}$%8if_Ndls)sAC!xDy7nFRAe5!nTdX;)zi|ws3J`q0I zKIOOc_`#Sm^jZaP3-mwAYiRz~=FzUxJ?|tpiq0deZcr`Pwo}np5P9pH;SqjS7?T;3 zq7tK0Hzs2UuL^NYcg#9+5c^6a!=ZK@xbn_lXH{Cls7vW73}|m+gWwZ1;jAI;nD$|H zvRR%omHD2RU>asxw^l+lI?&HDUedc8TKnVEms7_LqYYIiawbKlOD4!$i?`aT+i4zY zkG4OYesPy`w>hZrdkU;tuh=}gq;+$T!9#|R^xnVrV{g=T)Ay^dhi~dP>Zs`2=*j78 z>f`g2;04HYZA9@cE-v^KT-xk=@+b47WsvZ9%~LHhE%Gm@z~*$vbd9?FMpTw#Y_#nJ z%v76V8zsyo)^oQJZY8c>>m_Rg9`??e&Qq>R&cfRlJqvwl$4lFyJ7yd3m92K@`rkFZ z-Nj?34f1uZy{mb{WwEi21^-{YJs-3By;bXrn|2(>O*t$$lC=xwMsUi>_O&m(652!B zp&dClyLTu4t$wDfWSzc#v{lo3gZc|=;QRLbs~fSixl`5iCvgA?lJ-5>3GW0ir$CKB z1TiVuH0cG?yiha4jZ}nV1ZSbh2X0>OdM-EE2ww%Sy?N4U*=2cEIP{BauLyk&Q63RK zQC<16*0G@&jSZ15p-{cN)w|jBayznFrb;mqM#`UGg(<(q5JWphJt8hX&T?6OY&R?W zXsH9M@UPghSMZ?pjr!Qny7jhi@n`Zcm0t@#4+_bGBQZp)DLFq9nG&+r$sV zu?#SVP{szPjqe2ss;A~&k?q-}Nr@GSK_5bJ6`%LpfSGIeN3l0Ce= z#C8wW4=td)qST~x;*sG|wN$h^h2O$2>paa>H=B3-ItUtK8mdIJ**#s4c72L38=mLl zb3Jbru(cmq73>`R_0dX|I&JRM}Q) zm940Wc?SBMoaAnFCsS>u=ciwXH-{h1`b;;@*~}%;{(3PccwaAG-+68KYwjC94!#^d zZR|XPTUvtdCKlCT}caYGzpO|%8SpD4lSAOT+eug1v7(7NGjAzum<+Fe0Q2l4_xT2kh zla$-dQ_#h06LxpB*-_}racs4e6Hv29cWb&vU#hSbn?y7BP;&ioKVoYjO>J(nlUYiY z=48td6v$_km>7ElYLJBflrCuAAGD$tPFBHw0<}Vjmqi zfJmSR)^g@_hv0jKG36npg&nrfZ9x|=9AAlMy)(z2dE-^W_-rx>%5}D6TVbu(GV=-l zoJ;h-MTUvAhVP%axwt$aMi;N~&uGYP9nXL}mO}E`d8WqAujYi%yJ=WaK&*F4aj=rT z`%@V6zxN@-9X1lWQ{CZuY{+Gk{y~i-6_=H{7Jg!ra4d}J_!*D0ZJ(4KeX2#=&Rha? zXa274h_PeN^*&o>Azz!S4nmXg3DUos{9l)LT*jSVDd`nTSE4(MACL)p*W=KOr(4x- z4wWp>Dl=B2mpOYG)1j(-0_}8ieeSK~8-^~D5Cq&T|Cs78b4co`P zY5Oj!uAF(ZAS7CiQ?cq5b1M98{vlS)eqq(ocHq6gq{kUe`wcr)g^X>K96e}kbnDrI z6z=pWnacg#9ubi?@BouAS|T!Hw+@#h{Y~$Oa&XBdo}j=mC)}S*rK-Ay1TrPjPYXH_ zCW)3Xk^8uh?dhJ7v+n{}3aCOv;3f&GX|5rTO+PmRd?WhS<-v~$K0S5c#Y_KO;4}~c zce+>PdyP7mV!lPit*`-Vz&P#}oz%rY*D1aMjZ#3!pdF=5`${+BVeR=$0l>i!bsVgw z>qTltX9`Pp-Y<6{K$Xhp=y-Nb6_-!Co&H|vyg`E$(Ih0q>(}c?+Rw36L*nxYv=MFH zF$u-ctj&8yj2N@J9vHUmud=f4sLy|pX9p91TSW^4DInO&hy{ZvqAZm529ZRr6x%vk zmVt)fLGYhJtD36K+P?`6@B~U)yzQrOr^EWQvFrv~sAG8#`pY@Zw*AWaBr;7>7|6Bt zvt<4nWdD3uxMLtFGdhYZVpl>klkpbVEa`h3z{Yjf+oG$hON42EoaAO`WLvvAWp=s| zHaxeLWeLm}d=kCK`uQup7LrDA=2)|_NvD_F`4sy#xE_nT=~}537Qn$IU;{A{ZHQ+P zdImG&inBM=oWZz>KW2N2>osoV0gtR&c;aRh@(!diNm@J%z-?lqd>lno5a6SM{cmu&4sN~rv}mpiWLBq7;Bc|sZ~wo z03C1di@{>n(puNE9N;XV4u_s!!GJtxDPE*2@Y-_i2hR_3j%?hCq2cqH35dFkWe?*Iy8M!2VF?Sc5Z`|Lb#(^nwGR_RQG~S5-J8+y?)6k&?tH>3V1$1C{OoD zkv`dpb!M$n`U=O(=|Uw!o;LBlZNn-UsWk37oIH$q@8-Y`crH0M4)u$$Ok7we8;5H8 zoC0@pR=9SvCIi%`Bq;)+?2r`~@XW%B3I_4>UlIfpLnDedHX{U=4BIcsg?_dH$7WXy ziv_Yk){DQpnG%z&w*8basF=&jfqJ^-un3j(Q7PVn!ClhWjp_9z?ji;6DKPcF5ir+t zWge=*@8^J;<0Xl8y}#CtnK^Pdgy(r` zka6I=6@S+QtcW)^Ny~>@WXgs=4H(7y;YUrNF(am6*Q1IwZKmeF%N$yt_>@?pt%REn z7ji-gxC0g9i^BY$Vbz6-3DWwC2+KuQSXb^9hf(Ryw4i`3ZYzir42BD zI#2#j!tHpM<(7C4&|nw6OPw2eY+>;LK^z3Es8179Bn8RxguD`MO$yy7<{hH~%K^M|c9va)Zp&)`@WUG4`_I2$A~WJ6#+ z34=x#Zgtpcs`8-E`wY4xqo- zUZe-Ctbb+rMa2vXcD`ataA+nzkZVC(V6*4I@zp%;7%b#*qA+TwMkMp2Kxw9fyRTN%>7V(rXPh%n1RC?DBiRr zILVQZ)nLb@zd_N!l?^zv826OTRd;yrb!?F|nZi&P2+=_!_(>}UJeE~a@y2Iy z6z^tX%7X4cJGKENSo%Q}AcI{vb656BX0Z40#Lvg-+$4|C-Ui(mFbrMr3C^5^;a5Gp zjCGz2%tlba-e*x$Pbig7gPJ}@Z+ao`e@cjR_}bR2<8wMu>eTynqzX$GPnBexN0tJg zUag92#(RWa^rxIC&@N#)-w!^Ey-86ben3eTG6442*FxVLV9O!y0)U)j%&0_GbVQ-tAxg+;J zf4gX|6=3Xs-7%r`{KV)4A?iG6bd&n!3lXOitH!fz@pp%`-0(jI?P-^UC`6pxJaGj0 zXdIUoaoXcx*?OS%apmlyLP#uI)7bq9ghD(+g1uqXbEnoe!9 zmvD}=WurPEIdSjOGTO)}O}ZKnfzu}L1}WTtMAZ-AR$17M2Bln13-@Eb%i_g^$hZ7X zt9k87R}>%Ltp!28#khk11}W3{>FAk2jup~NIGqMFAHh`}YQ)IrG`_@oHc7t7rKCZL zGjQ_+QifaPhLe%r4sS&NHl{9`{Q9Qd40S-CYe!V*2`E-ifKvPxG>EAU(a)1Vt4tez zO~CNF{9=`xG@AoHVn|Q)Lb||wdpw3`CYhO7Fe@GURl3IyaZeZp6&t2!q@b16YJA~# zA;b`aF(k-!fh75VDvCa?L(hQ42`%+OT6(7j_Pw1S)`OH!d)i>WSD|akP`+(;k#tpW zIop?kJab1oSI6O6dhwYVP8lQTh`Yg4gay9%K~Hp3cY6_HbbVwYKWCK|`PR|*pQd#Y z*`NS7&#^X2T*rZwe${{lN_$ssm|;G_%ID%&h?MV+WtRg)DBKC6cGsGFf?t<4MQpjz zKr?J1xtym?LTzQascdLxE)GpFL1e{C!y9_|+$k&#tm5G;>U@=_;lJgB{LbMkjw&5g z+w9){%o{l$FixD7LP{Gq`ty<+|M2UceWjvl-elJ%`L6C5Zn1)IWuB14qMo6J`jY|)JLxD#6^mhdX;?IYKn zE6+EAu5r+vSM{r~#^q9*Wc``vmP*)=Z;yNe($|k29tvVZ!v|jX?a)E|;!sp?CqtXo znhZ)${f3jP$rW$)T!6;>Zs_i(Bb3%f7NRGjf9!0%klalMWCDnDcGhEzc=AA=mYv=% z87O;JwYm9nc^KHSj9uGSbQSLK$79f#gAkDt+dk_nQd*JJxHMnB$eGVm?dg<)(sP7e zy9&cHpmXbV$9Rg=ndy4;etx>L-s0Ip)ekVte^@imwJdFiT||Xn;~ir!AGrNs@p%bB z=!WZ^O_m8#{6xbR#b=Yj=*U>W{K$Bd=tH$Gywfo^kVp4v&)|3C)KuVH`QCrt{ERw- zb0qFOnI{ofz-e{R!4nhT8B+yQU9PgeZs*xFsDG|(FKC#`Z{DfC8=REww4hh3bTy}i zGUGSnF#!wc;T*p`tRJMR_BSZ}G8x*C?c{wi*&jmS^{>*C#VEJSchRjED9+q{OKE~I#bjC@$iW`d+S#@Z`ik}e_Z(< znV_+XO^IB6aI0^66i|jbu*$nJDaZ=XTp%nQS{7r-w4Yh7xO{9dYv#z3P(AFr4T}R- z{X%I?gXoua2n(S;x|1a0q z38l8BAZ_f5s0eLaBBjoQ+UuhY?%s9_!C#SoZI?lvB@_Q5$!VHja2U*?LNvVzZ*IaD zdRWmOOc4jp?mk6)O!7g(8x8n~8QIrFohZlhuC*2;ZEPeiH-fdEwx;%yp_VIW zCq%jPs!;Zg%KaHou`*^GIgOXj{}`IW%bU|$=Z;ea;LqPT zf{IHIgOpcYG$Wqgd7dYC`JfN*d7;!|u2oQm7~Cd9quqm#w%MUX(!z@jcRnYfTN=%6_EB;lyCOqtSHFXe_@FZ2k>{}H*RlVlOPgOOjZ>}Q{eIB+ zXii}f80LAhW+phQpU!tNt#qfOG~}S?^IuSSr}tW{OpWBFXzBd|6=TDur$8wUTeh(@ zC@H*7gQ8)ZBUU+f-|?Rw-~JXY3g&D5x1i{Ag5a<|3>t1dScs&khNO58|K^dH-MrJV zLw0Ldc{>~E)K6786EmZ@EJ^~y?1nWPLNaMlb>r)ui}mz496gpW?IALIz_lfBT`vcB`aea?WK`B1(Fe(~nCcENs zPB-YGLUQmbxc5IL%UESYAhx6WL(6<6R*1CFEG6xZPpdjoti( zUEBP9lL22>(OA1h|LI10)bM+>&b_oqw)&}TTwCZNPO+VKji|G(epRPuv*q(osB$i0 zg}LQRfPs8#thi6KB~iRg`xbYF$NS)B$OM&Yz_iJm6rJ|<-pbX@?Hg4!7)y8Uqn@ig zAE1Y585;%vL7EKSQKtIGPHwZ0S3ihbGisIqjK$ZfevaRqHcma-xV-ONrA%%wW~@@4 zB|V`@5&PHSyCI*^gcsI~$A_xLrJU%*6>url3eg!3k_JAm! z`|Z|lm6Z|Z}2mN8nyt8{ev(YzYWOT3%L6r(&n2(^0VA0vOmtRI}kb_yjZPYi*GoaVdB zd$%{G0q68Tf9zMn5It!|#VH(wt-~V z{2`!uP{sbM_0zO%jw+8cUsmt#YpHPBFcqg+F~zM!<^z1DrbhxQq;&a`P8%mEYaL^E zSuxiW3i^jNoTS!d??!Als+E&LP*A;P!{H4Y^JiBtRx2#$yij9Mm zcK717`iAZsRo5VReq=t)H5lY4c&^eZLU-Dk>;B2_k$nEYi`j&p%9 zkEpt$D8fzh4+(!JMN(ypy|Hg+_|UN9>{2KM#S2WW!3ca8v)^bgTAhbH+YK_+bWJZl z70jixD^~0xhUG03*}z9$DmKLM-}<|xJ1J}i0}Cz|gg*Un#%R!kD#fRvWZ1-S-^|K*6K{b?i!>;x6@Y_V&WAwkGhF z&IIk!JB83+n9={tV+fYBDelwaOf@$sT0YugJX3l*}*u!Xf*Vo^{vn4^zbj&|H*XCJ&}1OWYF1q4!hQ z=FcVS$J8`<1oWZ#+A6rhT;0G;90M&!IM=+Yl3nRvB*%AVcKqmsGs*I!adCD^#O|;I zafRtAp3>~HeiFs?%AptPWQ_)oCexq3s9Deu`3`QZLXwAM>ceYt>l%dg8*5(i;?Gzv z-5OwBI7%lzG6+=FZa`%&Z+e_D+ou%`Zl|_cK7Rfsj?O@9Un`tJ7Qf`uH&rbh>^8a-ePYk<+izI>-_zD>{s{OaY;zxG@;)e|D~ zW^uSl>;^eT5D@1&tJyk~LeGM&eFYzU6(E$ss$#YD{ z01IUfqlF#}F)4hy+sE9@lq;em4M6jz@ZEGYWg15b!%Gq`6Wo~vZ7S*m$$eK=X3Vzsg{yo-BZU1Q?HPh*2$-R7b%&P0@$&8jaYS8ZGF&=dgf;2b zf?}Y<%in_T>RkcBml7j@aacTc&H_#fr$hz-Wz$9uAf?3zVCfZp36=DRp>Ml0KPM+8 zmJb*NLgC^NKIGTH`^6ZCzWjUzMZ&nw%=jAexNgGycq%NlBL9yh$S_ib?o2AoOa@`&^ApR2)k&7|uU?2a-*;Ey$PTjG>Qfjqq(<3I4z zSzf*rdxiEL(%AKUpoStYk2F6>5Vrhfcc-Nh@)vvjA1Y8Nj~)=;ud^XQ);UU|wx9!i z6FaCZiJ&wuA0eI6j{8>Ve7^j*oKs3XL`QE2MksFT6EhjQIU3fRk4q6QQl6(i6K!8g z=-K{WeIqc-(z=rFkZ;CbIs3pBqNM-RLNq$v^6XXM6dbAB-?*+_=HfYcyn24 zpa!RL%DGeZsB>XX)qQ zUgb)pBtLqwABpEPArG97oz&HTDX`EU@x626$5O-hop?%1kZ2hj=d3413{O)Z@mV-E zrb(qhWs3-8JRP?5%o+j~U%ry{2Od!$jcWThYrmC5n`a`+FT;~5o-%W;T-F?;$d?YR z>+N_jX{M0=NXO=JnL|v37>?_%|SnaOEL+Fl?1Y*;{&78s%kHV3;~lA4u&-p2SBmK_3EjusmG4 zA#j%1q^>U)k<`d&U&Pa*zrp_&tb8(6PSHV!`NCa!XdVn-ANPfoyJIcmPO{J(91M<) yii?&MNJ>gSlZ$}ox|&i9v5a+rYWSj_z<&$Y=|IX6s6Y1r07W?!*(zz1;Qs^SN8SAZ literal 0 HcmV?d00001 diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/images/villain.png b/public/docs/_examples/cb-a1-a2-quick-reference/ts/images/villain.png new file mode 100644 index 0000000000000000000000000000000000000000..d1e71cf00b6b6551d82fc59aa88219b91b7e27a0 GIT binary patch literal 19344 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 GasLNL^nLgM literal 0 HcmV?d00001 diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/index.html b/public/docs/_examples/cb-a1-a2-quick-reference/ts/index.html new file mode 100644 index 0000000000..71f5901c61 --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/index.html @@ -0,0 +1,35 @@ + + + + + Angular 1 to Angular 2 Quick Reference + + + + + + + + + + + + + + + + Loading app... + + + diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/plnkr.json b/public/docs/_examples/cb-a1-a2-quick-reference/ts/plnkr.json new file mode 100644 index 0000000000..ad554ad166 --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/plnkr.json @@ -0,0 +1,9 @@ +{ + "description": "Angular 1 to Angular 2 Quick Reference", + "files":[ + "!**/*.d.ts", + "!**/*.js", + "!**/*.[1].*" + ], + "tags":["cookbook"] +} \ No newline at end of file diff --git a/public/docs/ts/latest/cookbook/_data.json b/public/docs/ts/latest/cookbook/_data.json index 5ee951914b..fa3783d3e6 100644 --- a/public/docs/ts/latest/cookbook/_data.json +++ b/public/docs/ts/latest/cookbook/_data.json @@ -5,7 +5,11 @@ "title": "Cookbook" }, + "a1-a2-quick-reference": { + "title": "Angular 1 to 2 Quick Ref" + }, + "component-communication": { "title": "Component Communication" } -} \ No newline at end of file +} diff --git a/public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade b/public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade new file mode 100644 index 0000000000..9643d0cf6e --- /dev/null +++ b/public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade @@ -0,0 +1,795 @@ +include ../../../../_includes/_util-fns +a(id="top") +:marked + There are many conceptual and syntactical differences between Angular 1 and Angular 2. + This chapter provides a quick reference guide to some of the common Angular 1 + syntax and its equivalent in Angular 2. + +:marked + **See the Angular 2 syntax in this [live example](/resources/live-examples/cb-a1-a2-quick-reference/ts/plnkr.html)**. + + ## Contents + This chapter covers + * [Template Basics](#template-basics) - binding and local variables + + * [Template Directives](#template-directives) - built-in directives `ngIf` and ` `ngClass` + + * [Filters/Pipes](#filters-pipes) - built-in *filters*, known as *pipes* in Angular 2 + + * [Controllers/Components](#controllers-components) - *controllers* are *components* in Angular 2. + Also covers modules. + + * [Style Sheets](#style-sheets) - more options for CSS in Angular 2. + + * [String date pipe](#string-dates) - a tip for displaying string date values. + +.l-main-section +:marked + ## Template Basics + Templates are the user-facing part of an Angular application and are written in HTML. + The following are some of the key Angular 1 template features with the equivalent + template syntax in Angular 2. + +- var top="vertical-align:top" +table(width="100%") + col(width="50%") + col(width="50%") + tr + th Angular 1 + th Angular 2 + tr(style=top) + td + :marked + ### Bindings/Interpolation + code-example. + Your favorite hero is: {{vm.favoriteHero}} + :marked + In Angular 1, an expression in curly braces denotes one-way binding. + This binds the value of the element to a property in the controller + associated with this template. + + When using the `controller as` syntax, + the binding is prefixed with the controller alias (`vm`) because we + have to be specific about the source of the binding. + td + :marked + ### Bindings/Interpolation + +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'interpolation')(format="." ) + :marked + In Angular 2, a template expression in curly braces still denotes one-way binding. + This binds the value of the element to a property of the component. + The context of the binding is implied and is always the + associated component, so it needs no reference variable. + + For more information see [Template Syntax](../guide/template-syntax.html#interpolation). + tr(style=top) + td + :marked + ### Filters + code-example. + <td>{{movie.title | uppercase}}</td> + :marked + To filter output in our templates in Angular 1, we use the pipe character (|) and one or more filters. + + In this example, we filter the `mpaa` property to uppercase. + td + :marked + ### Pipes + +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'uppercase')(format="." ) + :marked + In Angular 2, we use similar syntax with the pipe (|) character to filter output, but now we call them **pipes**. + Many (but not all) of the built-in filters from Angular 1 are + built-in pipes in Angular 2. + + See the heading [Filters / Pipes](#Pipes) below for more information. + tr(style=top) + td + :marked + ### Local variables + code-example(format=""). + <tr ng-repeat="movie in vm.movies"> + <td>{{movie.title}}</td> + </tr> + :marked + Here, `movie` is a user-defined local variable. + td + :marked + ### Local variables + +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'local')(format="." ) + :marked + In Angular 2, we have true local template variables that are explicitly defined using the hash (#) symbol. + + Using a local template variable, we can move data between elements in the template. We can use the local template + variable on the same element, on sibling elements, or on any child elements. + + For more information see [Template Syntax](../guide/template-syntax.html#local-vars). +:marked + [Back to top](#top) + +.l-main-section +:marked + ## Template Directives + Angular 1 provides over seventy built-in directives for use in our templates. + Many of them are no longer needed in Angular 2 because of its more capable and expressive binding system. + The following are some of the key Angular 1 built-in directives and the equivalent feature in Angular 2. + +table(width="100%") + col(width="50%") + col(width="50%") + tr + th Angular 1 + th Angular 2 + tr(style=top) + td + :marked + ### ng-app + code-example. + <body ng-app="movieHunter"> + :marked + The application startup process is called **bootstrapping**. + + Although we can bootstrap an Angular 1 app in code, + many applications bootstrap declaratively with the `ng-app` directive, + giving it the name of the application's module (`movieHunter`). + td + :marked + ### Bootstrapping + +makeExample('cb-a1-a2-quick-reference/ts/app/main.ts')(format="." ) + :marked + Angular 2 does not have a bootstrap directive. + We always launch the app in code by explicitly calling a bootstrap function + and passing it the name of the application's module (`AppComponent`). + + For more information see [Quick Start](../quickstart.html). + tr(style=top) + td + :marked + ### ng-class + code-example(format=""). + <div ng-class="{active: isActive}"> + <div ng-class="{active: isActive, + shazam: isImportant}"> + :marked + In Angular 1, the `ng-class` directive includes/excludes CSS classes + based on an expression. That expression is often a key-value control object with each + key of the object defined as a CSS class name, and each value defined as a template expression + that evaluates to a Boolean value. + + In the first example, the `active` class is applied to the element if `isActive` is true. + + We can specify multiple classes as shown in the second example. + td + :marked + ### ngClass + +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'ngClass')(format="." ) + :marked + In Angular 2, the `ngClass` directive works similarly. + It includes/excludes CSS classes based on an expression. + + In the first example, the `active` class is applied to the element if `isActive` is true. + + We can specify multiple classes as shown in the second example. + + Angular 2 also has **class binding**, which is good way to add or remove a single class + as shown in the third example. + + For more information see [Template Syntax](../guide/template-syntax.html#other-bindings). + + tr(style=top) + td + :marked + ### ng-click + code-example(format=""). + <button ng-click="vm.toggleImage()"> + <button ng-click="vm.toggleImage($event)"> + :marked + In Angular 1, the `ng-click` directive allows us to specify custom behavior when an element is clicked. + + In the first example, when the button is clicked, the `toggleImage()` method in the controller referenced by the `vm` `controller as` alias is executed. + + The second example demonstrates passing in the `$event` object, which provides details about the event + to the controller. + td + :marked + ### bind to the `click` event + +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'event-binding')(format="." ) + :marked + The Angular 1 event-based directives do not exist in Angular 2. + Rather, we define one-way binding from the template view to the component using **event binding**. + + For event binding, we define the name of the target event within parenthesis and + specify a template statement in quotes to the right of the equals. Angular 2 then + sets up an event handler for the target event. When the event is raised, the handler + executes the template statement. + + In the first example, when the button is clicked, the `toggleImage()` method in the associated component is executed. + + The second example demonstrates passing in the `$event` object, which provides details about the event + to the component. + + For a list of DOM events, see: https://developer.mozilla.org/en-US/docs/Web/Events. + + For more information see [Template Syntax](../guide/template-syntax.html#event-binding). + + tr(style=top) + td + :marked + ### ng-controller + code-example(format=""). + <div ng-controller="MovieListCtrl as vm"> + :marked + In Angular 1, the `ng-controller` directive attaches a controller to the view. + Using the `ng-controller` (or defining the controller as part of the routing) ties the + view to the controller code associated with that view. + td + :marked + ### Component decorator + +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'component')(format="." ) + :marked + In Angular 2, the template no longer specifies its associated controller. + Rather, the component specifies its associated template as part of the component class decorator. + + For more information see [Architecture Overview](../guide/architecture.html#component). + + tr(style=top) + td + :marked + ### ng-hide + In Angular 1, the `ng-hide` directive shows or hides the associated HTML element based on + an expression. See [ng-show](#ng-show) for more information. + td + :marked + ### bind to the `hidden` property + In Angular 2, we use property binding; there is no built-in *hide* directive. + See [ng-show](#ng-show) for more information. + tr(style=top) + td + :marked + ### ng-href + code-example(format=""). + <a ng-href="angularDocsUrl">Angular Docs</a> + :marked + The `ng-href` directive allows Angular 1 to preprocess the `href` property so it + can replace the binding expression with the appropriate URL before the browser + fetches from that URL. + + In Angular 1, the `ng-href` is often used to activate a route as part of navigation. + code-example(format=""). + <a ng-href="#movies">Movies</a> + :marked + Routing is handled differently in Angular 2. + td + :marked + ### bind to the `href` property + +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'href')(format="." ) + :marked + In Angular 2, we use property binding; there is no built-in *href* directive. + We place the element's `href` property in square brackets and set it to a quoted template expression. + + For more information on property binding see [Template Syntax](../guide/template-syntax.html#property-binding). + + In Angular 2, `href` is no longer used for routing. Routing uses `routerLink` as shown in the third example. + +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'router-link')(format="." ) + :marked + For more information on routing see [Routing & Navigation](../guide/router.html#router-link). + + tr(style=top) + td + :marked + ### ng-if + code-example(format=""). + <table ng-if="movies.length"> + :marked + In Angular 1, the `ng-if` directive removes or recreates a portion of the DOM + based on an expression. If the expression is false, the element is removed from the DOM. + + In this example, the `table` element is removed from the DOM unless the `movies` array has a length. + td + :marked + ### *ngIf + +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'ngIf')(format="." ) + :marked + The `*ngIf` directive in Angular 2 works the same as the `ng-if` directive in Angular 1, + it removes or recreates a portion of the DOM based on an expression. + + In this example, the `table` element is removed from the DOM unless the `movies` array has a length. + + The (*) before `ngIf` is required in this example. + For more information see [Structural Directives](../guide/structural-directives). + tr(style=top) + td + :marked + ### ng-model + code-example(format=""). + <input ng-model="vm.favoriteHero"/> + :marked + In Angular 1, the `ng-model` directive binds a form control to a property in the controller associated with the template. + This provides **two-way binding** whereby any changes made to the value in the view is synchronized with the model and + any changes to the model are synchronized with the value in the view. + td + :marked + ### ngModel + +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'ngModel')(format="." ) + :marked + In Angular 2, **two-way binding** is denoted with [()], descriptively referred to as a "banana in a box". + This syntax is a short-cut for defining both property binding (from the component to the view) + and event binding (from the view to the component), thereby giving us two-way binding. + + For more information on two-way binding with ngModel see [Template Syntax](../guide/template-syntax.html#ngModel). + tr(style=top) + td + :marked + ### ng-repeat + code-example(format=""). + <tr ng-repeat="movie in vm.movies"> + :marked + In Angular 1, the `ng-repeat` directive repeats the associated DOM element + for each item from the specified collection. + + In this example, the table row (`tr`) element is repeated for each movie object in the collection of movies. + td + :marked + ### *ngFor + +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'ngFor')(format="." ) + :marked + The `*ngFor` directive in Angular 2 is similar to the `ng-repeat` directive in Angular 1. + It repeats the associated DOM element for each item from the specified collection. + More accurately, it turns the defined element (`tr` in this example) and its contents into a template and + uses that template to instantiate a view for each item in the list. + + Notice the other syntax differences: + The (*) before `ngFor` is required; + the (#) identifies `movie` as a local variable; + the list preposition is `of`, not `in`. + + For more information see [Structural Directives](../guide/structural-directives). + tr(style=top) + td + :marked + ### ng-show + code-example(format=""). + <h3 ng-show="vm.favoriteHero"> + Your favorite hero is: {{vm.favoriteHero}} + </h3> + :marked + In Angular 1, the `ng-show` directive shows or hides the associated DOM element based on + an expression. + + In this example, the `div` element is shown if the `favoriteHero` variable is truthy. + td + :marked + ### bind to the `hidden` property + +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'hidden')(format="." ) + :marked + In Angular 2, we use property binding; there is no built-in *show* directive. + For hiding and showing elements, we bind to the HTML `hidden` property. + + To conditionally display an element, place the element's `hidden` property in square brackets and + set it to a quoted template expression that evaluates to the *opposite* of *show*. + + In this example, the `div` element is hidden if the `favoriteHero` variable is not truthy. + + For more information on property binding see [Template Syntax](../guide/template-syntax.html#property-binding). + tr(style=top) + td + :marked + ### ng-src + code-example(format=""). + <img ng-src="{{movie.imageurl}}"> + :marked + The `ng-src` directive allows Angular 1 to preprocess the `src` property so it + can replace the binding expression with the appropriate URL before the browser + fetches from that URL. + td + :marked + ### bind to the `src` property + +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'src')(format="." ) + :marked + In Angular 2, we use property binding; there is no built-in *src* directive. + We place the `src` property in square brackets and set it to a quoted template expression. + + For more information on property binding see [Template Syntax](../guide/template-syntax.html#property-binding). + tr(style=top) + td + :marked + ### ng-style + code-example(format=""). + <div ng-style="{color: colorPreference}"> + :marked + In Angular 1, the `ng-style` directive sets a CSS style on an HTML element + based on an expression. That expression is often a key-value control object with each + key of the object defined as a CSS style name, and each value defined as an expression + that evaluates to a value appropriate for the style. + + In the example, the `color` style is set to the current value of the `colorPreference` variable. + td + :marked + ### ngStyle + +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'ngStyle')(format="." ) + :marked + In Angular 2, the `ngStyle` directive works similarly. It sets a CSS style on an HTML element based on an expression. + + In the first example, the `color` style is set to the current value of the `colorPreference` variable. + + Angular 2 also has **style binding**, which is good way to set a single style. This is shown in the second example. + + For more information on style binding see [Template Syntax](../guide/template-syntax.html#style-binding). + + For more information on the ngStyle directive see [Template Syntax](../guide/template-syntax.html#ngStyle). + tr(style=top) + td + :marked + ### ng-switch + code-example(format=""). + <div ng-switch="vm.favoriteHero && + vm.checkMovieHero(vm.favoriteHero)"> + <div ng-switch-when="true"> + Excellent choice! + </div> + <div ng-switch-when="false"> + No movie, sorry! + </div> + <div ng-switch-default> + Please enter your favorite hero. + </div> + </div> + :marked + In Angular 1, the `ng-switch` directive swaps the contents of + an element by selecting one of the templates based on the current value of an expression. + + In this example, if `favoriteHero` is not set, the template displays "Please enter ...". + If the `favoriteHero` is set, it checks the movie hero by calling a controller method. + If that method returns `true`, the template displays "Excellent choice!". + If that methods returns `false`, the template displays "No movie, sorry!". + td + :marked + ### ngSwitch + +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'ngSwitch')(format="." ) + :marked + In Angular 2, the `ngSwitch` directive works similarly. + It displays an element whose `*ngSwitchWhen` matches the current `ngSwitch` expression value. + + In this example, if `favoriteHero` is not set, the `ngSwitch` value is `null` + and we see the `*ngSwitchDefault` paragraph, "Please enter ...". + If the `favoriteHero` is set, it checks the movie hero by calling a component method. + If that method returns `true`, we see "Excellent choice!". + If that methods returns `false`, we see "No movie, sorry!". + + The (*) before `ngSwitchWhen` and `ngSwitchDefault` is required in this example. + + For more information on the ngSwitch directive see [Template Syntax](../guide/template-syntax.html#ngSwitch). +:marked + [Back to top](#top) + +a(id="filters-pipes") +.l-main-section +:marked + ## Filters / Pipes + Angular 2 **pipes** provide formatting and transformation for data in our template, similar to Angular 1 **filters**. + Many of the built-in filters in Angular 1 have corresponding pipes in Angular 2. + For more information on pipes see [Pipes](../guide/pipes.html). + +table(width="100%") + col(width="50%") + col(width="50%") + tr + th Angular 1 + th Angular 2 + tr(style=top) + td + :marked + ### currency + code-example. + <td>{{movie.price | currency}}</td> + :marked + Formats a number as a currency. + td + :marked + ### currency + +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'currency')(format="." ) + :marked + The Angular 2 `currency` pipe is similar although some of the parameters have changed. + tr(style=top) + td + :marked + ### date + code-example. + <td>{{movie.releaseDate | date}}</td> + :marked + Formats a date to a string based on the requested format. + td + :marked + ### date + +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'date')(format=".") + :marked + The Angular 2 `date` pipe is similar. See [note](#string-dates) about string date values. + + tr(style=top) + td + :marked + ### filter + code-example. + <tr ng-repeat="movie in movieList | filter: {title:listFilter}"> + :marked + Selects a subset of items from the defined collection based on the filter criteria. + td + :marked + ### none + :marked + There is no comparable pipe in Angular 2 for performance reasons. + Filtering should be coded in the component. + Consider building a custom pipe if the same filtering code + will be reused in several templates. + + tr(style=top) + td + :marked + ### json + code-example. + <pre>{{movie | json}}</pre> + :marked + Converts a JavaScript object into a JSON string. This is useful for debugging. + td + :marked + ### json + +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'json')(format=".") + :marked + The Angular 2 `json` pipe does the same thing. + tr(style=top) + td + :marked + ### limitTo + code-example. + <tr ng-repeat="movie in movieList | limitTo: 2"> + :marked + Selects the defined number of items from the collection. + td + :marked + ### slice + +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'slice')(format=".") + :marked + The first parameter of the `SlicePipe` is the starting index; the second is the limit. + As in Angular 1, performance may improve if this operation is coded in the component. + tr(style=top) + td + :marked + ### lowercase + code-example. + <div>{{movie.title | lowercase}}</div> + :marked + Converts the string to lowercase. + td + :marked + ### lowercase + +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'lowercase')(format=".") + :marked + The Angular 2 `lowercase` pipe does the same thing. + tr(style=top) + td + :marked + ### number + code-example. + <td>{{movie.starRating | number}}</td> + :marked + Formats a number as text. + td + :marked + ### number + +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'number')(format=".") + :marked + The Angular 2 `number` pipe is similar. + It provides more functionality when defining + the decimal places as shown in the second example above. + + Angular 2 also has a `percent` pipe which formats a number as a local percentage + as shown in the third example. + tr(style=top) + td + :marked + ### orderBy + code-example. + <tr ng-repeat="movie in movieList | orderBy : 'title'"> + :marked + Orders the collection as specified by the expression. + In this example, the movieList is ordered by the movie title. + td + :marked + ### none + There is no comparable pipe in Angular 2 for performance reasons. + Ordering/sorting the results should be coded in the component. + Consider building a custom pipe if the same ordering/sorting code + will be reused in several templates. +:marked + [Back to top](#top) + +a(id="controllers-components") +.l-main-section +:marked + ## Controllers / Components + In Angular 1, we write the code that provides the model and the methods for the view in a **controller**. + In Angular 2, we build a **component**. + + Because much of our Angular 1 code is in JavaScript, JavaScript code is shown in the Angular 1 column. + The Angular 2 code is shown using TypeScript. + +table(width="100%") + col(width="50%") + col(width="50%") + tr + th Angular 1 + th Angular 2 + tr(style=top) + td + :marked + ### IIFE + code-example. + (function () { + }()); + :marked + In Angular 1, we often defined an immediately invoked function expression (or IIFE) around our controller code. + This kept our controller code out of the global namespace. + td + :marked + ### none + We don't need to worry about this in Angular 2 because we use ES 2015 modules + and modules handle the namespacing for us. + + For more information on modules see [Architecture Overview](../guide/architecture.html#module). + tr(style=top) + td + :marked + ### Angular modules + code-example. + angular.module("movieHunter", ["ngRoute"]); + :marked + In Angular 1, we define an Angular module, which keeps track of our + controllers, services, and other code. The second argument defines the list + of other modules that this module depends upon. + td + :marked + ### import + +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'import')(format=".") + :marked + Angular 2 does not have its own module system. Instead we use ES 2015 modules. + ES 2015 modules are file based, so each code file is its own module. + + We `import` what we need from the module files. + + For more information on modules see [Architecture Overview](../guide/architecture.html#module). + tr(style=top) + td + :marked + ### Controller registration + code-example. + angular + .module("movieHunter") + .controller("MovieListCtrl", + ["movieService", + MovieListCtrl]); + :marked + In Angular 1, we have code in each controller that looks up an appropriate Angular module + and registers the controller with that module. + + The first argument is the controller name. The second argument defines the string names of + all dependencies injected into this controller, and a reference to the controller function. + td + :marked + ### Component Decorator + +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'component')(format=".") + :marked + In Angular 2, we add a decorator to the component class to provide any required metadata. + The Component decorator declares that the class is a component and provides metadata about + that component, such as its selector (or tag) and its template. + + This is how we associate a template with code, which is defined in the component class. + + For more information on components see [Architecture Overview](../guide/architecture.html#component). + tr(style=top) + td + :marked + ### Controller function + code-example. + function MovieListCtrl(movieService) { + } + :marked + In Angular 1, we write the code for the model and methods in a controller function. + td + :marked + ### Component class + +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'class')(format=".") + :marked + In Angular 2, we create a component class. + + NOTE: If you are using TypeScript with Angular 1 then the only difference here is + that the component class must be exported using the `export` keyword. + + For more information on components see [Architecture Overview](../guide/architecture.html#component). + tr(style=top) + td + :marked + ### Dependency injection + code-example. + MovieListCtrl.$inject = ['MovieService']; + function MovieListCtrl(movieService) { + } + :marked + In Angular 1, we pass in any dependencies as controller function arguments. + In this example, we inject a `MovieService`. + + We also guard against minification problems by telling Angular explicitly + that it should inject an instance of the `MovieService` in the first parameter. + td + :marked + ### Dependency injection + +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'di')(format=".") + :marked + In Angular 2, we pass in dependencies as arguments to the component class constructor. + In this example, we inject a `MovieService`. + The first parameter's TypeScript type tells Angular what to inject even after minification. + + For more information on dependency injection see [Architecture Overview](../guide/architecture.html#dependency-injection). +:marked + [Back to top](#top) + +a(id="style-sheets") +.l-main-section +:marked + ## Style Sheets + Style sheets give our application a nice look. + In Angular 1, we specify the style sheets for our entire application. + As the application grows over time, the styles for the many parts of the application + are merged, which can cause unexpected results. + In Angular 2, we can still define style sheets for our entire application. But now we can + also encapculate a style sheet within a specific component. +table(width="100%") + col(width="50%") + col(width="50%") + tr + th Angular 1 + th Angular 2 + tr(style=top) + td + :marked + ### Link tag + code-example. + <link href="styles.css" rel="stylesheet" /> + :marked + In Angular 1, we use a `link` tag in the head section of our `index.html` file + to define the styles for our application. + td + :marked + ### Link tag + +makeExample('cb-a1-a2-quick-reference/ts/index.html', 'style')(format=".") + :marked + In Angular 2, we can continue to use the link tag to define the styles for our application in the `index.html` file. + But we can now also encapsulate styles for our components. + :marked + ### StyleUrls + In Angular 2, we can use the `styles` or `styleUrls` property of the `@Component` metadata to define + a style sheet for a particular component. + +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'style-url')(format=".") + :marked + This allows us to set appropriate styles for individual components that won’t leak into + other parts of the application. +:marked + [Back to top](#top) + +a(id="string-dates") +.l-main-section +:marked + ## Appendix: String dates + + Currently the Angular 2 `date` pipe does not process string dates such as + "2015-12-19T00:00:00". + + As a work around, subclass the Angular `DatePipe` with a version that can convert strings + and substitute that pipe in the HTML: + ++makeExample('cb-a1-a2-quick-reference/ts/app/date.pipe.ts', 'date-pipe', 'date.pipe.ts')(format=".") +:marked + Then import and declare that pipe in the `@Component` metadata `pipes` array: +:marked ++makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'date-pipe')(format=".") + +:marked + [Back to top](#top) diff --git a/public/docs/ts/latest/guide/_data.json b/public/docs/ts/latest/guide/_data.json index b7f759488e..84963feb59 100644 --- a/public/docs/ts/latest/guide/_data.json +++ b/public/docs/ts/latest/guide/_data.json @@ -8,7 +8,7 @@ "cheatsheet": { "title": "Angular Cheat Sheet" }, - + "architecture": { "title": "Architecture Overview" },