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() { diff --git a/public/_includes/_next-item.jade b/public/_includes/_next-item.jade index 7c0f2a9cae..e8736722e6 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 下一步 a.translated-cn(href="/docs/#{current.path[1]}/#{current.path[2]}/#{current.path[3]}/#{slug}.html") #{page.title} diff --git a/public/contribute.jade b/public/contribute.jade index 2aa6ddca6c..ce4a9d5caa 100644 --- a/public/contribute.jade +++ b/public/contribute.jade @@ -7,8 +7,9 @@ .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, 目前正在beta阶段,是下一代移动和桌面应用开发平台。 + p Angular 2 is a next generation mobile and desktop application development platform. + + p Angular 2是下一代移动与桌面应用开发平台。 a(href="https://github.com/angular/angular/blob/master/CONTRIBUTING.md" class="button" md-button) Contribute to Angular 2 a(href="https://github.com/angular/angular/blob/master/CONTRIBUTING.md" class="button" md-button) 为Angular 2做贡献 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 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/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: 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.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/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/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 9ef06ca47c..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,29 +11,29 @@ 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 { // #docregion search heroes: Observable; // #enddocregion search - // #docregion searchSubject - searchSubject = new Subject(); - // #enddocregion searchSubject + // #docregion searchTerms + private 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 +41,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/_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/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": { 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/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 eff9a7e77e..c97d5f8043 100644 --- a/public/docs/dart/latest/guide/_data.json +++ b/public/docs/dart/latest/guide/_data.json @@ -36,6 +36,13 @@ "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.", + "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 +70,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 +91,6 @@ "basics": true }, - "security": { - "title": "Security", - "intro": "Prevent security vulnerabilities" - }, - "hierarchical-dependency-injection": { "title": "Hierarchical Dependency Injectors", "navTitle": "Hierarchical Injectors", @@ -112,14 +119,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 +161,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.jade b/public/docs/dart/latest/guide/forms-deprecated.jade new file mode 100644 index 0000000000..f5711f49ee --- /dev/null +++ b/public/docs/dart/latest/guide/forms-deprecated.jade @@ -0,0 +1,4 @@ +include ../_util-fns + +:marked + 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 f8df2a84a6..d76267fce1 100644 --- a/public/docs/dart/latest/guide/router-deprecated.jade +++ b/public/docs/dart/latest/guide/router-deprecated.jade @@ -1 +1,4 @@ -!= partial("../../../_includes/_ts-temp") \ No newline at end of file +include ../_util-fns + +:marked + This page has no Dart equivalent. Instead, see the [router guide](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 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/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.html deleted file mode 100644 index f8df2a84a6..0000000000 --- a/public/docs/js/latest/cookbook/dynamic-form-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.html b/public/docs/js/latest/cookbook/dynamic-form-deprecated.jade similarity index 100% rename from public/docs/dart/latest/guide/forms-deprecated.html rename to public/docs/js/latest/cookbook/dynamic-form-deprecated.jade diff --git a/public/docs/js/latest/cookbook/ts-to-js.jade b/public/docs/js/latest/cookbook/ts-to-js.jade index e7af4222b0..554ae7e328 100644 --- a/public/docs/js/latest/cookbook/ts-to-js.jade +++ b/public/docs/js/latest/cookbook/ts-to-js.jade @@ -45,10 +45,10 @@ include ../../../../_includes/_util-fns [`Host`(宿主)与`Query`(查询)元数据](#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.** - **运行并比较本烹饪宝典里的在线[TypeScript](/resources/live-examples/cb-ts-to-js/ts/plnkr.html)和[JavaScript](/resources/live-examples/cb-ts-to-js/js/plnkr.html)代码** + **运行并比较本烹饪宝典里的在线TypeScriptJavaScript代码** 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/_data.json b/public/docs/ts/latest/cookbook/_data.json index 3dca78d6ed..3dd63484d5 100644 --- a/public/docs/ts/latest/cookbook/_data.json +++ b/public/docs/ts/latest/cookbook/_data.json @@ -26,14 +26,9 @@ "intro": "依赖注入技术" }, "dynamic-form": { - "title": "动态表单", - "intro": "通过FormGroup渲染动态表单", - "basics": true - }, - "dynamic-form-deprecated": { - "title": "动态表单(已废弃)", - "intro": "通过NgFormModel渲染动态表单", - "hide": true + "title": "Dynamic Forms", + "intro": "Render dynamic forms with FormGroup", + "basics": true, }, "set-document-title": { 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 5a0711b72f..36456deee5 100644 --- a/public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade +++ b/public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade @@ -9,7 +9,7 @@ a(id="top") 本章提供了一个快速的参考指南,指出一些常用的Angular 1语法及其在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 **. **可到[在线范例](/resources/live-examples/cb-a1-a2-quick-reference/ts/plnkr.html)中查看Angular 2语法**。 diff --git a/public/docs/ts/latest/cookbook/component-communication.jade b/public/docs/ts/latest/cookbook/component-communication.jade index 10a276c2fd..2ee79bd8da 100644 --- a/public/docs/ts/latest/cookbook/component-communication.jade +++ b/public/docs/ts/latest/cookbook/component-communication.jade @@ -48,9 +48,9 @@ include ../_util-fns [父组件和子组件通过服务来通讯](#bidirectional-service) :marked - **See the [live example](/resources/live-examples/cb-component-communication/ts/plnkr.html)**. + **See the **. - **参见[在线例子](/resources/live-examples/cb-component-communication/ts/plnkr.html)** + **参见**。 .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 c19ecc036c..2f76fc7666 100644 --- a/public/docs/ts/latest/cookbook/component-relative-paths.jade +++ b/public/docs/ts/latest/cookbook/component-relative-paths.jade @@ -118,14 +118,14 @@ include ../_util-fns .l-main-section :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. - **参见[在线范例](/resources/live-examples/cb-component-relative-paths/ts/plnkr.html)**,并从中下载源码或只在这里阅读相关源码。 + **参见**,并从中下载源码或只在这里阅读相关源码。 +makeTabs( `cb-component-relative-paths/ts/app/some.component.ts, diff --git a/public/docs/ts/latest/cookbook/dependency-injection.jade b/public/docs/ts/latest/cookbook/dependency-injection.jade index 604519f7c6..4efb897d81 100644 --- a/public/docs/ts/latest/cookbook/dependency-injection.jade +++ b/public/docs/ts/latest/cookbook/dependency-injection.jade @@ -113,7 +113,7 @@ include ../_util-fns [使用类的前向引用(*forwardRef*)打破循环依赖](#forwardref) :marked - **See the [live example](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)** + **See the ** of the code supporting this cookbook. 要获取本“烹饪宝典”的代码,**参见[在线例子](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)**。 @@ -419,13 +419,13 @@ figure.image-display The `ngOnInit` pass that `id` to the service which fetches and caches the hero. The getter for the `hero` property pulls the cached hero from the service. And the template displays this data-bound property. - + 父组件`HeroBiosComponent`把一个值绑定到`heroId`。`ngOnInit`把该`id`传递到服务,然后服务获取和缓存英雄。`hero`属性的getter从服务里面获取缓存的英雄,并在模板里显示它绑定到属性值。 - 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. - 到[在线代码](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)找到这个例子,确认三个`HeroBioComponent`实例拥有自己独立的英雄数据缓存。 + 到在线例子中找到这个例子,确认三个`HeroBioComponent`实例拥有自己独立的英雄数据缓存。 figure.image-display img(src="/resources/images/cookbooks/dependency-injection/hero-bios.png" alt="Bios") @@ -924,7 +924,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. 该函数从`HeroService`获取英雄参赛者,从中取`2`个作为亚军,并把他们的名字拼接起来。请到[在线例子](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)查看全部原代码。 @@ -1197,7 +1197,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. 安全起见,我们添加了[@Optional](#optional)装饰器,但是[在线例子](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)显示`alex`参数确实被设置了。 @@ -1253,7 +1253,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 3e6c56021a..289a9bc7e1 100644 --- a/public/docs/ts/latest/cookbook/dynamic-form.jade +++ b/public/docs/ts/latest/cookbook/dynamic-form.jade @@ -60,9 +60,9 @@ include ../_util-fns [动态模板](#dynamic-template) :marked - **See the [live example](/resources/live-examples/cb-dynamic-form/ts/plnkr.html)**. + **See the **. - **参见[在线例子](/resources/live-examples/cb-dynamic-form/ts/plnkr.html)**. + **参见**。 .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 e71d6739a7..ce892018ef 100644 --- a/public/docs/ts/latest/cookbook/set-document-title.jade +++ b/public/docs/ts/latest/cookbook/set-document-title.jade @@ -7,9 +7,9 @@ a(id='top') 应用程序应该能让浏览器标题栏显示我们想让它显示的内容。本*烹饪宝典*解释怎么做。 :marked - **See the [live example](/resources/live-examples/cb-set-document-title/ts/plnkr.html)**. + **See the **. - **参见[在线例子](/resources/live-examples/cb-set-document-title/ts/plnkr.html)**. + **参见**。 .l-sub-section img(src='/resources/images/devguide/plunker-separate-window-button.png' alt="pop out the window" align="right" style="margin-right:-20px") diff --git a/public/docs/ts/latest/glossary.jade b/public/docs/ts/latest/glossary.jade index abeaff0c39..68b3495cc3 100644 --- a/public/docs/ts/latest/glossary.jade +++ b/public/docs/ts/latest/glossary.jade @@ -369,10 +369,10 @@ include _util-fns Angular提供并使用自己精心设计的[依赖注入(Dependency Injection)](dependency-injection.html)系统来组装和运行应用程序:在要用时,将一些部件“注入”到另一些部件里面。 - 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. - 依赖注入的核心是一个[注入器(Injector)](#injector),这个注入器根据需要返回被依赖部件。`injector.get(token)`方法返回与该token(令牌)参数相关的依赖部件。 + 在Angular内核中有一个[注入器(Injector)](#injector),这个注入器根据需要返回被依赖部件。`injector.get(token)`方法返回与该token(令牌)参数相关的依赖部件。 A token is an Angular type (`OpaqueToken`). We rarely deal with tokens directly; most methods accept a class name (`Foo`) or a string ("foo") and Angular converts it @@ -383,7 +383,7 @@ include _util-fns 当调用`injector.get(Foo)`时,注入器返回用`Foo`类生成的令牌所对应的依赖值,该依赖值通常是`Foo`类的实例。 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. Angular在创建[组件(Component)](#AppComponent)以供显示的过程中,会在内部执行很多类似的依赖注入请求。 diff --git a/public/docs/ts/latest/guide/animations.jade b/public/docs/ts/latest/guide/animations.jade index f73fa03074..b0d570b16b 100644 --- a/public/docs/ts/latest/guide/animations.jade +++ b/public/docs/ts/latest/guide/animations.jade @@ -77,7 +77,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 . 本章中引用的这个例子可以到[在线例子](/resources/live-examples/animations/ts/plnkr.html)去体验。 diff --git a/public/docs/ts/latest/guide/architecture.jade b/public/docs/ts/latest/guide/architecture.jade index 12496e2730..fcce30b7b7 100644 --- a/public/docs/ts/latest/guide/architecture.jade +++ b/public/docs/ts/latest/guide/architecture.jade @@ -208,7 +208,8 @@ block angular-library-modules
- 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}. 还有另一些重要的Angular模块库,比如`@angular/common`、`@angular/router` 和 `@angular/http`。我们从一个Angular的!{_library_module}导入我们需要的模块。 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 f361c6ffdb..1449804d71 100644 --- a/public/docs/ts/latest/guide/forms.jade +++ b/public/docs/ts/latest/guide/forms.jade @@ -65,10 +65,10 @@ include ../_util-fns - sharing information among controls with template reference variables - 通过模板引用变量,在控件之间共享信息 - - [Live Example](/resources/live-examples/forms/ts/plnkr.html) - - [在线例子](/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 505bab64d4..fe94782676 100644 --- a/public/docs/ts/latest/guide/index.jade +++ b/public/docs/ts/latest/guide/index.jade @@ -188,7 +188,7 @@ table.vertical-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. 在每页靠近顶部的地方都可以看到一个链接,指向这个范例的可执行版本,比如[架构](architecture.html)一章中的[在线例子](/resources/live-examples/architecture/ts/plnkr.html)。 diff --git a/public/docs/ts/latest/guide/pipes.jade b/public/docs/ts/latest/guide/pipes.jade index a71864f8dd..67164c9fdf 100644 --- a/public/docs/ts/latest/guide/pipes.jade +++ b/public/docs/ts/latest/guide/pipes.jade @@ -61,6 +61,16 @@ block includes 在这个插值表达式中,我们让组件的`birthday`值通过[管道操作符](./template-syntax.html#pipe)( | )流动到 右侧的[Date管道](../api/common/index/DatePipe-class.html)函数中。所有管道都会用这种方式工作。 +.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. + + `Date`和`Currency`管道需要**ECMAScript国际化(I18n)API**,但Safari和其它老式浏览器不支持它,该问题可以用垫片(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 @@ -74,7 +84,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". 要学习更多内建管道的知识,参见[API参考手册](../api/#!?apiFilter=pipe),并用“pipe”为关键词对结果进行过滤。 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 5e0c612d1d..ceb84cc152 100644 --- a/public/docs/ts/latest/guide/router.jade +++ b/public/docs/ts/latest/guide/router.jade @@ -15,9 +15,9 @@ include ../_util-fns 在用户使用应用程序时,Angular的***组件路由器***能让用户从一个[视图](./glossary.html#view)导航到另一个视图。 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. - 本章覆盖了该路由器的主要特性。我们通过一个小型应用的成长演进来讲解它。参见[在线例子](/resources/live-examples/router/ts/plnkr.html)。 + 本章覆盖了该路由器的主要特性。我们通过一个小型应用的成长演进来讲解它。参见在线例子。 .l-sub-section @@ -339,9 +339,6 @@ code-example(format="", language="html"). :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 application using the `Router` service and the `routerState` property. @@ -530,13 +527,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). - - 完整代码可以在[在线例子](/resources/live-examples/router/ts/plnkr.html)中找到。 - :marked Our client is the Hero Employment Agency. Heroes need work and The Agency finds Crises for them to solve. @@ -554,8 +545,6 @@ table 1. A *Heroes* area where we maintain the list of heroes employed by The Agency. - 1. 一个*英雄*区,用来维护该中心雇佣英雄的列表。 - Run the [live example](/resources/live-examples/router/ts/plnkr.html). It opens in the *Crisis Center*. We'll come back to that. @@ -2753,7 +2742,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. @@ -2912,7 +2901,7 @@ figure.image-display ## 总结 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. 本章中涉及到了很多背景知识,而且本应用程序也太大了,所以没法在这里显示。请访问[在线例子](/resources/live-examples/router/ts/plnkr.html),在那里你可以下载最终的源码。 diff --git a/public/docs/ts/latest/guide/user-input.jade b/public/docs/ts/latest/guide/user-input.jade index abe7211679..0d51df1e5d 100644 --- a/public/docs/ts/latest/guide/user-input.jade +++ b/public/docs/ts/latest/guide/user-input.jade @@ -9,9 +9,9 @@ include ../_util-fns 当用户点击链接、按下按钮或者输入文字时,我们得知道发生了什么。这些用户动作都会产生DOM事件。 本章中,我们将学习如何使用Angular事件绑定语法来绑定这些事件。 - [Run the live example](/resources/live-examples/user-input/ts/plnkr.html) + Run the live example - [运行在线例子](/resources/live-examples/user-input/ts/plnkr.html) + 运行在线例子 :marked ## Binding to user input events diff --git a/public/docs/ts/latest/tutorial/toh-pt6.jade b/public/docs/ts/latest/tutorial/toh-pt6.jade index a865cb315e..873c0c4148 100644 --- a/public/docs/ts/latest/tutorial/toh-pt6.jade +++ b/public/docs/ts/latest/tutorial/toh-pt6.jade @@ -179,7 +179,7 @@ block dont-be-distracted-by-backend-subst 来看看我们目前的`HeroService`的实现 -+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. @@ -219,7 +219,7 @@ block get-heroes-details *现在*,我们先利用`toPromise`操作符把`Observable`直接转换成`Promise`对象,回到已经熟悉的地盘。 - +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. @@ -236,7 +236,7 @@ block get-heroes-details 如果我们希望得到那些能力,就得自己添加那些操作符。 那很容易,只要从RxJS库中导入它们就可以了,就像这样: - +makeExample('toh-6/ts/app/hero.service.ts', 'rxjs')(format=".") + +makeExcerpt('app/hero.service.ts', 'rxjs', '') :marked ### Extracting the data in the *then* callback @@ -248,7 +248,7 @@ block get-heroes-details 在*promise*的`then`回调中,我们调用http的`Reponse`对象的`json`方法,以提取出其中的数据。 - +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. @@ -292,7 +292,7 @@ block get-heroes-details 在`getHeroes()`的最后,我们`catch`了服务器的失败信息,并把它们传给了错误处理器: -+makeExcerpt('app/hero.service.ts', 'catch') ++makeExcerpt('app/hero.service.ts', 'catch', '') :marked This is a critical step! @@ -301,7 +301,8 @@ block get-heroes-details 这是一个关键的步骤! 我们必须预料到http请求会失败,因为有太多我们无法控制的原因可能导致它们频繁出现各种错误。 -+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. @@ -357,9 +358,9 @@ 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. - Put用来编辑一个指定的英雄,但是代码结构和POST请求很相似。唯一的不同是,我们要修改url,为它附加上我们想要编辑的那位英雄的id。 + Put用来编辑一个指定的英雄,但是代码结构和POST请求很相似。唯一的不同是,我们要修改URL,为它附加上我们想要编辑的那位英雄的id。 +makeExcerpt('app/hero.service.ts', 'put') @@ -437,7 +438,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. 为了区分添加和编辑操作,我们增加了一步检查,看看url中是否传入了id。如果没有id,我们就把`HeroDetailComponent`绑定到一个空的`Hero`对象。 无论是哪种情况,通过UI进行的任何编辑操作都会被绑定回同一个`hero`属性。 @@ -527,7 +528,13 @@ block add-new-hero-via-detail-comp 用户可以通过点击英雄名后面的删除按钮来*删除*一个现存的英雄。 往`heroes.component.html`中往`
  • `标签中名字的紧后面添加下列HTML代码: -+makeExample('app/heroes.component.html', 'delete') ++makeExcerpt('app/heroes.component.html', 'delete') +:marked + Add the following to the bottom of the `HeroesComponent` CSS file: + + 把下列代码添加到`HeroesComponent`的CSS文件底部: + ++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. @@ -599,14 +606,16 @@ block review 下面是这些劳动成果的操作演示: 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 - ## Observables + ## !{_Observable}s ## 可观察对象(Observable) +block observables-section-intro + :marked Each `Http` method returns an `Observable` of HTTP `Response` objects. 每个`Http`方法都返回一个Http `Response`对象的`Observable`实例。 @@ -646,117 +655,137 @@ block observables-section 转换成承诺通常是更好地选择,我们通常要求`http`获取单块数据。只要接收到数据,就算完成。 使用承诺这种形式的结果是让调用方更容易写,并且承诺已经在JavaScript程序员中被广泛接受了。 - - 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. - - 但是请求并非总是“一次性”的。我们可以开始一个请求,并且取消它,再开始另一个不同的请求 —— 在服务器对第一个请求作出回应之前。 - 像这样一个_请求-取消-新请求_的序列用*承诺*是很难实现的,但接下来我们会看到,它对于*可观察对象*却很简单。 - - ### 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. - - 我们要为《英雄指南》添加一个*英雄搜索*特性。 - 当用户在搜索框中输入一个名字时,我们将不断发起http请求,以获得按名字过滤的英雄。 - - We start by creating `HeroSearchService` that sends search queries to our server's web api. - - 我们先创建`HeroSearchService`服务,它会把搜索请求发送到我们服务器上的Web API。 - - +makeExample('toh-6/ts/app/hero-search.service.ts', null, 'app/hero-search.service.ts')(format=".") - - :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. - - `HeroSearchService`中的`http.get`调用和`HeroService`中的很相似。 - 显著的不同是:我们不再调用`toPromise`,而是直接返回*可观察对象*。 - - ### HeroSearchComponent - - ### HeroSearchComponent - - Let's create a new `HeroSearchComponent` that calls this new `HeroSearchService`. - - 我们再创建一个新的`HeroSearchComponent`来调用这个新的`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. - - 当用户在搜索框中输入时,一个*keyup*事件绑定会调用该组件的`search`方法,并传入新的搜索框的值。 - - The `*ngFor` repeats *hero* objects from the component's `heroes` property. No surprise there. - - `*ngFor`为该组件的`heroes`属性重复*hero*对象。这也没啥特别的。 - - 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`. - - 但是,接下来我们看到`heroes`属性返回了一个英雄们的`Observable`对象,不是英雄们的数组。 - `*ngFor`不能利用可观察对象做任何事,除非我们在它后面跟一个`AsyncPipe`(`heroes | async`)。 - `AsyncPipe`会订阅到这个可观察对象,并且为`*ngFor`生产一个英雄们的数组。 - - Time to create the `HeroSearchComponent` class and metadata. - - 该创建`HeroSearchComponent`类及其元数据了。 - - +makeExample('toh-6/ts/app/hero-search.component.ts', null,'hero-search.component.ts') +: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. + + 我们要为《英雄指南》添加一个*英雄搜索*特性。 + 当用户在搜索框中输入一个名字时,我们将不断发起http请求,以获得按名字过滤的英雄。 + + We start by creating `HeroSearchService` that sends search queries to our server's web api. + + 我们先创建`HeroSearchService`服务,它会把搜索请求发送到我们服务器上的Web API。 + ++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. + + `HeroSearchService`中的`http.get()`调用和`HeroService`中的很相似,只是这次带了查询字符串。 + 显著的不同是:我们不再调用`toPromise`,而是直接返回*可观察对象*。 + + ### HeroSearchComponent + + ### HeroSearchComponent + + Let's create a new `HeroSearchComponent` that calls this new `HeroSearchService`. + + 我们再创建一个新的`HeroSearchComponent`来调用这个新的`HeroSearchService`。 + + 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. + + 当用户在搜索框中输入时,一个*keyup*事件绑定会调用该组件的`search`方法,并传入新的搜索框的值。 + + The `*ngFor` repeats *hero* objects from the component's `heroes` property. No surprise there. + + `*ngFor`为该组件的`heroes`属性重复*hero*对象。这也没啥特别的。 + + 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`. + + 但是,接下来我们看到`heroes`属性现在是英雄列表的`Observable`对象,而不再只是英雄数组。 + `*ngFor`不能利用可观察对象做任何事,除非我们在它后面跟一个`async` pipe (`AsyncPipe`)。 + 这个`async`管道会订阅到这个可观察对象,并且为`*ngFor`生成一个英雄数组。 + + Time to create the `HeroSearchComponent` class and metadata. + + 该创建`HeroSearchComponent`类及其元数据了。 + ++makeExample('app/hero-search.component.ts') + +:marked + #### Search terms + + #### 搜索词 + + Let's focus on the `!{_priv}searchTerms`: + + 仔细看下这个`searchTerms`: + ++makeExcerpt('app/hero-search.component.ts', 'searchTerms', '') + +block search-criteria-intro :marked - Focus on the `searchSubject`. - - 仔细看`searchSubject`。 - - +makeExample('toh-6/ts/app/hero-search.component.ts', 'searchSubject')(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. + A `Subject` is a producer of an _observable_ event stream; + `searchTerms` produces an `Observable` of strings, the filter criteria for the name search. `Subject`(主体)是一个_可观察的_事件流中的生产者。 - 这里的`searchSubject`生产一些字符串的`Observable`,用于作为按名搜索时的过滤条件。 - + `searchTerms`生成一些字符串的`Observable`,用于作为按名搜索时的过滤条件。 + Each call to `search` puts a new string into this subject's _observable_ stream by calling `next`. - 每次到`search`的调用都会调用`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. + 每当调用`search`时都会调用`next`来把新的字符串放进该主体的_可观察_流中。 - `Subject`也是一个`Observable`对象。 - 我们将访问`Observable`并且把字符串数组组成的流转换成`Hero[]`数组组成的流,也就是`heroes`属性。 +:marked + + #### Initialize the _**heroes**_ property (_**ngOnInit**_) + + #### 初始化_**heroes**_属性(_**ngOnInit**_) + + 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. + + `Subject`也是一个`Observable`对象。 + 我们要把字符串数组的流转换成`Hero`数组的流,并把结果赋值给`heroes`属性。 - +makeExample('toh-6/ts/app/hero-search.component.ts', 'search')(format=".") ++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. + + 如果我们直接把每一次用户按键都直接传给`HeroSearchService`,就会发起一场HTTP请求风暴。 + 这可不好玩。我们不希望占用服务器资源,也不想耗尽网络带宽。 + +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. - - 如果我们直接把每一次用户按键都直接传给`HeroSearchService`,就会发起一场Http请求风暴。 - 这可不好玩。我们不希望占用服务器资源,也不想耗尽网络带宽。 - - 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: 幸运的是,我们可以在字符串的`Observable`后面串联一个`Observable`操作符,来归并这些请求。 我们将对`HeroSearchService`发起更少的调用,并且仍然获得足够及时的响应。做法如下: - * The `asObservable` operator casts the `Subject` as an `Observable` of filter strings. - - * `asObservable`操作符把`Subject`转换成过滤字符串组成的`Observable`。 - * `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. @@ -840,42 +869,42 @@ block observables-section 在这个例子中,我们使用一些不同的方法。 我们把整个应用中要用的那些RxJS `Observable`扩展组合在一起,放在一个单独的RxJS导入文件中。 - +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`. 我们在`AppComponent`中导入`rxjs-extensions`就可以一次性加载它们。 - +makeExample('toh-6/ts/app/app.component.ts', 'rxjs-extensions', 'app/app.component.ts')(format=".") + +makeExcerpt('app/app.component.ts', 'rxjs-extensions') - :marked - ### Adding the search component to the dashboard - - ### 为仪表盘添加搜索组件 +:marked + ### Add the search component to the dashboard + + ### 为仪表盘添加搜索组件 - We add the `HeroSearchComponent` to the bottom of the `DashboardComponent` template. - - 将`HeroSearchComponent`添加到`DashboardComponent`的模版的最后面。 + We add the hero search HTML element to the bottom of the `DashboardComponent` template. + + 将表示“英雄搜索”组件的HTML元素添加到`DashboardComponent`模版的最后面。 - +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. - - 最后,导入`HeroSearchComponent`并将其添加到`directives`数组中。 +:marked + And finally, we import the `HeroSearchComponent` and add it to the `directives` !{_array}. + + 最后,导入`HeroSearchComponent`并将其添加到`directives`数组中。 - +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. - - 再次运行该应用,跳转到*Dashboard*,并在英雄下方的搜索框里输入一些文本。 - 看起来就像这样: +: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. + + 再次运行该应用,跳转到*Dashboard*,并在英雄下方的搜索框里输入一些文本。 + 看起来就像这样: - 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 @@ -905,9 +934,10 @@ 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.css (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 @@ -919,7 +949,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 @@ -935,17 +964,17 @@ block filetree 旅程即将结束,不过我们已经收获颇丰。 - - We added the necessary dependencies to use Http in our application. + - We added the necessary dependencies to use HTTP in our application. - - 我们添加了在应用程序中使用Http的必备依赖。 + - 我们添加了在应用程序中使用HTTP的必备依赖。 - - We refactored HeroService to load heroes from an API. + - We refactored `HeroService` to load heroes from a web API. - - 我们重构了HeroService,以通过api来加载英雄数据。 + - 我们重构了`HeroService`,以通过web API来加载英雄数据。 - - We extended HeroService to support post, put and delete calls. + - We extended `HeroService` to support post, put and delete methods. - - 我们扩展了HeroService来支持post、put和delete调用。 + - 我们扩展了`HeroService`来支持post、put和delete方法。 - We updated our components to allow adding, editing and deleting of heroes. @@ -955,44 +984,45 @@ block filetree - 我们配置了一个内存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( `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` -) + ) 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 b0dabaf97a..2a8ab26932 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. 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');