From 04d5337b75107461f726c13c4d7c738338a8e85e Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Mon, 1 Aug 2016 11:22:23 -0700 Subject: [PATCH 01/20] docs(toh-6): search query fixes closes #2008 Changes: - Drop `asObservable()` since it is deprecated in RxJS 5 (see the [migration guide](https://github.com/ReactiveX/RxJS/blob/master/MIGRATION.md#operat ors-renamed-or-removed)). - Drop `+` from hero search query URL: `app/heroes/?name=${term}+`. At best it is interpreted as a regex op that serves no purpose, at worst, it gets interpreted as a space (cf. [HTML 4.01 section 17.13.4](https://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4) ). - Rename `searchSubject` to `searchTerms` - Other minor tweaks to prose. This work is in preparation for #1924. Note: toh-6 tests pass. --- .../toh-6/ts/app/dashboard.component.html | 3 --- .../toh-6/ts/app/hero-search.component.ts | 18 ++++++++---------- .../toh-6/ts/app/hero-search.service.ts | 4 +--- public/docs/ts/latest/tutorial/toh-pt6.jade | 14 ++++++-------- 4 files changed, 15 insertions(+), 24 deletions(-) diff --git a/public/docs/_examples/toh-6/ts/app/dashboard.component.html b/public/docs/_examples/toh-6/ts/app/dashboard.component.html index e22a2a5ebb..fe1ee585f6 100644 --- a/public/docs/_examples/toh-6/ts/app/dashboard.component.html +++ b/public/docs/_examples/toh-6/ts/app/dashboard.component.html @@ -1,13 +1,10 @@

Top Heroes

-
-

{{hero.name}}

- diff --git a/public/docs/_examples/toh-6/ts/app/hero-search.component.ts b/public/docs/_examples/toh-6/ts/app/hero-search.component.ts index 9ef06ca47c..81bb8eb773 100644 --- a/public/docs/_examples/toh-6/ts/app/hero-search.component.ts +++ b/public/docs/_examples/toh-6/ts/app/hero-search.component.ts @@ -17,23 +17,22 @@ export class HeroSearchComponent implements OnInit { // #docregion search heroes: Observable; // #enddocregion search - // #docregion searchSubject - searchSubject = new Subject(); - // #enddocregion searchSubject + // #docregion searchTerms + searchTerms = new Subject(); + // #enddocregion searchTerms constructor( private heroSearchService: HeroSearchService, private router: Router) {} - // #docregion searchSubject + // #docregion searchTerms // Push a search term into the observable stream. - search(term: string) { this.searchSubject.next(term); } - // #enddocregion searchSubject + search(term: string) { this.searchTerms.next(term); } + // #enddocregion searchTerms // #docregion search ngOnInit() { - this.heroes = this.searchSubject - .asObservable() // cast as Observable + this.heroes = this.searchTerms .debounceTime(300) // wait for 300ms pause in events .distinctUntilChanged() // ignore if next search term is same as previous .switchMap(term => term // switch to new observable each time @@ -41,9 +40,8 @@ export class HeroSearchComponent implements OnInit { ? this.heroSearchService.search(term) // or the observable of empty heroes if no search term : Observable.of([])) - .catch(error => { - // Todo: real error handling + // TODO: real error handling console.log(error); return Observable.of([]); }); diff --git a/public/docs/_examples/toh-6/ts/app/hero-search.service.ts b/public/docs/_examples/toh-6/ts/app/hero-search.service.ts index 42018e3526..95a31707eb 100644 --- a/public/docs/_examples/toh-6/ts/app/hero-search.service.ts +++ b/public/docs/_examples/toh-6/ts/app/hero-search.service.ts @@ -9,11 +9,9 @@ export class HeroSearchService { constructor(private http: Http) {} - // #docregion observable-search search(term: string) { return this.http - .get(`app/heroes/?name=${term}+`) + .get(`app/heroes/?name=${term}`) .map((r: Response) => r.json().data as Hero[]); } - // #enddocregion observable-search } diff --git a/public/docs/ts/latest/tutorial/toh-pt6.jade b/public/docs/ts/latest/tutorial/toh-pt6.jade index 104c8575fe..c7edf449fc 100644 --- a/public/docs/ts/latest/tutorial/toh-pt6.jade +++ b/public/docs/ts/latest/tutorial/toh-pt6.jade @@ -419,11 +419,11 @@ block observables-section Time to create the `HeroSearchComponent` class and metadata. +makeExample('toh-6/ts/app/hero-search.component.ts', null,'hero-search.component.ts') :marked - Focus on the `searchSubject`. - +makeExample('toh-6/ts/app/hero-search.component.ts', 'searchSubject')(format=".") + Focus on the `searchTerms`. + +makeExample('toh-6/ts/app/hero-search.component.ts', 'searchTerms')(format=".") :marked A `Subject` is a producer of an _observable_ event stream. - This `searchSubject` produces an `Observable` of strings, the filter criteria for the name search. + This `searchTerms` produces an `Observable` of strings, the filter criteria for the name search. Each call to `search` puts a new string into this subject's _observable_ stream by calling `next`. @@ -439,8 +439,6 @@ block observables-section Fortunately we can chain `Observable` operators to the string `Observable` that reduce the request flow. We'll make fewer calls to the `HeroSearchService` and still get timely results. Here's how: - * The `asObservable` operator casts the `Subject` as an `Observable` of filter strings. - * `debounceTime(300)` waits until the flow of new string events pauses for 300 milliseconds before passing along the latest string. We'll never make requests more frequently than 300ms. @@ -495,11 +493,11 @@ block observables-section +makeExample('toh-6/ts/app/app.component.ts', 'rxjs-extensions', 'app/app.component.ts')(format=".") :marked - ### Adding the search component to the dashboard + ### Add the search component to the dashboard - We add the `HeroSearchComponent` to the bottom of the `DashboardComponent` template. + We add the hero search HTML element to the bottom of the `DashboardComponent` template. - +makeExample('toh-6/ts/app/dashboard.component.html', null, 'dashboard.component.html') + +makeExample('app/dashboard.component.html') :marked And finally, we import the `HeroSearchComponent` and add it to the `directives` array. From 818c82c2a2576c5de2bccbacdc4396ce011b406d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesu=CC=81s=20Rodri=CC=81guez?= Date: Tue, 26 Jul 2016 15:51:53 +0200 Subject: [PATCH 02/20] chore: add README.md to each plunker closes #1974 --- public/docs/_examples/plunker.README.md | 2 ++ tools/plunker-builder/plunkerBuilder.js | 26 +++++++++++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) create mode 100644 public/docs/_examples/plunker.README.md diff --git a/public/docs/_examples/plunker.README.md b/public/docs/_examples/plunker.README.md new file mode 100644 index 0000000000..5bcc99414d --- /dev/null +++ b/public/docs/_examples/plunker.README.md @@ -0,0 +1,2 @@ +### Angular 2 Documentation Example + diff --git a/tools/plunker-builder/plunkerBuilder.js b/tools/plunker-builder/plunkerBuilder.js index bf5c428a3f..29efd1b990 100644 --- a/tools/plunker-builder/plunkerBuilder.js +++ b/tools/plunker-builder/plunkerBuilder.js @@ -10,10 +10,10 @@ var mkdirp = require('mkdirp'); var indexHtmlTranslator = require('./indexHtmlTranslator'); var regionExtractor = require('../doc-shredder/regionExtractor'); var COPYRIGHT, COPYRIGHT_JS_CSS, COPYRIGHT_HTML; +var README; // content of plunker.README.md for plunkers var SYSTEMJS_CONFIG; // content of systemjs.config.js for plunkers that use systemjs var TSCONFIG; // content of tsconfig.json for plunkers that use systemjs - module.exports = { buildPlunkers: buildPlunkers }; @@ -30,7 +30,7 @@ function buildCopyrightStrings() { } function buildPlunkers(basePath, destPath, options) { - getSystemJsConfigPlunker(basePath); + getPlunkerFiles(basePath); var errFn = options.errFn || function(e) { console.log(e); }; var plunkerPaths = path.join(basePath, '**/*plnkr.json'); var fileNames = globby.sync(plunkerPaths, { ignore: "**/node_modules/**"}); @@ -59,7 +59,7 @@ function buildPlunkerFrom(configFileName, basePath, destPath) { try { var config = initConfigAndCollectFileNames(configFileName); var postData = createPostData(config); - addSystemJsConfig(config, postData); + addPlunkerFiles(config, postData); var html = createPlunkerHtml(postData); fs.writeFileSync(outputFileName, html, 'utf-8'); if (altFileName) { @@ -81,10 +81,8 @@ function buildPlunkerFrom(configFileName, basePath, destPath) { } } -/** - * Add plunker versions of systemjs.config and tsconfig.json - */ -function addSystemJsConfig(config, postData){ +function addPlunkerFiles(config, postData) { + addReadme(config, postData); if (config.basePath.indexOf('/ts') > -1) { // uses systemjs.config.js so add plunker version postData['files[systemjs.config.js]'] = SYSTEMJS_CONFIG; @@ -92,8 +90,20 @@ function addSystemJsConfig(config, postData){ } } -function getSystemJsConfigPlunker(basePath) { +function addReadme(config, postData) { + var existingFiles = config.fileNames.map(function(file) { + return file.substr(file.lastIndexOf('/') + 1); + }); + + if (existingFiles.indexOf('README.md') === -1) { + var plunkerReadme = README + config.description; + postData['files[README.md]'] = plunkerReadme; + } +} + +function getPlunkerFiles(basePath) { // Assume plunker version is sibling of node_modules version + README = fs.readFileSync(basePath + '/plunker.README.md', 'utf-8'); SYSTEMJS_CONFIG = fs.readFileSync(basePath + '/systemjs.config.plunker.js', 'utf-8'); SYSTEMJS_CONFIG += COPYRIGHT_JS_CSS; TSCONFIG = fs.readFileSync(basePath + '/tsconfig.json', 'utf-8'); From daac8fffbe5a433aa7dbf7473943a7b1d4d14b6d Mon Sep 17 00:00:00 2001 From: Torgeir Helgevold Date: Sat, 30 Jul 2016 13:06:37 -0400 Subject: [PATCH 03/20] docs(cb-dynamic-forms): update subtitle closes #2004 --- public/docs/ts/latest/cookbook/_data.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/docs/ts/latest/cookbook/_data.json b/public/docs/ts/latest/cookbook/_data.json index 1d1c230763..2607a72898 100644 --- a/public/docs/ts/latest/cookbook/_data.json +++ b/public/docs/ts/latest/cookbook/_data.json @@ -33,7 +33,7 @@ "dynamic-form": { "title": "Dynamic Forms", - "intro": "Render dynamic forms with NgFormModel", + "intro": "Render dynamic forms with FormGroup", "basics": true, "hide": true }, From e2919de78f7b634cd7e6b661d8e8e1b6f12056bc Mon Sep 17 00:00:00 2001 From: Ciro Nunes Date: Sun, 31 Jul 2016 17:58:00 +0200 Subject: [PATCH 04/20] docs(glossary): improve DI word closes #2007 --- public/docs/ts/latest/glossary.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/docs/ts/latest/glossary.jade b/public/docs/ts/latest/glossary.jade index f4eb1ee117..2f8b11fced 100644 --- a/public/docs/ts/latest/glossary.jade +++ b/public/docs/ts/latest/glossary.jade @@ -248,7 +248,7 @@ include _util-fns to assemble and run applications by "injecting" application parts into other application parts where and when needed. - At the core is an [`Injector`](#injector) that returns dependency values on request. + At the core there is an [`Injector`](#injector) that returns dependency values on request. The expression `injector.get(token)` returns the value associated with the given token. A token is an Angular type (`OpaqueToken`). We rarely deal with tokens directly; most From 6f63e6a390aa605974a45f3258b7f636824e5595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ad=C3=A3o=20J=C3=BAnior?= Date: Mon, 1 Aug 2016 18:13:24 -0300 Subject: [PATCH 05/20] docs(server-communication): Resolve todo (#1993) * use latest version of http_in_memory_web_api * remove todo and drop the ?? body term --- .../server-communication/dart/lib/toh/hero_service.dart | 4 +--- public/docs/_examples/server-communication/dart/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/public/docs/_examples/server-communication/dart/lib/toh/hero_service.dart b/public/docs/_examples/server-communication/dart/lib/toh/hero_service.dart index 5da269fff7..dd16fe70cd 100644 --- a/public/docs/_examples/server-communication/dart/lib/toh/hero_service.dart +++ b/public/docs/_examples/server-communication/dart/lib/toh/hero_service.dart @@ -50,9 +50,7 @@ class HeroService { // #docregion extract-data dynamic _extractData(Response res) { var body = JSON.decode(res.body); - // TODO: https://github.com/adaojunior/http-in-memory-web-api/issues/1 - // Once #1 is fixed, drop the `?? body` term: - return body['data'] ?? body; + return body['data']; } // #enddocregion extract-data // #docregion error-handling diff --git a/public/docs/_examples/server-communication/dart/pubspec.yaml b/public/docs/_examples/server-communication/dart/pubspec.yaml index 217cb4edcc..3d8e06cbe0 100644 --- a/public/docs/_examples/server-communication/dart/pubspec.yaml +++ b/public/docs/_examples/server-communication/dart/pubspec.yaml @@ -11,7 +11,7 @@ dependencies: http: ^0.11.3+3 jsonpadding: ^0.1.0 stream_transformers: ^0.3.0+3 - http_in_memory_web_api: ^0.0.1 + http_in_memory_web_api: ^0.2.0 # #docregion transformers transformers: - angular2: From 36091d5934494edfec18b9783c9b0e6597e07fb5 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Mon, 1 Aug 2016 14:28:28 -0700 Subject: [PATCH 06/20] docs(DI/dart): fix incorrect snippet (#2017) Dart counterpart to #2001. Fixes #1956 for Dart. --- .../dart/lib/heroes/heroes_component_1.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/docs/_examples/dependency-injection/dart/lib/heroes/heroes_component_1.dart b/public/docs/_examples/dependency-injection/dart/lib/heroes/heroes_component_1.dart index 4546a7c5c3..dd63d95b15 100644 --- a/public/docs/_examples/dependency-injection/dart/lib/heroes/heroes_component_1.dart +++ b/public/docs/_examples/dependency-injection/dart/lib/heroes/heroes_component_1.dart @@ -7,11 +7,11 @@ import 'package:angular2/core.dart'; import 'hero_list_component_2.dart'; import 'hero_service_1.dart'; /* -// #docregion full +// #docregion full, v1 import 'hero_list_component.dart'; -// #docregion v1 +// #enddocregion v1 import 'hero_service.dart'; -// #enddocregion full, v1 +// #enddocregion full */ // #docregion full, v1 From bf3e1074ea40ac1dcbbf8b0ddf72a490f877aa03 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Mon, 1 Aug 2016 14:30:12 -0700 Subject: [PATCH 07/20] docs(api/dart): avoid duplicate entries and fix breadcrumbs (#1945) --- gulpfile.js | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index b7be783ea8..b2e93be14e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -108,20 +108,21 @@ var _exampleConfigFilename = 'example-config.json'; // Gulp flags: // -// --lang=[all | ts | js | dart | (ts|js) | (ts|js|dart) | ...] +// --lang=[all | ts | js | dart | 'ts|js' | 'ts|js|dart' | ...] // // This affects which language API docs and E2E tests are run. Can be 'all', // or a regex pattern to match any one of 'ts', 'js', or 'dart'. -// Default: '(ts|js)' except for check-deploy for which it is 'all'. +// Default: 'ts|js' except for the "full site build" tasks (see below), +// for which it is 'all'. // var lang, langs, buildDartApiDocs = false; function configLangs(langOption) { const fullSiteBuildTasks = ['build-compile', 'check-serve', 'check-deploy']; const buildAllDocs = argv['_'] && fullSiteBuildTasks.some((task) => argv['_'].indexOf(task) >= 0); - const langDefault = buildAllDocs ? 'all' : '(ts|js)'; + const langDefault = buildAllDocs ? 'all' : 'ts|js'; lang = (langOption || langDefault).toLowerCase(); - if (lang === 'all') lang = '(ts|js|dart)'; + if (lang === 'all') lang = 'ts|js|dart'; langs = lang.match(/\w+/g); // the languages in `lang` as an array gutil.log('Building docs for: ' + lang); if (langs.indexOf('dart') >= 0) { @@ -161,10 +162,8 @@ gulp.task('run-e2e-tests', runE2e); * Use it for repeated test runs (but not the FIRST run) * e.g. gulp e2e --fast * - * --lang to filter by code language + * --lang to filter by code language (see above for details) * e.g. gulp e2e --lang=ts // only TypeScript apps - * default is (ts|js) - * all means (ts|js|dart) */ function runE2e() { var promise; @@ -596,8 +595,16 @@ gulp.task('dartdoc', ['pub upgrade'], function() { return true; } checkAngularProjectPath(ngRepoPath); + const topLevelLibFilePath = path.resolve(ngRepoPath, 'lib', 'angular2.dart'); + const tmpPath = topLevelLibFilePath + '.disabled'; + if (!fs.existsSync(topLevelLibFilePath)) throw new Error(`Missing file: ${topLevelLibFilePath}`); + fs.renameSync(topLevelLibFilePath, tmpPath); + gutil.log(`Hiding top-level angular2 library: ${topLevelLibFilePath}`); const dartdoc = spawnExt('dartdoc', ['--output', 'doc/api', '--add-crossdart'], { cwd: ngRepoPath}); - return dartdoc.promise; + return dartdoc.promise.finally(() => { + gutil.log(`Restoring top-level angular2 library: ${topLevelLibFilePath}`); + fs.renameSync(tmpPath, topLevelLibFilePath); + }) }); gulp.task('pub upgrade', [], function() { From a49ecc7fd85265b0e3f5ac43e19f9bd7badd3d3b Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Mon, 1 Aug 2016 14:34:36 -0700 Subject: [PATCH 08/20] docs(architecture): give example of libraries in TS and Dart (#2015) Follow-up to https://github.com/angular/angular.io/pull/1972#issuecomment-235738082 --- public/docs/ts/latest/guide/architecture.jade | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/docs/ts/latest/guide/architecture.jade b/public/docs/ts/latest/guide/architecture.jade index fbf782f6f2..3510c864bb 100644 --- a/public/docs/ts/latest/guide/architecture.jade +++ b/public/docs/ts/latest/guide/architecture.jade @@ -120,7 +120,8 @@ block angular-library-modules `!{_at_angular}/core` is the primary Angular library from which we get most of what we need.
- There are other important Angular libraries too, such as `!{_at_angular}/common`, `!{_at_angular}/router`, and `!{_at_angular}/http`. + There are other important Angular libraries too, such as `!{_at_angular}/common`, + `!{_at_angular}/http` and `!{_at_angular}/router`. We import what we need from an Angular !{_library_module}. block angular-imports From 8a6c5b5725e4a39d93d29391f11023cb1c05218b Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Tue, 2 Aug 2016 09:59:35 -0700 Subject: [PATCH 09/20] docs(toh-6): add hero search to Dart; minor edits to TS (#2018) * docs(toh-6/dart): add hero search Fixes #1924. * docs(toh-6/ts): minor updates * post-review updates * post-review updates --- .../toh-6/dart/lib/dashboard_component.dart | 21 +- .../toh-6/dart/lib/dashboard_component.html | 5 +- .../toh-6/dart/lib/hero_search_component.css | 15 ++ .../toh-6/dart/lib/hero_search_component.dart | 57 ++++++ .../toh-6/dart/lib/hero_search_component.html | 11 ++ .../toh-6/dart/lib/hero_search_service.dart | 33 ++++ .../toh-6/dart/lib/heroes_component.css | 8 + .../dart/lib/in_memory_data_service.dart | 10 +- public/docs/_examples/toh-6/dart/pubspec.yaml | 1 + .../docs/_examples/toh-6/dart/web/index.html | 1 - .../docs/_examples/toh-6/dart/web/sample.css | 7 - .../toh-6/ts/app/dashboard.component.ts | 7 +- .../toh-6/ts/app/hero-search.component.ts | 2 +- public/docs/dart/latest/tutorial/toh-pt6.jade | 105 +++++++--- public/docs/ts/latest/tutorial/toh-pt6.jade | 182 ++++++++++-------- 15 files changed, 326 insertions(+), 139 deletions(-) create mode 100644 public/docs/_examples/toh-6/dart/lib/hero_search_component.css create mode 100644 public/docs/_examples/toh-6/dart/lib/hero_search_component.dart create mode 100644 public/docs/_examples/toh-6/dart/lib/hero_search_component.html create mode 100644 public/docs/_examples/toh-6/dart/lib/hero_search_service.dart delete mode 100644 public/docs/_examples/toh-6/dart/web/sample.css diff --git a/public/docs/_examples/toh-6/dart/lib/dashboard_component.dart b/public/docs/_examples/toh-6/dart/lib/dashboard_component.dart index ff0fb8c0d1..da965c301c 100644 --- a/public/docs/_examples/toh-6/dart/lib/dashboard_component.dart +++ b/public/docs/_examples/toh-6/dart/lib/dashboard_component.dart @@ -1,41 +1,31 @@ -// #docplaster -// #docregion +// #docregion , search import 'dart:async'; import 'package:angular2/core.dart'; -// #docregion import-router import 'package:angular2/router.dart'; -// #enddocregion import-router import 'hero.dart'; import 'hero_service.dart'; +import 'hero_search_component.dart'; @Component( selector: 'my-dashboard', - // #docregion template-url templateUrl: 'dashboard_component.html', - // #enddocregion template-url - // #docregion css - styleUrls: const ['dashboard_component.css'] - // #enddocregion css - ) -// #docregion component + styleUrls: const ['dashboard_component.css'], + directives: const [HeroSearchComponent]) +// #enddocregion search class DashboardComponent implements OnInit { List heroes; - // #docregion ctor final Router _router; final HeroService _heroService; DashboardComponent(this._heroService, this._router); - // #enddocregion ctor - Future ngOnInit() async { heroes = (await _heroService.getHeroes()).skip(1).take(4).toList(); } - // #docregion goto-detail void gotoDetail(Hero hero) { var link = [ 'HeroDetail', @@ -43,5 +33,4 @@ class DashboardComponent implements OnInit { ]; _router.navigate(link); } -// #enddocregion goto-detail } diff --git a/public/docs/_examples/toh-6/dart/lib/dashboard_component.html b/public/docs/_examples/toh-6/dart/lib/dashboard_component.html index 7133c10ada..fe1ee585f6 100644 --- a/public/docs/_examples/toh-6/dart/lib/dashboard_component.html +++ b/public/docs/_examples/toh-6/dart/lib/dashboard_component.html @@ -1,11 +1,10 @@

Top Heroes

- -
- +

{{hero.name}}

+ diff --git a/public/docs/_examples/toh-6/dart/lib/hero_search_component.css b/public/docs/_examples/toh-6/dart/lib/hero_search_component.css new file mode 100644 index 0000000000..b41b4ec33e --- /dev/null +++ b/public/docs/_examples/toh-6/dart/lib/hero_search_component.css @@ -0,0 +1,15 @@ +/* #docregion */ +.search-result { + border-bottom: 1px solid gray; + border-left: 1px solid gray; + border-right: 1px solid gray; + width:195px; + height: 20px; + padding: 5px; + background-color: white; + cursor: pointer; +} +#search-box { + width: 200px; + height: 20px; +} diff --git a/public/docs/_examples/toh-6/dart/lib/hero_search_component.dart b/public/docs/_examples/toh-6/dart/lib/hero_search_component.dart new file mode 100644 index 0000000000..fc52ace1ba --- /dev/null +++ b/public/docs/_examples/toh-6/dart/lib/hero_search_component.dart @@ -0,0 +1,57 @@ +// #docplaster +// #docregion +import 'dart:async'; + +import 'package:angular2/core.dart'; +import 'package:angular2/router.dart'; +import 'package:stream_transformers/stream_transformers.dart'; + +import 'hero_search_service.dart'; +import 'hero.dart'; + +@Component( + selector: 'hero-search', + templateUrl: 'hero_search_component.html', + styleUrls: const ['hero_search_component.css'], + providers: const [HeroSearchService]) +class HeroSearchComponent implements OnInit { + HeroSearchService _heroSearchService; + Router _router; + + // #docregion search + Stream> heroes; + // #enddocregion search + // #docregion searchTerms + StreamController _searchTerms = + new StreamController.broadcast(); + // #enddocregion searchTerms + + HeroSearchComponent(this._heroSearchService, this._router) {} + // #docregion searchTerms + + // Push a search term into the stream. + void search(String term) => _searchTerms.add(term); + // #enddocregion searchTerms + // #docregion search + + Future ngOnInit() async { + heroes = _searchTerms.stream + .transform(new Debounce(new Duration(milliseconds: 300))) + .distinct() + .transform(new FlatMapLatest((term) => term.isEmpty + ? new Stream>.fromIterable([[]]) + : _heroSearchService.search(term).asStream())) + .handleError((e) { + print(e); // for demo purposes only + }); + } + // #enddocregion search + + void gotoDetail(Hero hero) { + var link = [ + 'HeroDetail', + {'id': hero.id.toString()} + ]; + _router.navigate(link); + } +} diff --git a/public/docs/_examples/toh-6/dart/lib/hero_search_component.html b/public/docs/_examples/toh-6/dart/lib/hero_search_component.html new file mode 100644 index 0000000000..08c0560c5b --- /dev/null +++ b/public/docs/_examples/toh-6/dart/lib/hero_search_component.html @@ -0,0 +1,11 @@ + +
+

Hero Search

+ +
+
+ {{hero.name}} +
+
+
diff --git a/public/docs/_examples/toh-6/dart/lib/hero_search_service.dart b/public/docs/_examples/toh-6/dart/lib/hero_search_service.dart new file mode 100644 index 0000000000..3fecf42e1b --- /dev/null +++ b/public/docs/_examples/toh-6/dart/lib/hero_search_service.dart @@ -0,0 +1,33 @@ +// #docregion +import 'dart:async'; +import 'dart:convert'; + +import 'package:angular2/core.dart'; +import 'package:http/http.dart'; + +import 'hero.dart'; + +@Injectable() +class HeroSearchService { + final Client _http; + + HeroSearchService(this._http); + + Future> search(String term) async { + try { + final response = await _http.get('app/heroes/?name=$term'); + return _extractData(response) + .map((json) => new Hero.fromJson(json)) + .toList(); + } catch (e) { + throw _handleError(e); + } + } + + dynamic _extractData(Response resp) => JSON.decode(resp.body)['data']; + + Exception _handleError(dynamic e) { + print(e); // for demo purposes only + return new Exception('Server error; cause: $e'); + } +} diff --git a/public/docs/_examples/toh-6/dart/lib/heroes_component.css b/public/docs/_examples/toh-6/dart/lib/heroes_component.css index 35e45af98d..15efef53e4 100644 --- a/public/docs/_examples/toh-6/dart/lib/heroes_component.css +++ b/public/docs/_examples/toh-6/dart/lib/heroes_component.css @@ -1,3 +1,4 @@ +/* #docregion */ .selected { background-color: #CFD8DC !important; color: white; @@ -57,3 +58,10 @@ button { button:hover { background-color: #cfd8dc; } +/* #docregion additions */ +.error {color:red;} +button.delete-button { + float:right; + background-color: gray !important; + color:white; +} diff --git a/public/docs/_examples/toh-6/dart/lib/in_memory_data_service.dart b/public/docs/_examples/toh-6/dart/lib/in_memory_data_service.dart index 86aad3de53..927b93bc70 100644 --- a/public/docs/_examples/toh-6/dart/lib/in_memory_data_service.dart +++ b/public/docs/_examples/toh-6/dart/lib/in_memory_data_service.dart @@ -1,6 +1,7 @@ // #docregion import 'dart:async'; import 'dart:convert'; +import 'dart:math'; // #docregion init import 'package:angular2/core.dart'; @@ -23,17 +24,18 @@ class InMemoryDataService extends MockClient { {'id': 19, 'name': 'Magma'}, {'id': 20, 'name': 'Tornado'} ]; - // #enddocregion init - static final List _heroesDb = _initialHeroes.map((json) => new Hero.fromJson(json)).toList(); - static int _nextId = 21; + // #enddocregion init + static int _nextId = _heroesDb.map((hero) => hero.id).reduce(max) + 1; static Future _handler(Request request) async { var data; switch (request.method) { case 'GET': - data = _heroesDb; + String prefix = request.url.queryParameters['name'] ?? ''; + final regExp = new RegExp(prefix, caseSensitive: false); + data = _heroesDb.where((hero) => hero.name.contains(regExp)).toList(); break; case 'POST': var name = JSON.decode(request.body)['name']; diff --git a/public/docs/_examples/toh-6/dart/pubspec.yaml b/public/docs/_examples/toh-6/dart/pubspec.yaml index b59118580c..cdb0ce29f1 100644 --- a/public/docs/_examples/toh-6/dart/pubspec.yaml +++ b/public/docs/_examples/toh-6/dart/pubspec.yaml @@ -13,6 +13,7 @@ dependencies: dart_to_js_script_rewriter: ^1.0.1 # #docregion additions http: ^0.11.0 + stream_transformers: ^0.3.0 transformers: - angular2: # #enddocregion additions diff --git a/public/docs/_examples/toh-6/dart/web/index.html b/public/docs/_examples/toh-6/dart/web/index.html index be8fb7b42e..acb7482f70 100644 --- a/public/docs/_examples/toh-6/dart/web/index.html +++ b/public/docs/_examples/toh-6/dart/web/index.html @@ -7,7 +7,6 @@ - diff --git a/public/docs/_examples/toh-6/dart/web/sample.css b/public/docs/_examples/toh-6/dart/web/sample.css deleted file mode 100644 index 6bbf5de8b7..0000000000 --- a/public/docs/_examples/toh-6/dart/web/sample.css +++ /dev/null @@ -1,7 +0,0 @@ -/* #docregion */ -.error {color:red;} -button.delete-button { - float:right; - background-color: gray !important; - color:white; -} diff --git a/public/docs/_examples/toh-6/ts/app/dashboard.component.ts b/public/docs/_examples/toh-6/ts/app/dashboard.component.ts index 82a817fa5a..41b4de58df 100644 --- a/public/docs/_examples/toh-6/ts/app/dashboard.component.ts +++ b/public/docs/_examples/toh-6/ts/app/dashboard.component.ts @@ -1,6 +1,4 @@ -// #docplaster -// #docregion -// #docregion hero-search-component +// #docregion , search import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; @@ -14,9 +12,8 @@ import { HeroSearchComponent } from './hero-search.component'; styleUrls: ['app/dashboard.component.css'], directives: [HeroSearchComponent] }) -// #enddocregion hero-search-component +// #enddocregion search export class DashboardComponent implements OnInit { - heroes: Hero[] = []; constructor( diff --git a/public/docs/_examples/toh-6/ts/app/hero-search.component.ts b/public/docs/_examples/toh-6/ts/app/hero-search.component.ts index 81bb8eb773..d9a04fce3f 100644 --- a/public/docs/_examples/toh-6/ts/app/hero-search.component.ts +++ b/public/docs/_examples/toh-6/ts/app/hero-search.component.ts @@ -18,7 +18,7 @@ export class HeroSearchComponent implements OnInit { heroes: Observable; // #enddocregion search // #docregion searchTerms - searchTerms = new Subject(); + private searchTerms = new Subject(); // #enddocregion searchTerms constructor( diff --git a/public/docs/dart/latest/tutorial/toh-pt6.jade b/public/docs/dart/latest/tutorial/toh-pt6.jade index 6536c1a7d3..bee08c95de 100644 --- a/public/docs/dart/latest/tutorial/toh-pt6.jade +++ b/public/docs/dart/latest/tutorial/toh-pt6.jade @@ -25,7 +25,8 @@ block http-library ### Pubspec updates - We need to add a package dependency for the !{_Angular_http_library}. + We need to add package dependencies for the + `stream_transformers` and !{_Angular_http_library}s. We also need to add a `resolved_identifiers` entry, to inform the [angular2 transformer][ng2x] that we'll be using `BrowserClient`. (For an explanation of why @@ -37,7 +38,7 @@ block http-library [guide-http]: ../guide/server-communication.html#!#http-providers [ng2x]: https://github.com/angular/angular/wiki/Angular-2-Dart-Transformer - - var stylePattern = { pnk: /(http.*|resolved_identifiers:|Browser.*|Client.*)/gm }; + - var stylePattern = { pnk: /(http.*|stream.*|resolved_identifiers:|Browser.*|Client.*)/gm }; +makeExcerpt('pubspec.yaml', 'additions', null, stylePattern) block http-providers @@ -55,7 +56,13 @@ block backend implementations. block dont-be-distracted-by-backend-subst - //- N/A + //- No backend substitution but we do need to comment on the changes to Hero. + :marked + As is common for web API services, our mock in-memory service will be + encoding and decoding heroes in JSON format, so we enhance the `Hero` + class with these capabilities: + + +makeExample('lib/hero.dart') block get-heroes-details :marked @@ -89,8 +96,42 @@ block heroes-comp-add block review //- Not showing animated gif due to differences between TS and Dart implementations. -block observables-section - //- TBC +block observables-section-intro + :marked + Recall that `HeroService.getHeroes()` awaits for an `http.get()` + response and yields a _Future_ `List`, which is fine when we are only + interested in a single result. + +block search-criteria-intro + :marked + A [StreamController][], as its name implies, is a controller for a [Stream][] that allows us to + manipulate the underlying stream by adding data to it, for example. + + In our sample, the underlying stream of strings (`_searchTerms.stream`) represents the hero + name search patterns entered by the user. Each call to `search` puts a new string into + the stream by calling `add` over the controller. + + [Stream]: https://api.dartlang.org/stable/dart-async/Stream-class.html + [StreamController]: https://api.dartlang.org/stable/dart-async/StreamController-class.html + +block observable-transformers + :marked + Fortunately, there are stream transformers that will help us reduce the request flow. + We'll make fewer calls to the `HeroSearchService` and still get timely results. Here's how: + + * `transform(new Debounce(... 300)))` waits until the flow of search terms pauses for 300 + milliseconds before passing along the latest string. We'll never make requests more frequently + than 300ms. + + * `distinct()` ensures that we only send a request if a search term has changed. + There's no point in repeating a request for the same search term. + + * `transform(new FlatMapLatest(...))` applies a map-like transformer that (1) calls our search + service for each search term that makes it through the debounce and distinct gauntlet and (2) + returns only the most recent search service result, discarding any previous results. + + * `handleError()` handles errors. Our simple example prints the error to the console; a real + life application should do better. block filetree .filetree @@ -98,47 +139,65 @@ block filetree .children .file lib .children - .file app_component.dart .file app_component.css + .file app_component.dart .file dashboard_component.css - .file dashboard_component.html .file dashboard_component.dart + .file dashboard_component.html .file hero.dart .file hero_detail_component.css - .file hero_detail_component.html .file hero_detail_component.dart + .file hero_detail_component.html + .file hero_search_component.css (new) + .file hero_search_component.dart (new) + .file hero_search_component.html (new) + .file hero_search_service.dart (new) .file hero_service.dart .file heroes_component.css - .file heroes_component.html .file heroes_component.dart - .file main.dart + .file heroes_component.html .file in_memory_data_service.dart (new) .file web .children .file main.dart .file index.html - .file sample.css (new) .file styles.css .file pubspec.yaml block file-summary +makeTabs( - `toh-6/dart/lib/hero.dart, + `toh-6/dart/lib/dashboard_component.dart, + toh-6/dart/lib/dashboard_component.html, + toh-6/dart/lib/hero.dart, toh-6/dart/lib/hero_detail_component.dart, toh-6/dart/lib/hero_detail_component.html, toh-6/dart/lib/hero_service.dart, - toh-6/dart/lib/heroes_component.dart, - toh-6/dart/web/index.html, - toh-6/dart/web/main.dart, - toh-6/dart/web/sample.css`, - `,,,,,,final,`, - `lib/hero.dart, + toh-6/dart/lib/heroes_component.css, + toh-6/dart/lib/heroes_component.dart`, + null, + `lib/dashboard_component.dart, + lib/dashboard_component.html, + lib/hero.dart, lib/hero_detail_component.dart, lib/hero_detail_component.html, lib/hero_service.dart, - lib/heroes_component.dart, - web/index.html, - web/main.dart, - web/sample.css`) + lib/heroes_component.css, + lib/heroes_component.dart`) - +makeExample('pubspec.yaml') + +makeTabs( + `toh-6/dart/lib/hero_search_component.css, + toh-6/dart/lib/hero_search_component.dart, + toh-6/dart/lib/hero_search_component.html, + toh-6/dart/lib/hero_search_service.dart`, + null, + `lib/hero_search_component.css, + lib/hero_search_component.dart, + lib/hero_search_component.html, + lib/hero_search_service.dart`) + + +makeTabs( + `toh-6/dart/pubspec.yaml, + toh-6/dart/web/main.dart`, + `,final`, + `pubspec.yaml, + web/main.dart`) diff --git a/public/docs/ts/latest/tutorial/toh-pt6.jade b/public/docs/ts/latest/tutorial/toh-pt6.jade index c7edf449fc..4730b7e61f 100644 --- a/public/docs/ts/latest/tutorial/toh-pt6.jade +++ b/public/docs/ts/latest/tutorial/toh-pt6.jade @@ -111,7 +111,7 @@ block dont-be-distracted-by-backend-subst Look at our current `HeroService` implementation -+makeExample('toh-4/ts/app/hero.service.ts', 'get-heroes', 'app/hero.service.ts (old getHeroes)')(format=".") ++makeExcerpt('toh-4/ts/app/hero.service.ts (old getHeroes)', 'get-heroes') :marked We returned a !{_Promise} resolved with mock heroes. @@ -135,7 +135,7 @@ block get-heroes-details For *now* we get back on familiar ground by immediately by converting that `Observable` to a `Promise` using the `toPromise` operator. - +makeExample('toh-6/ts/app/hero.service.ts', 'to-promise')(format=".") + +makeExcerpt('app/hero.service.ts', 'to-promise', '') :marked Unfortunately, the Angular `Observable` doesn't have a `toPromise` operator ... not out of the box. The Angular `Observable` is a bare-bones implementation. @@ -143,13 +143,13 @@ block get-heroes-details There are scores of operators like `toPromise` that extend `Observable` with useful capabilities. If we want those capabilities, we have to add the operators ourselves. That's as easy as importing them from the RxJS library like this: - +makeExample('toh-6/ts/app/hero.service.ts', 'rxjs')(format=".") + +makeExcerpt('app/hero.service.ts', 'rxjs', '') :marked ### Extracting the data in the *then* callback In the *promise*'s `then` callback we call the `json` method of the http `Response` to extract the data within the response. - +makeExample('toh-6/ts/app/hero.service.ts', 'to-data')(format=".") + +makeExcerpt('app/hero.service.ts', 'to-data', '') :marked That response JSON has a single `data` property. @@ -172,12 +172,15 @@ block get-heroes-details ### Error Handling At the end of `getHeroes()` we `catch` server failures and pass them to an error handler: -+makeExcerpt('app/hero.service.ts', 'catch') + ++makeExcerpt('app/hero.service.ts', 'catch', '') + :marked This is a critical step! We must anticipate HTTP failures as they happen frequently for reasons beyond our control. -+makeExcerpt('app/hero.service.ts', 'handleError') ++makeExcerpt('app/hero.service.ts', 'handleError', '') + - var rejected_promise = _docsFor == 'dart' ? 'propagated exception' : 'rejected promise'; :marked In this demo service we log the error to the console; we should do better in real life. @@ -209,7 +212,7 @@ block get-heroes-details ### Put - Put will be used to update an individual hero. Its structure is very similar to Post requests. The only difference is that we have to change the url slightly by appending the id of the hero we want to update. + Put will be used to update an individual hero. Its structure is very similar to Post requests. The only difference is that we have to change the URL slightly by appending the id of the hero we want to update. +makeExcerpt('app/hero.service.ts', 'put') @@ -259,7 +262,7 @@ block hero-detail-comp-updates +makeExcerpt('app/hero-detail.component.ts', 'ngOnInit') :marked - In order to differentiate between add and edit we are adding a check to see if an id is passed in the url. If the id is absent we bind `HeroDetailComponent` to an empty `Hero` object. In either case, any edits made through the UI will be bound back to the same `hero` property. + In order to differentiate between add and edit we are adding a check to see if an id is passed in the URL. If the id is absent we bind `HeroDetailComponent` to an empty `Hero` object. In either case, any edits made through the UI will be bound back to the same `hero` property. :marked Add a save method to `HeroDetailComponent` and call the corresponding save method in `HeroesService`. @@ -315,7 +318,7 @@ block add-new-hero-via-detail-comp The user can *delete* an existing hero by clicking a delete button next to the hero's name. Add the following to the heroes component HTML right after the hero name in the repeated `
  • ` tag: -+makeExample('app/heroes.component.html', 'delete') ++makeExcerpt('app/heroes.component.html', 'delete') :marked Now let's fix-up the `HeroesComponent` to support the *add* and *delete* actions used in the template. @@ -357,12 +360,13 @@ block review ### Let's see it Here are the fruits of labor in action: figure.image-display - img(src='/resources/images/devguide/toh/toh-http.anim.gif' alt="Heroes List Editting w/ HTTP") + img(src='/resources/images/devguide/toh/toh-http.anim.gif' alt="Heroes List Editing w/ HTTP") -block observables-section +:marked + ## !{_Observable}s + +block observables-section-intro :marked - ## Observables - Each `Http` method returns an `Observable` of HTTP `Response` objects. Our `HeroService` converts that `Observable` into a `Promise` and returns the promise to the caller. @@ -384,59 +388,78 @@ block observables-section A single result in the form of a promise is easy for the calling component to consume and it helps that promises are widely understood by JavaScript programmers. - But requests aren't always "one and done". We may start one request, - then cancel it, and make a different request ... before the server has responded to the first request. - Such a _request-cancel-new-request_ sequence is difficult to implement with *promises*. - It's easy with *observables* as we'll see. +:marked + But requests aren't always "one and done". We may start one request, + then cancel it, and make a different request before the server has responded to the first request. + Such a _request-cancel-new-request_ sequence is difficult to implement with *!{_Promise}s*. + It's easy with *!{_Observable}s* as we'll see. - ### Search-by-name - We're going to add a *hero search* feature to the Tour of Heroes. - As the user types a name into a search box, we'll make repeated http requests for heroes filtered by that name. + ### Search-by-name + We're going to add a *hero search* feature to the Tour of Heroes. + As the user types a name into a search box, we'll make repeated HTTP requests for heroes filtered by that name. - We start by creating `HeroSearchService` that sends search queries to our server's web api. + We start by creating `HeroSearchService` that sends search queries to our server's web api. - +makeExample('toh-6/ts/app/hero-search.service.ts', null, 'app/hero-search.service.ts')(format=".") ++makeExample('app/hero-search.service.ts') +:marked + The `!{_priv}http.get()` call in `HeroSearchService` is similar to the one + in the `HeroService`, although the URL now has a query string. + Another notable difference: we no longer call `toPromise`, + we simply return the *observable* instead. + + ### HeroSearchComponent + + Let's create a new `HeroSearchComponent` that calls this new `HeroSearchService`. + + The component template is simple — just a text box and a list of matching search results. + ++makeExample('app/hero-search.component.html') + +:marked + As the user types in the search box, a *keyup* event binding calls the component's `search` method with the new search box value. + + The `*ngFor` repeats *hero* objects from the component's `heroes` property. No surprise there. + + But, as we'll soon see, the `heroes` property is now !{_an} *!{_Observable}* of hero !{_array}s, rather than just a hero !{_array}. + The `*ngFor` can't do anything with !{_an} `!{_Observable}` until we flow it through the `async` pipe (`AsyncPipe`). + The `async` pipe subscribes to the `!{_Observable}` and produces the !{_array} of heroes to `*ngFor`. + + Time to create the `HeroSearchComponent` class and metadata. + ++makeExample('app/hero-search.component.ts') + +:marked + #### Search terms + + Let's focus on the `!{_priv}searchTerms`: + ++makeExcerpt('app/hero-search.component.ts', 'searchTerms', '') + +block search-criteria-intro :marked - The `http.get` call in `HeroSearchService` is similar to the `http.get` call in the `HeroService`. - The notable difference: we no longer call `toPromise`. - We simply return the *observable* instead. - - ### HeroSearchComponent - Let's create a new `HeroSearchComponent` that calls this new `HeroSearchService`. - - The component template is simple - just a textbox and a list of matching search results. - +makeExample('toh-6/ts/app/hero-search.component.html', null,'hero-search.component.html') - :marked - As the user types in the search box, a *keyup* event binding calls the component's `search` with the new search box value. - - The `*ngFor` repeats *hero* objects from the component's `heroes` property. No surprise there. - - But, as we'll soon see, the `heroes` property returns an `Observable` of heroes, not an array of heroes. - The `*ngFor` can't do anything with an observable until we flow it through the `AsyncPipe` (`heroes | async`). - The `AsyncPipe` subscribes to the observable and produces the array of heroes to `*ngFor`. - - Time to create the `HeroSearchComponent` class and metadata. - +makeExample('toh-6/ts/app/hero-search.component.ts', null,'hero-search.component.ts') - :marked - Focus on the `searchTerms`. - +makeExample('toh-6/ts/app/hero-search.component.ts', 'searchTerms')(format=".") - :marked - A `Subject` is a producer of an _observable_ event stream. - This `searchTerms` produces an `Observable` of strings, the filter criteria for the name search. + A `Subject` is a producer of an _observable_ event stream; + `searchTerms` produces an `Observable` of strings, the filter criteria for the name search. Each call to `search` puts a new string into this subject's _observable_ stream by calling `next`. - A `Subject` is also an `Observable`. - We're going to access that `Observable` and turn the stream - of strings into a stream of `Hero[]` arrays, the `heroes` property. +:marked + + #### Initialize the _**heroes**_ property (_**ngOnInit**_) - +makeExample('toh-6/ts/app/hero-search.component.ts', 'search')(format=".") + A `Subject` is also an `Observable`. + We're going to turn the stream + of search terms into a stream of `Hero` !{_array}s and assign the result to the `heroes` property. + ++makeExcerpt('app/hero-search.component.ts', 'search', '') + +:marked + If we passed every user keystroke directly to the `HeroSearchService`, we'd unleash a storm of HTTP requests. + Bad idea. We don't want to tax our server resources and burn through our cellular network data plan. + +block observable-transformers :marked - If we passed every user keystroke directly to the `HeroSearchService`, we'd unleash a storm of http requests. - Bad idea. We don't want to tax our server resources and burn through our cellular network data plan. - - Fortunately we can chain `Observable` operators to the string `Observable` that reduce the request flow. + Fortunately, we can chain `Observable` operators to the string `Observable` that reduce the request flow. We'll make fewer calls to the `HeroSearchService` and still get timely results. Here's how: * `debounceTime(300)` waits until the flow of new string events pauses for 300 milliseconds @@ -486,30 +509,31 @@ block observables-section We take a different approach in this example. We combine all of the RxJS `Observable` extensions that _our entire app_ requires into a single RxJS imports file. - +makeExample('toh-6/ts/app/rxjs-extensions.ts', null, 'app/rxjs-extensions.ts')(format=".") + +makeExample('app/rxjs-extensions.ts') + :marked We load them all at once by importing `rxjs-extensions` in `AppComponent`. - +makeExample('toh-6/ts/app/app.component.ts', 'rxjs-extensions', 'app/app.component.ts')(format=".") + +makeExcerpt('app/app.component.ts', 'rxjs-extensions') - :marked - ### Add the search component to the dashboard +:marked + ### Add the search component to the dashboard - We add the hero search HTML element to the bottom of the `DashboardComponent` template. + We add the hero search HTML element to the bottom of the `DashboardComponent` template. - +makeExample('app/dashboard.component.html') ++makeExample('app/dashboard.component.html') - :marked - And finally, we import the `HeroSearchComponent` and add it to the `directives` array. +:marked + And finally, we import the `HeroSearchComponent` and add it to the `directives` !{_array}. - +makeExcerpt('app/dashboard.component.ts', 'hero-search-component') ++makeExcerpt('app/dashboard.component.ts', 'search') - :marked - Run the app again, go to the *Dashboard*, and enter some text in the search box below the hero tiles. - At some point it might look like this. +:marked + Run the app again, go to the *Dashboard*, and enter some text in the search box. + At some point it might look like this. - figure.image-display - img(src='/resources/images/devguide/toh/toh-hero-search.png' alt="Hero Search Component") +figure.image-display + img(src='/resources/images/devguide/toh/toh-hero-search.png' alt="Hero Search Component") .l-main-section :marked @@ -534,9 +558,9 @@ block filetree .file hero-detail.component.css .file hero-detail.component.html .file hero-detail.component.ts - .file hero-search.component.html - .file hero-search.component.ts - .file hero-search.service.ts + .file hero-search.component.html (new) + .file hero-search.component.ts (new) + .file hero-search.service.ts (new) .file rxjs-operators.ts .file hero.service.ts .file heroes.component.css @@ -559,14 +583,14 @@ block filetree ## Home Stretch We are at the end of our journey for now, but we have accomplished a lot. - - We added the necessary dependencies to use Http in our application. - - We refactored HeroService to load heroes from an API. - - We extended HeroService to support post, put and delete calls. + - We added the necessary dependencies to use HTTP in our application. + - We refactored `HeroService` to load heroes from a web API. + - We extended `HeroService` to support post, put and delete methods. - We updated our components to allow adding, editing and deleting of heroes. - We configured an in-memory web API. -
  • We learned how to use Observables.
  • + - We learned how to use !{_Observable}s. - Below is a summary of the files we changed and added. + Here are the files we added or changed in this chapter. block file-summary +makeTabs( @@ -599,4 +623,4 @@ block file-summary hero-search.component.ts, hero-search.service.html, rxjs-operators.ts` -) + ) From a423724847b717c7f6f61599c6ef986f046c4576 Mon Sep 17 00:00:00 2001 From: Kathy Walrath Date: Wed, 3 Aug 2016 12:29:04 -0700 Subject: [PATCH 10/20] docs(dart): update angular.io/dart's link to change log --- public/docs/dart/latest/_data.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/docs/dart/latest/_data.json b/public/docs/dart/latest/_data.json index ab9169d800..a93259c9ab 100644 --- a/public/docs/dart/latest/_data.json +++ b/public/docs/dart/latest/_data.json @@ -3,7 +3,7 @@ "icon": "home", "title": "Angular Docs", "menuTitle": "Docs Home", - "banner": "Welcome to angular.io/dart! The current Angular 2 Dart release is beta.18. Consult the Change Log about recent enhancements, fixes, and breaking changes." + "banner": "Welcome to angular.io/dart! The current Angular 2 Dart release is beta.18. Consult the Change Log about recent enhancements, fixes, and breaking changes." }, "quickstart": { From 6a2cad2640f73133de71b537cf1723b5ced18876 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Fri, 5 Aug 2016 11:13:32 -0700 Subject: [PATCH 11/20] docs(chore): ensure {forms|router}{,-deprecated} chapters have proper content (#2034) Fixes #2026. --- public/docs/dart/latest/guide/_data.json | 37 +++++++++++-------- .../dart/latest/guide/forms-deprecated.html | 1 - .../dart/latest/guide/forms-deprecated.jade | 5 +++ .../dart/latest/guide/router-deprecated.jade | 6 ++- public/docs/dart/latest/guide/router.jade | 7 +--- 5 files changed, 33 insertions(+), 23 deletions(-) delete mode 100644 public/docs/dart/latest/guide/forms-deprecated.html create mode 100644 public/docs/dart/latest/guide/forms-deprecated.jade diff --git a/public/docs/dart/latest/guide/_data.json b/public/docs/dart/latest/guide/_data.json index eff9a7e77e..2b3bdf70e5 100644 --- a/public/docs/dart/latest/guide/_data.json +++ b/public/docs/dart/latest/guide/_data.json @@ -36,6 +36,14 @@ "basics": true }, + "forms-deprecated": { + "title": "Forms", + "intro": "A form creates a cohesive, effective, and compelling data entry experience. An Angular form coordinates a set of data-bound user controls, tracks changes, validates input, and presents errors.", + "nextable": true, + "basics": true, + "hide": true + }, + "dependency-injection": { "title": "Dependency Injection", "intro": "Angular's dependency injection system creates and delivers dependent services \"just-in-time\".", @@ -63,6 +71,11 @@ "basics": true }, + "animations": { + "title": "Animations", + "intro": "A guide to Angular's animation system." + }, + "attribute-directives": { "title": "Attribute Directives", "intro": "Attribute directives attach behavior to elements." @@ -79,11 +92,6 @@ "basics": true }, - "security": { - "title": "Security", - "intro": "Prevent security vulnerabilities" - }, - "hierarchical-dependency-injection": { "title": "Hierarchical Dependency Injectors", "navTitle": "Hierarchical Injectors", @@ -112,14 +120,19 @@ }, "router-deprecated": { - "title": "Router (Deprecated Beta)", - "intro": "The deprecated Beta Router." + "title": "Routing & Navigation", + "intro": "Discover the basics of screen navigation with the Angular 2 Component Router.", + "hide": true }, "router": { "title": "Routing & Navigation", - "intro": "Discover the basics of screen navigation with the Angular 2 router.", - "hide": true + "intro": "Discover the basics of screen navigation with the Angular 2 Component Router." + }, + + "security": { + "title": "Security", + "intro": "Developing for content security in Angular applications" }, "structural-directives": { @@ -149,11 +162,5 @@ "title": "Webpack: an introduction", "intro": "Create your Angular 2 applications with a Webpack based tooling", "hide": true - }, - - "glossary": { - "title": "Glossary", - "intro": "Brief definitions of the most important words in the Angular 2 vocabulary", - "basics": true } } diff --git a/public/docs/dart/latest/guide/forms-deprecated.html b/public/docs/dart/latest/guide/forms-deprecated.html deleted file mode 100644 index f8df2a84a6..0000000000 --- a/public/docs/dart/latest/guide/forms-deprecated.html +++ /dev/null @@ -1 +0,0 @@ -!= partial("../../../_includes/_ts-temp") \ No newline at end of file diff --git a/public/docs/dart/latest/guide/forms-deprecated.jade b/public/docs/dart/latest/guide/forms-deprecated.jade new file mode 100644 index 0000000000..184b0c79e2 --- /dev/null +++ b/public/docs/dart/latest/guide/forms-deprecated.jade @@ -0,0 +1,5 @@ +include ../_util-fns + +:marked + There is no deprecated forms library in Angular Dart. + The forms guide is [here](forms.html). diff --git a/public/docs/dart/latest/guide/router-deprecated.jade b/public/docs/dart/latest/guide/router-deprecated.jade index f8df2a84a6..e8a92f6ed2 100644 --- a/public/docs/dart/latest/guide/router-deprecated.jade +++ b/public/docs/dart/latest/guide/router-deprecated.jade @@ -1 +1,5 @@ -!= partial("../../../_includes/_ts-temp") \ No newline at end of file +include ../_util-fns + +:marked + There is no deprecated router library in Angular Dart. + The router guide is [here](router.html). diff --git a/public/docs/dart/latest/guide/router.jade b/public/docs/dart/latest/guide/router.jade index c7d0130990..f8df2a84a6 100644 --- a/public/docs/dart/latest/guide/router.jade +++ b/public/docs/dart/latest/guide/router.jade @@ -1,6 +1 @@ -include ../_util-fns - -:marked - We're working on the Dart version of this chapter. - In the meantime, please read the - [TypeScript version of this chapter](/docs/ts/latest/guide/router.html). +!= partial("../../../_includes/_ts-temp") \ No newline at end of file From 531d6a8bcec1512baae6f0cb885fcf026fefe287 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Fri, 5 Aug 2016 12:13:29 -0700 Subject: [PATCH 12/20] docs(glossary/dart): recover content (#2037) Fixes #1918. Follow-up work will be done under #2036. --- public/docs/dart/latest/glossary.jade | 60 ++++++++----------- public/docs/dart/latest/guide/_data.json | 1 - .../dart/latest/guide/forms-deprecated.jade | 3 +- public/docs/dart/latest/guide/glossary.jade | 5 +- .../dart/latest/guide/router-deprecated.jade | 3 +- 5 files changed, 31 insertions(+), 41 deletions(-) diff --git a/public/docs/dart/latest/glossary.jade b/public/docs/dart/latest/glossary.jade index 4dad0d501e..673436c805 100644 --- a/public/docs/dart/latest/glossary.jade +++ b/public/docs/dart/latest/glossary.jade @@ -1,45 +1,35 @@ include _util-fns -// From ts/glossary.jade, the folder ts/latest/_fragments is generated which contains a bunch of partial files. -// These partials comprise the glossary,a subset of these partials should be used to generate the glossary for -// __dart__ under BASICS. -!=partial('../../ts/latest/_fragments/glossary-intro') -!=partial('../../ts/latest/_fragments/glossary-a-2') -!=partial('../../ts/latest/_fragments/glossary-b-c') -!=partial('../../ts/latest/_fragments/glossary-d1') -!=partial('../../ts/latest/_fragments/glossary-d2') -!=partial('../../ts/latest/_fragments/glossary-e1') -!=partial('../../ts/latest/_fragments/glossary-e2') -!=partial('../../ts/latest/_fragments/glossary-f-l') -!=partial('../../ts/latest/_fragments/glossary-m1') -//!=partial('../../ts/latest/_fragments/glossary-m2') not needed in dart -!=partial('../../ts/latest/_fragments/glossary-n-s-1') + +block var-def + - var fragPath='../../ts/latest/_fragments/'; + +!=partial(fragPath + 'glossary-intro') +!=partial(fragPath + 'glossary-a1') +!=partial(fragPath + 'glossary-a-2') +!=partial(fragPath + 'glossary-b-c') +!=partial(fragPath + 'glossary-d1') +!=partial(fragPath + 'glossary-d2') +!=partial(fragPath + 'glossary-e1') +!=partial(fragPath + 'glossary-e2') +!=partial(fragPath + 'glossary-f-l') +!=partial(fragPath + 'glossary-m1') +//partial(fragPath + 'glossary-m2') not needed in dart +!=partial(fragPath + 'glossary-n-s-1') :marked ## snake_case + .l-sub-section :marked - The practice of writing compound words or phrases such that each word is separated by an underscore (`_`). + The practice of writing compound words or phrases such that each word is separated by an + underscore (`_`). - Library and file names are often spelled in snake_case. Examples include: `angular2_tour_of_heroes` and `app_component.dart`. + Library and file names are often spelled in snake_case. Examples include: + `angular2_tour_of_heroes` and `app_component.dart`. This form is also known as **underscore case**. -!=partial('../../ts/latest/_fragments/glossary-n-s-2') -!=partial('../../ts/latest/_fragments/glossary-t1') -//!=partial('../../ts/latest/_fragments/glossary-t2') notneeded in dart -!=partial('../../ts/latest/_fragments/glossary-u-z') - -// NOTE: (ericjim): I am almost certain these lines are doing nothing, -// so instead I use `!=partial` to include the glossary fragments. -//+includeShared('{ts}', 'intro') -//+includeShared('{ts}', 'a2') -//+includeShared('{ts}', 'b-c') -//+includeShared('{ts}', 'd1') -//+includeShared('{ts}', 'd2') -//+includeShared('{ts}', 'e1') -//+includeShared('{ts}', 'e2') -//+includeShared('{ts}', 'f-l') -//+includeShared('{ts}', 'm1') -//+includeShared('{ts}', 'n-s') -//+includeShared('{ts}', 't1') -//+includeShared('{ts}', 'u-z') +!=partial(fragPath + 'glossary-n-s-2') +!=partial(fragPath + 'glossary-t1') +//partial(fragPath + 'glossary-t2') notneeded in dart +!=partial(fragPath + 'glossary-u-z') diff --git a/public/docs/dart/latest/guide/_data.json b/public/docs/dart/latest/guide/_data.json index 2b3bdf70e5..c97d5f8043 100644 --- a/public/docs/dart/latest/guide/_data.json +++ b/public/docs/dart/latest/guide/_data.json @@ -39,7 +39,6 @@ "forms-deprecated": { "title": "Forms", "intro": "A form creates a cohesive, effective, and compelling data entry experience. An Angular form coordinates a set of data-bound user controls, tracks changes, validates input, and presents errors.", - "nextable": true, "basics": true, "hide": true }, diff --git a/public/docs/dart/latest/guide/forms-deprecated.jade b/public/docs/dart/latest/guide/forms-deprecated.jade index 184b0c79e2..f5711f49ee 100644 --- a/public/docs/dart/latest/guide/forms-deprecated.jade +++ b/public/docs/dart/latest/guide/forms-deprecated.jade @@ -1,5 +1,4 @@ include ../_util-fns :marked - There is no deprecated forms library in Angular Dart. - The forms guide is [here](forms.html). + This page has no Dart equivalent. Instead, see the [forms guide](forms.html). diff --git a/public/docs/dart/latest/guide/glossary.jade b/public/docs/dart/latest/guide/glossary.jade index ca1429104e..eeef440cb0 100644 --- a/public/docs/dart/latest/guide/glossary.jade +++ b/public/docs/dart/latest/guide/glossary.jade @@ -1 +1,4 @@ -include ../glossary +extends ../glossary + +block var-def + - var fragPath='../../../ts/latest/_fragments/'; diff --git a/public/docs/dart/latest/guide/router-deprecated.jade b/public/docs/dart/latest/guide/router-deprecated.jade index e8a92f6ed2..d76267fce1 100644 --- a/public/docs/dart/latest/guide/router-deprecated.jade +++ b/public/docs/dart/latest/guide/router-deprecated.jade @@ -1,5 +1,4 @@ include ../_util-fns :marked - There is no deprecated router library in Angular Dart. - The router guide is [here](router.html). + This page has no Dart equivalent. Instead, see the [router guide](router.html). From b93fb12fea33f149f8561abb7b76e0e7fd7a8a1a Mon Sep 17 00:00:00 2001 From: Brandon Roberts Date: Sat, 30 Jul 2016 21:00:52 -0500 Subject: [PATCH 13/20] chore(examples): Updated live example links to use helper directive closes #2005 --- public/docs/js/latest/cookbook/ts-to-js.jade | 4 ++-- public/docs/js/latest/guide/forms-deprecated.jade | 3 ++- public/docs/js/latest/guide/forms.jade | 2 +- public/docs/js/latest/quickstart.jade | 2 +- .../docs/ts/latest/cookbook/a1-a2-quick-reference.jade | 2 +- .../ts/latest/cookbook/component-communication.jade | 2 +- .../ts/latest/cookbook/component-relative-paths.jade | 2 +- .../docs/ts/latest/cookbook/dependency-injection.jade | 10 +++++----- .../ts/latest/cookbook/dynamic-form-deprecated.jade | 2 +- public/docs/ts/latest/cookbook/dynamic-form.jade | 2 +- public/docs/ts/latest/cookbook/set-document-title.jade | 2 +- public/docs/ts/latest/guide/animations.jade | 2 +- public/docs/ts/latest/guide/forms-deprecated.jade | 2 +- public/docs/ts/latest/guide/forms.jade | 2 +- public/docs/ts/latest/guide/index.jade | 2 +- public/docs/ts/latest/guide/router-deprecated.jade | 10 +++++----- public/docs/ts/latest/guide/router.jade | 10 +++++----- public/docs/ts/latest/guide/user-input.jade | 2 +- public/resources/js/directives/if-docs.js | 2 +- public/resources/js/directives/live-example.js | 6 ++++-- public/resources/js/directives/ngio-ex-path.js | 2 +- public/resources/js/util.js | 4 ++-- 22 files changed, 40 insertions(+), 37 deletions(-) diff --git a/public/docs/js/latest/cookbook/ts-to-js.jade b/public/docs/js/latest/cookbook/ts-to-js.jade index c76fee3207..5a834fb5fb 100644 --- a/public/docs/js/latest/cookbook/ts-to-js.jade +++ b/public/docs/js/latest/cookbook/ts-to-js.jade @@ -26,8 +26,8 @@ include ../../../../_includes/_util-fns [Host and Query Metadata](#other-property-metadata) - **Run and compare the live [TypeScript](/resources/live-examples/cb-ts-to-js/ts/plnkr.html) and - [JavaScript](/resources/live-examples/cb-ts-to-js/js/plnkr.html) code shown in this cookbook.** + **Run and compare the live TypeScript and JavaScript + code shown in this cookbook.** a(id="modularity") .l-main-section diff --git a/public/docs/js/latest/guide/forms-deprecated.jade b/public/docs/js/latest/guide/forms-deprecated.jade index e17b9fe46c..5a963272c8 100644 --- a/public/docs/js/latest/guide/forms-deprecated.jade +++ b/public/docs/js/latest/guide/forms-deprecated.jade @@ -35,7 +35,8 @@ include ../_util-fns - How to share information across controls with template local variables - [Live Example](/resources/live-examples/forms-deprecated/js/plnkr.html) + Live Example + .l-main-section :marked ## Template-Driven Forms diff --git a/public/docs/js/latest/guide/forms.jade b/public/docs/js/latest/guide/forms.jade index 2613b7b6b7..09a942b236 100644 --- a/public/docs/js/latest/guide/forms.jade +++ b/public/docs/js/latest/guide/forms.jade @@ -35,7 +35,7 @@ include ../_util-fns - How to share information across controls with template local variables - [Live Example](/resources/live-examples/forms/js/plnkr.html) + Live Example .l-main-section :marked diff --git a/public/docs/js/latest/quickstart.jade b/public/docs/js/latest/quickstart.jade index 2edd48bb7a..315d687414 100644 --- a/public/docs/js/latest/quickstart.jade +++ b/public/docs/js/latest/quickstart.jade @@ -13,7 +13,7 @@ include _util-fns :marked ## See It Run! - Running the [live example](/resources/live-examples/quickstart/js/plnkr.html) + Running the is the quickest way to see an Angular 2 app come to life. Clicking that link fires up a browser, loads the sample in [plunker](http://plnkr.co/ "Plunker"), diff --git a/public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade b/public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade index 980e4ecb84..8860d2bfe9 100644 --- a/public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade +++ b/public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade @@ -6,7 +6,7 @@ a(id="top") 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)**. + **See the Angular 2 syntax in this **. ## Contents This chapter covers diff --git a/public/docs/ts/latest/cookbook/component-communication.jade b/public/docs/ts/latest/cookbook/component-communication.jade index 014f5ffd88..da69eb5b15 100644 --- a/public/docs/ts/latest/cookbook/component-communication.jade +++ b/public/docs/ts/latest/cookbook/component-communication.jade @@ -30,7 +30,7 @@ include ../_util-fns [Parent and children communicate via a service](#bidirectional-service) :marked - **See the [live example](/resources/live-examples/cb-component-communication/ts/plnkr.html)**. + **See the **. .l-main-section diff --git a/public/docs/ts/latest/cookbook/component-relative-paths.jade b/public/docs/ts/latest/cookbook/component-relative-paths.jade index 814e790e58..4c274d5563 100644 --- a/public/docs/ts/latest/cookbook/component-relative-paths.jade +++ b/public/docs/ts/latest/cookbook/component-relative-paths.jade @@ -75,7 +75,7 @@ include ../_util-fns :marked ## Source - **We can see the [live example](/resources/live-examples/cb-component-relative-paths/ts/plnkr.html)** + **We can see the ** and download the source code from there or simply read the pertinent source here. +makeTabs( diff --git a/public/docs/ts/latest/cookbook/dependency-injection.jade b/public/docs/ts/latest/cookbook/dependency-injection.jade index 81fdb5c1c2..352ecd3c2b 100644 --- a/public/docs/ts/latest/cookbook/dependency-injection.jade +++ b/public/docs/ts/latest/cookbook/dependency-injection.jade @@ -45,7 +45,7 @@ include ../_util-fns [Break circularities with a forward class reference (*forwardRef*)](#forwardref) :marked - **See the [live example](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)** + **See the ** of the code supporting this cookbook. .l-main-section @@ -236,7 +236,7 @@ figure.image-display The getter for the `hero` property pulls the cached hero from the service. And the template displays this data-bound property. - Find this example in [live code](/resources/live-examples/cb-dependency-injection/ts/plnkr.html) + Find this example in live code and confirm that the three `HeroBioComponent` instances have their own cached hero data. figure.image-display img(src="/resources/images/cookbooks/dependency-injection/hero-bios.png" alt="Bios") @@ -535,7 +535,7 @@ a(id='usefactory') :marked The function retrieves candidate heroes from the `HeroService`, takes `2` of them to be the runners-up, and returns their concatenated names. - Look at the [live example](/resources/live-examples/cb-dependency-injection/ts/plnkr.html) + Look at the for the full source code. a(id="tokens") @@ -703,7 +703,7 @@ a(id='alex') +makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','cathy','parent-finder.component.ts (CathyComponent)')(format='.') :marked We added the [@Optional](#optional) qualifier for safety but - the [live example](/resources/live-examples/cb-dependency-injection/ts/plnkr.html) + the confirms that the `alex` parameter is set. @@ -737,7 +737,7 @@ a(id='alex') +makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','craig','parent-finder.component.ts (CraigComponent)')(format='.') :marked Unfortunately, this does not work. - The [live example](/resources/live-examples/cb-dependency-injection/ts/plnkr.html) + The confirms that the `alex` parameter is null. *We cannot inject a parent by its base class.* diff --git a/public/docs/ts/latest/cookbook/dynamic-form-deprecated.jade b/public/docs/ts/latest/cookbook/dynamic-form-deprecated.jade index 2efa5f8197..453b46bc7d 100644 --- a/public/docs/ts/latest/cookbook/dynamic-form-deprecated.jade +++ b/public/docs/ts/latest/cookbook/dynamic-form-deprecated.jade @@ -35,7 +35,7 @@ include ../_util-fns [Dynamic Template](#dynamic-template) :marked - **See the [live example](/resources/live-examples/cb-dynamic-form-deprecated/ts/plnkr.html)**. + **See the **. .l-main-section diff --git a/public/docs/ts/latest/cookbook/dynamic-form.jade b/public/docs/ts/latest/cookbook/dynamic-form.jade index e4eb6af1d4..2c865b64cf 100644 --- a/public/docs/ts/latest/cookbook/dynamic-form.jade +++ b/public/docs/ts/latest/cookbook/dynamic-form.jade @@ -37,7 +37,7 @@ include ../_util-fns [Dynamic Template](#dynamic-template) :marked - **See the [live example](/resources/live-examples/cb-dynamic-form/ts/plnkr.html)**. + **See the **. .l-main-section diff --git a/public/docs/ts/latest/cookbook/set-document-title.jade b/public/docs/ts/latest/cookbook/set-document-title.jade index 7424b1632c..9c545f5a0d 100644 --- a/public/docs/ts/latest/cookbook/set-document-title.jade +++ b/public/docs/ts/latest/cookbook/set-document-title.jade @@ -5,7 +5,7 @@ a(id='top') Our app should be able to make the browser title bar say whatever we want it to say. This cookbook explains how to do it. :marked - **See the [live example](/resources/live-examples/cb-set-document-title/ts/plnkr.html)**. + **See the **. .l-sub-section img(src='/resources/images/devguide/plunker-separate-window-button.png' alt="pop out the window" align="right" style="margin-right:-20px") :marked diff --git a/public/docs/ts/latest/guide/animations.jade b/public/docs/ts/latest/guide/animations.jade index 6a14d4b0d4..9b198261f9 100644 --- a/public/docs/ts/latest/guide/animations.jade +++ b/public/docs/ts/latest/guide/animations.jade @@ -37,7 +37,7 @@ include ../_util-fns .l-sub-section :marked - The examples referenced in this chapter are available as a [live example](/resources/live-examples/animations/ts/plnkr.html). + The examples referenced in this chapter are available as a . a(id="example-transitioning-between-states") .l-main-section diff --git a/public/docs/ts/latest/guide/forms-deprecated.jade b/public/docs/ts/latest/guide/forms-deprecated.jade index 0be1f0bfff..f29cb3087a 100644 --- a/public/docs/ts/latest/guide/forms-deprecated.jade +++ b/public/docs/ts/latest/guide/forms-deprecated.jade @@ -35,7 +35,7 @@ include ../_util-fns - sharing information among controls with template reference variables - [Live Example](/resources/live-examples/forms-deprecated/ts/plnkr.html) + Live Example .l-main-section :marked ## Template-Driven Forms diff --git a/public/docs/ts/latest/guide/forms.jade b/public/docs/ts/latest/guide/forms.jade index 929a7ad0dd..90facf5e1f 100644 --- a/public/docs/ts/latest/guide/forms.jade +++ b/public/docs/ts/latest/guide/forms.jade @@ -37,7 +37,7 @@ include ../_util-fns - sharing information among controls with template reference variables - [Live Example](/resources/live-examples/forms/ts/plnkr.html) + Live Example .l-main-section :marked diff --git a/public/docs/ts/latest/guide/index.jade b/public/docs/ts/latest/guide/index.jade index 9fc8f82f68..282029cda9 100644 --- a/public/docs/ts/latest/guide/index.jade +++ b/public/docs/ts/latest/guide/index.jade @@ -100,7 +100,7 @@ table(width="100%") block example-links :marked Look for a link to a running version of that sample near the top of each page, - such as this [live example](/resources/live-examples/architecture/ts/plnkr.html) from the [Architecture](architecture.html) chapter. + such as this from the [Architecture](architecture.html) chapter. The link launches a browser-based code editor where we can inspect, modify, save, and download the code. diff --git a/public/docs/ts/latest/guide/router-deprecated.jade b/public/docs/ts/latest/guide/router-deprecated.jade index 5e758ce887..357ce7c10a 100644 --- a/public/docs/ts/latest/guide/router-deprecated.jade +++ b/public/docs/ts/latest/guide/router-deprecated.jade @@ -10,7 +10,7 @@ include ../_util-fns as users perform application tasks. We cover the router's primary features in this chapter, illustrating them through the evolution - of a small application that we can [run live](/resources/live-examples/router-deprecated/ts/plnkr.html). + of a small application that we can run live. .l-sub-section img(src='/resources/images/devguide/plunker-separate-window-button.png' alt="pop out the window" align="right" style="margin-right:-20px") :marked @@ -207,7 +207,7 @@ table We discuss code and design decisions pertinent to routing and application design. We gloss over everything in between. - The full source is available in the [live example](/resources/live-examples/router-deprecated/ts/plnkr.html). + The full source is available in the :marked Our client is the Hero Employment Agency. Heroes need work and The Agency finds Crises for them to solve. @@ -216,7 +216,7 @@ table 1. A *Crisis Center* where we maintain the list of crises for assignment to heroes. 1. A *Heroes* area where we maintain the list of heroes employed by The Agency. - Run the [live example](/resources/live-examples/router-deprecated/ts/plnkr.html). + Run the . It opens in the *Crisis Center*. We'll come back to that. Click the *Heroes* link. We're presented with a list of Heroes. @@ -1110,7 +1110,7 @@ code-example(format="." language="bash"). .l-sub-section :marked - The [live example](/resources/live-examples/router-deprecated/ts/plnkr.html) *does* highlight the selected + The *does* highlight the selected row because it demonstrates the final state of the application which includes the steps we're *about* to cover. At the moment we're describing the state of affairs *prior* to those steps. :marked @@ -1202,7 +1202,7 @@ code-example(format="." language="bash"). As we end our chapter, we take a parting look at the entire application. - We can always try the [live example](/resources/live-examples/router-deprecated/ts/plnkr.html) and download the source code from there. + We can always try the and download the source code from there. Our final project folder structure looks like this: .filetree diff --git a/public/docs/ts/latest/guide/router.jade b/public/docs/ts/latest/guide/router.jade index 84cc80ffad..e51f04f4dc 100644 --- a/public/docs/ts/latest/guide/router.jade +++ b/public/docs/ts/latest/guide/router.jade @@ -10,7 +10,7 @@ include ../_util-fns as users perform application tasks. We cover the router's primary features in this chapter, illustrating them through the evolution - of a small application that we can [run live](/resources/live-examples/router/ts/plnkr.html). + of a small application that we can run live. .l-sub-section img(src='/resources/images/devguide/plunker-separate-window-button.png' alt="pop out the window" align="right" style="margin-right:-20px") :marked @@ -250,7 +250,7 @@ table We discuss code and design decisions pertinent to routing and application design. We gloss over everything in between. - The full source is available in the [live example](/resources/live-examples/router/ts/plnkr.html). + The full source is available in the . :marked Our client is the Hero Employment Agency. Heroes need work and The Agency finds Crises for them to solve. @@ -259,7 +259,7 @@ table 1. A *Crisis Center* where we maintain the list of crises for assignment to heroes. 1. A *Heroes* area where we maintain the list of heroes employed by The Agency. - Run the [live example](/resources/live-examples/router/ts/plnkr.html). + Run the . It opens in the *Crisis Center*. We'll come back to that. Click the *Heroes* link. We're presented with a list of Heroes. @@ -1442,7 +1442,7 @@ code-example(format="." language="bash"). .l-sub-section :marked - The [live example](/resources/live-examples/router/ts/plnkr.html) *does* highlight the selected + The *does* highlight the selected row because it demonstrates the final state of the application which includes the steps we're *about* to cover. At the moment we're describing the state of affairs *prior* to those steps. :marked @@ -1529,7 +1529,7 @@ figure.image-display :marked ## Wrap Up We've covered a lot of ground in this chapter and the application is too big to reprint here. - Please visit the [live example](/resources/live-examples/router/ts/plnkr.html) and + Please visit the and where you can download the final source code. .l-main-section diff --git a/public/docs/ts/latest/guide/user-input.jade b/public/docs/ts/latest/guide/user-input.jade index f1fe56fb06..681b8d5e51 100644 --- a/public/docs/ts/latest/guide/user-input.jade +++ b/public/docs/ts/latest/guide/user-input.jade @@ -6,7 +6,7 @@ include ../_util-fns In this chapter we learn to bind to those events using the Angular event binding syntax. - [Run the live example](/resources/live-examples/user-input/ts/plnkr.html) + Run the live example :marked ## Binding to user input events diff --git a/public/resources/js/directives/if-docs.js b/public/resources/js/directives/if-docs.js index d273053512..f403cf1695 100644 --- a/public/resources/js/directives/if-docs.js +++ b/public/resources/js/directives/if-docs.js @@ -17,7 +17,7 @@ angularIO.directive('ifDocs', ['ngIfDirective', '$location', function (ngIfDirec terminal: ngIf.terminal, restrict: ngIf.restrict, link: function (scope, element, attrs) { - var ngIfCond = (attrs.ifDocs === 'dart') == !NgIoUtil.isDartDoc($location); + var ngIfCond = (attrs.ifDocs === 'dart') == !NgIoUtil.isDoc($location, 'dart'); attrs.ngIf = function () { return !ngIfCond; } ngIf.link.apply(ngIf, arguments); } diff --git a/public/resources/js/directives/live-example.js b/public/resources/js/directives/live-example.js index bb7f9c404c..1e6a6c749c 100644 --- a/public/resources/js/directives/live-example.js +++ b/public/resources/js/directives/live-example.js @@ -28,10 +28,12 @@ angularIO.directive('liveExample', ['$location', function ($location) { var ex = attrs.name || NgIoUtil.getExampleName($location); var href, template; - var isForDart = attrs.lang === 'dart' || NgIoUtil.isDartDoc($location); + var isForDart = attrs.lang === 'dart' || NgIoUtil.isDoc($location, 'dart'); + var isForJs = attrs.lang === 'js' || NgIoUtil.isDoc($location, 'js'); + var exLang = isForDart ? 'dart' : isForJs ? 'js' : 'ts'; var href = isForDart ? 'http://angular-examples.github.io/' + ex - : '/resources/live-examples/' + ex + '/ts/plnkr.html'; + : '/resources/live-examples/' + ex + '/' + exLang + '/plnkr.html'; // Link to live example. var template = a(text, { href: href, target: '_blank' }); diff --git a/public/resources/js/directives/ngio-ex-path.js b/public/resources/js/directives/ngio-ex-path.js index 72ee27309f..01b7cd546b 100644 --- a/public/resources/js/directives/ngio-ex-path.js +++ b/public/resources/js/directives/ngio-ex-path.js @@ -23,7 +23,7 @@ angularIO.directive('ngioEx', ['$location', function ($location) { compile: function (tElement, attrs) { var examplePath = attrs.path || tElement.text(); - if (NgIoUtil.isDartDoc($location) || attrs.lang === 'dart') { + if (NgIoUtil.isDoc($location, 'dart') || attrs.lang === 'dart') { examplePath = NgIoUtil.adjustTsExamplePathForDart(examplePath); } var template = '' + examplePath + ''; diff --git a/public/resources/js/util.js b/public/resources/js/util.js index 2582df3f27..87ddeed291 100644 --- a/public/resources/js/util.js +++ b/public/resources/js/util.js @@ -4,9 +4,9 @@ var NgIoUtil = (function () { function NgIoUtil() { } - NgIoUtil.isDartDoc = function ($location) { + NgIoUtil.isDoc = function ($location, lang) { var loc = $location.absUrl(); - return loc.includes('/docs/dart/'); + return loc.includes('/docs/' + lang + '/'); }; // The following util functions are adapted from _utils-fn.jade. From d26afa90fd9efb24e27e1ee741e2e4ccdb7eaa31 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 26 Jun 2016 06:49:15 -0500 Subject: [PATCH 14/20] docs(toh-6): Move styles from sample.css to heroes.component.css closes #1751 Move additional styles from `sample.css` to `hero-search.component.css`. Edit tutorial to reflect the removal of `sample.css` and the change to `heroes.component.css`. Edit tutorial to reflect the addition of `hero-search.component.css` file. Edit `hero-search.component.ts` to include styles from `hero-search.component.css`. Remove reference to `/public/docs/_examples/toh-6/ts/sample.css` from `/public/docs/_examples/toh-6/ts/index.html`. --- .../hero-search.component.css} | 8 -------- .../toh-6/ts/app/hero-search.component.ts | 1 + .../toh-6/ts/app/heroes.component.css | 8 ++++++++ public/docs/_examples/toh-6/ts/index.html | 1 - public/docs/ts/latest/tutorial/toh-pt6.jade | 20 ++++++++++++------- 5 files changed, 22 insertions(+), 16 deletions(-) rename public/docs/_examples/toh-6/ts/{sample.css => app/hero-search.component.css} (70%) diff --git a/public/docs/_examples/toh-6/ts/sample.css b/public/docs/_examples/toh-6/ts/app/hero-search.component.css similarity index 70% rename from public/docs/_examples/toh-6/ts/sample.css rename to public/docs/_examples/toh-6/ts/app/hero-search.component.css index a5ac5b4d70..741b379356 100644 --- a/public/docs/_examples/toh-6/ts/sample.css +++ b/public/docs/_examples/toh-6/ts/app/hero-search.component.css @@ -1,11 +1,4 @@ /* #docregion */ -.error {color:red;} -button.delete-button{ - float:right; - background-color: gray !important; - color:white; -} - .search-result{ border-bottom: 1px solid gray; border-left: 1px solid gray; @@ -21,4 +14,3 @@ button.delete-button{ width: 200px; height: 20px; } - diff --git a/public/docs/_examples/toh-6/ts/app/hero-search.component.ts b/public/docs/_examples/toh-6/ts/app/hero-search.component.ts index d9a04fce3f..25ada285ac 100644 --- a/public/docs/_examples/toh-6/ts/app/hero-search.component.ts +++ b/public/docs/_examples/toh-6/ts/app/hero-search.component.ts @@ -11,6 +11,7 @@ import { Hero } from './hero'; @Component({ selector: 'hero-search', templateUrl: 'app/hero-search.component.html', + styleUrls: ['app/hero-search.component.css'], providers: [HeroSearchService] }) export class HeroSearchComponent implements OnInit { diff --git a/public/docs/_examples/toh-6/ts/app/heroes.component.css b/public/docs/_examples/toh-6/ts/app/heroes.component.css index 35e45af98d..75969e0b3a 100644 --- a/public/docs/_examples/toh-6/ts/app/heroes.component.css +++ b/public/docs/_examples/toh-6/ts/app/heroes.component.css @@ -1,3 +1,4 @@ +/* #docregion */ .selected { background-color: #CFD8DC !important; color: white; @@ -57,3 +58,10 @@ button { button:hover { background-color: #cfd8dc; } +/* #docregion additions */ +.error {color:red;} +button.delete-button{ + float:right; + background-color: gray !important; + color:white; +} diff --git a/public/docs/_examples/toh-6/ts/index.html b/public/docs/_examples/toh-6/ts/index.html index b84f744a78..8bbbc6123d 100644 --- a/public/docs/_examples/toh-6/ts/index.html +++ b/public/docs/_examples/toh-6/ts/index.html @@ -6,7 +6,6 @@ - diff --git a/public/docs/ts/latest/tutorial/toh-pt6.jade b/public/docs/ts/latest/tutorial/toh-pt6.jade index 4730b7e61f..c93ec199ca 100644 --- a/public/docs/ts/latest/tutorial/toh-pt6.jade +++ b/public/docs/ts/latest/tutorial/toh-pt6.jade @@ -319,7 +319,9 @@ block add-new-hero-via-detail-comp The user can *delete* an existing hero by clicking a delete button next to the hero's name. Add the following to the heroes component HTML right after the hero name in the repeated `
  • ` tag: +makeExcerpt('app/heroes.component.html', 'delete') - +:marked + Add the following to the bottom of the `HeroesComponent` CSS file: ++makeExcerpt('app/heroes.component.css', 'additions') :marked Now let's fix-up the `HeroesComponent` to support the *add* and *delete* actions used in the template. Let's start with *add*. @@ -415,7 +417,9 @@ block observables-section-intro The component template is simple — just a text box and a list of matching search results. +makeExample('app/hero-search.component.html') - +:marked + We'll also want to add styles for the new component. ++makeExample('app/hero-search.component.css') :marked As the user types in the search box, a *keyup* event binding calls the component's `search` method with the new search box value. @@ -559,6 +563,7 @@ block filetree .file hero-detail.component.html .file hero-detail.component.ts .file hero-search.component.html (new) + .file hero-search.component.css (new) .file hero-search.component.ts (new) .file hero-search.service.ts (new) .file rxjs-operators.ts @@ -572,7 +577,6 @@ block filetree .file typings ... .file index.html .file package.json - .file sample.css (new) .file styles.css .file systemjs.config.json .file tsconfig.json @@ -597,30 +601,32 @@ block file-summary `toh-6/ts/app/app.component.ts, toh-6/ts/app/heroes.component.ts, toh-6/ts/app/heroes.component.html, + toh-6/ts/app/heroes.component.css, toh-6/ts/app/hero-detail.component.ts, toh-6/ts/app/hero-detail.component.html, toh-6/ts/app/hero.service.ts, - toh-6/ts/app/in-memory-data.service.ts, - toh-6/ts/sample.css`, + toh-6/ts/app/in-memory-data.service.ts`, null, `app.comp...ts, heroes.comp...ts, heroes.comp...html, + heroes.comp...css, hero-detail.comp...ts, hero-detail.comp...html, hero.service.ts, - in-memory-data.service.ts, - sample.css` + in-memory-data.service.ts` ) +makeTabs( `toh-6/ts/app/hero-search.service.ts, toh-6/ts/app/hero-search.component.ts, toh-6/ts/app/hero-search.component.html, + toh-6/ts/app/hero-search.component.css, toh-6/ts/app/rxjs-operators.ts`, null, `hero-search.service.ts, hero-search.component.ts, hero-search.service.html, + hero-search.component.css, rxjs-operators.ts` ) From 2328b5843b5724ab90145e5986ce2e43a5c7a7d1 Mon Sep 17 00:00:00 2001 From: wajdibr Date: Tue, 26 Jul 2016 18:14:26 +0200 Subject: [PATCH 15/20] docs(contribute): remove the word beta closes #1975 --- public/contribute.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/contribute.jade b/public/contribute.jade index 451269dd40..002c8da4a1 100644 --- a/public/contribute.jade +++ b/public/contribute.jade @@ -5,7 +5,7 @@ .l-sub-section h3 Angular 2 - p Angular 2, now in beta, is a next generation mobile and desktop application development platform. + p Angular 2 is a next generation mobile and desktop application development platform. a(href="https://github.com/angular/angular/blob/master/CONTRIBUTING.md" class="button" md-button) Contribute to Angular 2 From f0272f26f424ecf4d5c73cc0363789ae04ea7466 Mon Sep 17 00:00:00 2001 From: Ciro Nunes Date: Sun, 31 Jul 2016 20:28:48 +0200 Subject: [PATCH 16/20] docs(glossary): fix link to `component` for DI def closes #2009 --- public/docs/ts/latest/glossary.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/docs/ts/latest/glossary.jade b/public/docs/ts/latest/glossary.jade index 2f8b11fced..50c6100cda 100644 --- a/public/docs/ts/latest/glossary.jade +++ b/public/docs/ts/latest/glossary.jade @@ -257,7 +257,7 @@ include _util-fns the value associated with the token for the `Foo` class, typically an instance of `Foo` itself. Angular makes similar requests internally during many of its operations - as when it creates a [`Component`](#AppComponent) for display. + as when it creates a [`Component`](#component) for display. The `Injector` maintains an internal map of tokens to dependency values. If the `Injector` can't find a value for a given token, it creates From 14ad2a8c685f4cf565866d95c4bc1f05cbaf3c11 Mon Sep 17 00:00:00 2001 From: Brandon Roberts Date: Sun, 31 Jul 2016 19:57:47 -0500 Subject: [PATCH 17/20] fix(docs): Renamed files for JavaScript/Dart dynamic form cookbook closes #2010 --- ...ynamic-form-deprecated.html => dynamic-form-deprecated.jade} | 0 public/docs/js/latest/cookbook/_data.json | 2 +- ...ynamic-form-deprecated.html => dynamic-form-deprecated.jade} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename public/docs/dart/latest/cookbook/{dynamic-form-deprecated.html => dynamic-form-deprecated.jade} (100%) rename public/docs/js/latest/cookbook/{dynamic-form-deprecated.html => dynamic-form-deprecated.jade} (100%) diff --git a/public/docs/dart/latest/cookbook/dynamic-form-deprecated.html b/public/docs/dart/latest/cookbook/dynamic-form-deprecated.jade similarity index 100% rename from public/docs/dart/latest/cookbook/dynamic-form-deprecated.html rename to public/docs/dart/latest/cookbook/dynamic-form-deprecated.jade diff --git a/public/docs/js/latest/cookbook/_data.json b/public/docs/js/latest/cookbook/_data.json index 7b847da507..d95e3a6d68 100644 --- a/public/docs/js/latest/cookbook/_data.json +++ b/public/docs/js/latest/cookbook/_data.json @@ -27,7 +27,7 @@ }, "dynamic-form": { - "title": "Dynamic Form", + "title": "Dynamic Forms", "intro": "Render dynamic forms with NgFormModel" }, diff --git a/public/docs/js/latest/cookbook/dynamic-form-deprecated.html b/public/docs/js/latest/cookbook/dynamic-form-deprecated.jade similarity index 100% rename from public/docs/js/latest/cookbook/dynamic-form-deprecated.html rename to public/docs/js/latest/cookbook/dynamic-form-deprecated.jade From 28174673fec2f5bdf491078faa8e78b866b8d384 Mon Sep 17 00:00:00 2001 From: Matt Ezell Date: Tue, 2 Aug 2016 07:39:11 -0500 Subject: [PATCH 18/20] docs(router): formatting - Back Quote to Wrap Identifier closes #2020 --- public/docs/ts/latest/guide/router.jade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/docs/ts/latest/guide/router.jade b/public/docs/ts/latest/guide/router.jade index e51f04f4dc..1ae824f6bd 100644 --- a/public/docs/ts/latest/guide/router.jade +++ b/public/docs/ts/latest/guide/router.jade @@ -166,8 +166,8 @@ code-example(format="", language="html"). the `RouterLink` if we so desired. :marked ### Router State - After the end of each successful navigation lifecycle, the router builds a tree of `ActivatedRoute`s, - which make up the current state of the router. We can access the current `RouterState` from anywhere in our + After the end of each successful navigation lifecycle, the router builds a tree of `ActivatedRoute` objects + that make up the current state of the router. We can access the current `RouterState` from anywhere in our application using the `Router` service and the `routerState` property. The router state provides us with methods to traverse up and down the route tree from any activated route From 22a370494713d50b6ee21a0f33c6405da492c0b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesu=CC=81s=20Rodri=CC=81guez?= Date: Thu, 4 Aug 2016 16:58:58 +0200 Subject: [PATCH 19/20] chore: update next-item for hidden closes #2032 --- public/_includes/_next-item.jade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/_includes/_next-item.jade b/public/_includes/_next-item.jade index c4626a453f..55ab4b448f 100644 --- a/public/_includes/_next-item.jade +++ b/public/_includes/_next-item.jade @@ -6,7 +6,7 @@ for page, slug in data // CHECK IF CURRENT PAGE IS SET, THEN SET NEXT PAGE if currentPage - if !nextPage && page.nextable + if !nextPage && page.nextable && !page.hide .l-sub-section h3 Next Step a(href="/docs/#{current.path[1]}/#{current.path[2]}/#{current.path[3]}/#{slug}.html") #{page.title} @@ -16,4 +16,4 @@ for page, slug in data // SET CURRENT PAGE FLAG WHEN YOU PASS IT if current.path[4] == slug - - var currentPage = true \ No newline at end of file + - var currentPage = true From 1a8bbea1d18884d5b80751b7c169db51a54a4354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesu=CC=81s=20Rodri=CC=81guez?= Date: Fri, 29 Jul 2016 13:08:39 +0200 Subject: [PATCH 20/20] docs(pipes): add a section about the Intl API closes #1999 --- public/docs/ts/latest/guide/pipes.jade | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/public/docs/ts/latest/guide/pipes.jade b/public/docs/ts/latest/guide/pipes.jade index 744674ac3c..3d50ef7f42 100644 --- a/public/docs/ts/latest/guide/pipes.jade +++ b/public/docs/ts/latest/guide/pipes.jade @@ -39,6 +39,14 @@ block includes [pipe operator](./template-syntax.html#pipe) ( | ) to the [Date pipe](../api/common/index/DatePipe-class.html) function on the right. All pipes work this way. +.l-sub-section + :marked + The `Date` and `Currency` pipes need the **ECMAScript Internationalization API**. + Safari and other older browsers don't support it. We can add support with a polyfill. + + code-example(language="html"). + <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en"></script> + .l-main-section :marked ## Built-in pipes @@ -48,7 +56,7 @@ block includes .l-sub-section :marked - Learn more about these and many other built-in pipes in the the [API Reference](../api/#!?apiFilter=pipe); + Learn more about these and many other built-in pipes in the [API Reference](../api/#!?apiFilter=pipe); filter for entries that include the word "pipe". Angular 2 doesn't have a `FilterPipe` or an `OrderByPipe` for reasons explained in an [appendix below](#no-filter-pipe).