From fb9edf972efc063a7449e5596a63ae6e64af583f Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Tue, 5 Jul 2016 16:46:44 -0700 Subject: [PATCH 01/25] chore: fix "Invalid example" warnings from shred map builder closes #1832 The shred map (xref) builder was issuing warnings. This fix includes - Adjustments to the shredder map builder itself so that it understands, e.g., app-project relative example paths. - `**/guide/glossary.jade` now (Jade) `includes` the shared parent `glossary.jade` rather than (Harp) importing (via `partial`). This fixes `makeExample` path issues in the glossary. - Adjusted some `makeExample` paths that were ok for site build, but confused the xref tool. --- .../latest/guide/dependency-injection.jade | 2 +- public/docs/dart/latest/guide/glossary.jade | 2 +- public/docs/dart/latest/tutorial/toh-pt5.jade | 3 - public/docs/ts/latest/glossary.jade | 12 ++-- public/docs/ts/latest/guide/glossary.jade | 2 +- .../processors/shredMapProcessor.js | 61 +++++++++++++------ 6 files changed, 51 insertions(+), 31 deletions(-) diff --git a/public/docs/dart/latest/guide/dependency-injection.jade b/public/docs/dart/latest/guide/dependency-injection.jade index ad695a9732..7236d24c7d 100644 --- a/public/docs/dart/latest/guide/dependency-injection.jade +++ b/public/docs/dart/latest/guide/dependency-injection.jade @@ -101,7 +101,7 @@ block dart-map-alternative As an alternative to using a configuration `Map`, we can define a custom configuration class: - +makeExample('dependency-injection/ts/app/app.config.ts','config-alt','app/app-config.ts (alternative config)')(format='.') + +makeExample('lib/app_config.dart (alternative config)','config-alt') :marked Defining a configuration class has a few benefits. One key benefit diff --git a/public/docs/dart/latest/guide/glossary.jade b/public/docs/dart/latest/guide/glossary.jade index a66284569e..ca1429104e 100644 --- a/public/docs/dart/latest/guide/glossary.jade +++ b/public/docs/dart/latest/guide/glossary.jade @@ -1 +1 @@ -!= partial("../glossary") +include ../glossary diff --git a/public/docs/dart/latest/tutorial/toh-pt5.jade b/public/docs/dart/latest/tutorial/toh-pt5.jade index 1c0ab90de8..c2923c1a05 100644 --- a/public/docs/dart/latest/tutorial/toh-pt5.jade +++ b/public/docs/dart/latest/tutorial/toh-pt5.jade @@ -132,9 +132,6 @@ code-example(language="bash"). ### Add a base tag -// Our Tour of Heroes needs routing, -// so we load the library in the `index.html` in a script tag immediately *after* the angular script itself. -//+makeExample('toh-5/dart/web/index.html', 'router', 'index.html (router)')(format=".") :marked First, edit `index.html` and add `` at the top of the `` section. +makeExample('toh-5/dart/web/index.html', 'base-href', 'index.html (base href)')(format=".") diff --git a/public/docs/ts/latest/glossary.jade b/public/docs/ts/latest/glossary.jade index e386d0e2cf..f4eb1ee117 100644 --- a/public/docs/ts/latest/glossary.jade +++ b/public/docs/ts/latest/glossary.jade @@ -54,7 +54,7 @@ include _util-fns The barrel itself is a module file that re-exports *selected* exports of other modules. Imagine three modules in a `heroes` folder: - code-example(format=''). + code-example. // heroes/hero.component.ts export class HeroComponent {} @@ -65,26 +65,26 @@ include _util-fns export class HeroService {} :marked Without a barrel, a consumer would need three import statements: - code-example(format=''). + code-example. import { HeroComponent } from '../heroes/hero.component.ts'; import { Hero } from '../heroes/hero.model.ts'; import { HeroService } from '../heroes/hero.service.ts'; :marked We can add a barrel to the `heroes` folder (called `index` by convention) that exports all of these items: - code-example(format=''). + code-example. export * from './hero.model.ts'; // re-export all of its exports export * from './hero.service.ts'; // re-export all of its exports export { HeroComponent } from './hero.component.ts'; // re-export the named thing :marked Now a consumer can import what it needs from the barrel. - code-example(format=''). + code-example. import { Hero, HeroService } from '../heroes'; // index is implied :marked The Angular [scoped packages](#scoped-package) each have a barrel named `index`. // #enddocregion b-c :marked That's why we can write this: -+makeExample('../docs/_fragments/quickstart/ts/app/app.component.ts', 'import')(format=".") ++makeExcerpt('quickstart/ts/app/app.component.ts', 'import', '') // #docregion b-c :marked @@ -584,7 +584,7 @@ include _util-fns The only difference, from a consumer perspective, is that the package name begins with the Angular *scope name*, `@angular`. - +makeExample('../docs/_fragments/architecture/ts/app/app.component.ts', 'import')(format=".") + +makeExcerpt('architecture/ts/app/app.component.ts', 'import', '') // #docregion n-s-2 :marked diff --git a/public/docs/ts/latest/guide/glossary.jade b/public/docs/ts/latest/guide/glossary.jade index a66284569e..ca1429104e 100644 --- a/public/docs/ts/latest/guide/glossary.jade +++ b/public/docs/ts/latest/guide/glossary.jade @@ -1 +1 @@ -!= partial("../glossary") +include ../glossary diff --git a/tools/doc-shredder/processors/shredMapProcessor.js b/tools/doc-shredder/processors/shredMapProcessor.js index 5eb9ac1b24..569ba5511d 100644 --- a/tools/doc-shredder/processors/shredMapProcessor.js +++ b/tools/doc-shredder/processors/shredMapProcessor.js @@ -18,25 +18,37 @@ module.exports = function shredMapProcessor(log, createDocMessage) { var fragToJadeMap = {}; docs.forEach(function(doc) { - var jadePath = path.join(options.jadeDir, doc.fileInfo.relativePath); + var relativePath = doc.fileInfo.relativePath; + var jadePath = path.join(options.jadeDir, relativePath); + var lang = relativePath.substr(0, relativePath.indexOf('\/')); + var appProjDirName = jadeBaseFileNameToExampleName(doc.fileInfo.baseName); var fragInfoSet = {}; doc.fragItems.forEach(function(fragItem) { var mixinPath = fragItem.mixinPath; var fullExamplePath; + // Normalize mixinPath: strip out optional trailing '(...)' + var mixinPath = mixinPath.replace(/ \([^\)]*\)/,''); if ( mixinPath.indexOf('_api') >= 0) { var sourcePath = mixinPath.replace('_api/',''); fullExamplePath = path.join(options.apiExamplesDir, sourcePath); } else { fullExamplePath = path.join(options.devguideExamplesDir, mixinPath); } - var region = fragItem.region ? "-" + fragItem.region : ''; - var extn = path.extname(mixinPath); - var basename = path.basename(mixinPath, extn); - var fragDir = path.dirname(mixinPath); - var fragPath = path.join(fragDir, basename + region + extn) + '.md'; - var fullFragPath = path.join(options.fragmentsDir, fragPath); - - var fragInfo = { fragPath: fullFragPath, examplePath: fullExamplePath, exists: fs.existsSync(fullFragPath) }; + var fragInfo = makeFragInfo(options.fragmentsDir, fullExamplePath, fragItem, mixinPath); + if (!fragInfo.exists) { + var savedFragInfo = fragInfo; + // Assume that mixinPath is actually app-project-folder relative and + // prepend "lang/appProjDirName": + var appProjRelPath = mixinPath; + mixinPath = appProjDirName + '/' + lang + '/' + mixinPath; + fragInfo = makeFragInfo(options.fragmentsDir, fullExamplePath, fragItem, mixinPath); + if (fragInfo.exists) { + log.info('Ajusted example path (' + doc.fileInfo.baseName + '): ' + appProjRelPath + ' -> ' + mixinPath); + } else { + fragInfo = savedFragInfo; + } + } + var fragPath = fragInfo.relFragPath; fragInfoSet[fragPath] = fragInfo; if (fragInfo.exists) { var jadePathsSet = fragToJadeMap[fragPath]; @@ -46,7 +58,7 @@ module.exports = function shredMapProcessor(log, createDocMessage) { } jadePathsSet[jadePath] = jadePath; } else { - var relativePath = path.relative(".", fullFragPath); + var relativePath = path.relative(".", fragInfo.fragPath); log.warn(createDocMessage('Invalid example (unable to locate fragment file: "' + relativePath + '")', doc)); } }); @@ -82,13 +94,24 @@ module.exports = function shredMapProcessor(log, createDocMessage) { } }; -function getExampleName(fragPath) { - // pattern to isolate base fileName and extension from fragment name - var rx = /(.*)\-(.*)\.(.s)/; - var r = rx.exec(fragPath); - if (r) { - return r[1] + '.' + r[3]; - } else { - return fragPath; - } +// TODO: use the functionality in public/resources/js/util.js once it lands. +function jadeBaseFileNameToExampleName(name) { + // Adjust for known cases where chapter name is not the example name. + var matches = name.match(/(toh-)pt(\d+)/); + if (matches) name = matches[1] + matches[2]; + return name; +} + +function makeFragInfo(fragmentsDir, fullExamplePath, fragItem, mixinPath) { + var region = fragItem.region ? "-" + fragItem.region : ''; + var extn = path.extname(mixinPath); + var basename = path.basename(mixinPath, extn); + var fragDir = path.dirname(mixinPath); + var fragPath = path.join(fragDir, basename + region + extn) + '.md'; + var fullFragPath = path.join(fragmentsDir, fragPath); + return { + fragPath: fullFragPath, + relFragPath: fragPath, + examplePath: fullExamplePath, + exists: fs.existsSync(fullFragPath) }; } \ No newline at end of file From 86f82124d458285c4053482b6e9401eddcb859e0 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Tue, 5 Jul 2016 16:58:31 -0700 Subject: [PATCH 02/25] chore: dgeni tag defintions for ts2dart tags closes #1833 New `dgeni` tag definitions for `ts2dart` tags which are currently causing spurious warnings when generating API docs. --- tools/api-builder/angular.io-package/tag-defs/Annotation.js | 4 ++++ tools/api-builder/angular.io-package/tag-defs/index.js | 2 ++ .../api-builder/angular.io-package/tag-defs/ts2dart_const.js | 4 ++++ 3 files changed, 10 insertions(+) create mode 100644 tools/api-builder/angular.io-package/tag-defs/Annotation.js create mode 100644 tools/api-builder/angular.io-package/tag-defs/ts2dart_const.js diff --git a/tools/api-builder/angular.io-package/tag-defs/Annotation.js b/tools/api-builder/angular.io-package/tag-defs/Annotation.js new file mode 100644 index 0000000000..223195a9d7 --- /dev/null +++ b/tools/api-builder/angular.io-package/tag-defs/Annotation.js @@ -0,0 +1,4 @@ +// A ts2dart compiler annotation that can be ignored in API docs. +module.exports = function() { + return { name: 'Annotation', ignore: true }; +}; diff --git a/tools/api-builder/angular.io-package/tag-defs/index.js b/tools/api-builder/angular.io-package/tag-defs/index.js index 782a09189e..bbc9f5d167 100644 --- a/tools/api-builder/angular.io-package/tag-defs/index.js +++ b/tools/api-builder/angular.io-package/tag-defs/index.js @@ -1,9 +1,11 @@ module.exports = [ + require('./Annotation'), require('./deprecated'), require('./howToUse'), require('./whatItDoes'), require('./internal'), require('./stable'), + require('./ts2dart_const'), require('./experimental'), require('./docsNotRequired'), require('./security'), diff --git a/tools/api-builder/angular.io-package/tag-defs/ts2dart_const.js b/tools/api-builder/angular.io-package/tag-defs/ts2dart_const.js new file mode 100644 index 0000000000..dc2c3fa401 --- /dev/null +++ b/tools/api-builder/angular.io-package/tag-defs/ts2dart_const.js @@ -0,0 +1,4 @@ +// A ts2dart compiler annotation that can be ignored in API docs. +module.exports = function() { + return { name: 'ts2dart_const', ignore: true }; +}; From 81b011c6ba542132ed83a266f5d2c501aaeaf2e2 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Wed, 6 Jul 2016 14:48:19 -0700 Subject: [PATCH 03/25] =?UTF-8?q?chore(linkChecker):=20fix=20to=20checker?= =?UTF-8?q?=20config=20closes=20#1842=20This=20PR=20eliminates=20false=20p?= =?UTF-8?q?ositives=20by=20adjusting=20the=20checker=20config=20options:?= =?UTF-8?q?=20-=20Some=20sites=20don=E2=80=99t=20support=20`HEAD`=20so=20u?= =?UTF-8?q?se=20the=20`GET`=20method.=20-=20Exclude=20known=20problematic?= =?UTF-8?q?=20URLs=20from=20being=20checked.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gulpfile.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 44e0787e9b..dc10189b26 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -596,7 +596,18 @@ gulp.task('test-api-builder', function (cb) { // angular.io: gulp link-checker // local site: gulp link-checker --url=http://localhost:3000 gulp.task('link-checker', function(done) { - return linkChecker(); + var method = 'get'; // the default 'head' fails for some sites + var exclude = [ + // Dart API docs aren't working yet; ignore them + '*/dart/latest/api/*', + // Somehow the link checker sees ng1 {{...}} in the resource page; ignore it + 'resources/%7B%7Bresource.url%7D%7D', + // API docs have links directly into GitHub repo sources; these can + // quickly become invalid, so ignore them for now: + '*/angular/tree/*' + ]; + var blcOptions = { requestMethod: method, excludedKeywords: exclude}; + return linkChecker({ blcOptions: blcOptions }); }); @@ -727,12 +738,8 @@ function linkChecker(options) { var blcOptions = options.blcOptions || {}; var customData = options.customData || {}; - var excludeBad; // don't bother reporting bad links matching this RegExp - if (argv.excludeBad) { - excludeBad = new RegExp(argv.excludeBad); - } else { - excludeBad = options.excludeBad === undefined ? /docs\/dart\/latest\/api/ : ''; - } + // don't bother reporting bad links matching this RegExp + var excludeBad = argv.excludeBad ? new RegExp(argv.excludeBad) : (options.excludeBad || ''); var previousPage; var siteUrl = argv.url || options.url || 'https://angular.io/'; @@ -779,7 +786,8 @@ function linkChecker(options) { var outputFile = path.join(process.cwd(), 'link-checker-results.txt'); var header = 'Link checker results for: ' + siteUrl + '\nStarted: ' + (new Date()).toLocaleString() + - '\nSkipping bad links matching regex: ' +excludeBad.toString() + '\n\n'; + '\nExcluded links (blc file globs): ' + blcOptions.excludedKeywords + + '\nExcluded links (custom --exclude-bad regex): ' + excludeBad.toString() + '\n\n'; gutil.log(header); fs.writeFileSync(outputFile, header); From 761f857f13e363ff6dbd36ef1d89e7611fb3b4fd Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Fri, 1 Jul 2016 08:44:28 -0700 Subject: [PATCH 04/25] docs(architecture/dart): proofread, updated Dart/TS app and jade closes #1807 - e2e tests now also cover the tax calculator. - Dart app updated to match TS (it had no sales tax calculator). - TS sample source cleanup (e.g. removed many unnecessary `docregions`). - Prose updated to include @kwalrath's revisions from a while ago, Ward's comments, and some of my edits as well. Contributes to #1598 and #1508. --- .../architecture/dart/lib/app_component.dart | 15 + .../dart/lib/backend_service.dart | 30 +- .../_examples/architecture/dart/lib/hero.dart | 10 +- .../dart/lib/hero_detail_component.dart | 8 +- .../dart/lib/hero_detail_component.html | 8 +- .../dart/lib/hero_list_component.dart | 36 +- .../dart/lib/hero_list_component.html | 9 +- .../dart/lib/hero_list_component_1.html | 11 +- .../architecture/dart/lib/hero_service.dart | 14 +- .../architecture/dart/lib/logger_service.dart | 7 +- .../dart/lib/sales_tax_component.dart | 28 + .../dart/lib/sales_tax_service.dart | 14 + .../dart/lib/tax_rate_service.dart | 6 + .../architecture/dart/web/index.html | 17 +- .../_examples/architecture/dart/web/main.dart | 9 +- .../docs/_examples/architecture/e2e-spec.ts | 144 ++-- .../ts/app/hero-detail.component.html | 8 +- .../ts/app/hero-list.component.1.html | 9 +- .../ts/app/hero-list.component.html | 8 +- .../ts/app/hero-list.component.ts | 20 +- .../architecture/ts/app/hero.service.ts | 3 - .../architecture/ts/app/logger.service.ts | 2 - .../ts/app/sales-tax.component.ts | 17 - .../architecture/ts/app/sales-tax.service.ts | 12 +- .../architecture/ts/app/tax-rate.service.ts | 5 +- public/docs/dart/latest/guide/animations.jade | 1 + .../docs/dart/latest/guide/architecture.jade | 489 ++---------- public/docs/ts/latest/guide/architecture.jade | 742 ++++++++++-------- 28 files changed, 711 insertions(+), 971 deletions(-) create mode 100644 public/docs/_examples/architecture/dart/lib/app_component.dart create mode 100644 public/docs/_examples/architecture/dart/lib/sales_tax_component.dart create mode 100644 public/docs/_examples/architecture/dart/lib/sales_tax_service.dart create mode 100644 public/docs/_examples/architecture/dart/lib/tax_rate_service.dart create mode 100644 public/docs/dart/latest/guide/animations.jade diff --git a/public/docs/_examples/architecture/dart/lib/app_component.dart b/public/docs/_examples/architecture/dart/lib/app_component.dart new file mode 100644 index 0000000000..d0253504b4 --- /dev/null +++ b/public/docs/_examples/architecture/dart/lib/app_component.dart @@ -0,0 +1,15 @@ +// #docregion import +import 'package:angular2/core.dart'; +// #enddocregion import + +import 'hero_list_component.dart'; +import 'sales_tax_component.dart'; + +@Component( + selector: 'my-app', + template: ''' + + ''', + directives: const [HeroListComponent, SalesTaxComponent]) +// #docregion export +class AppComponent { } diff --git a/public/docs/_examples/architecture/dart/lib/backend_service.dart b/public/docs/_examples/architecture/dart/lib/backend_service.dart index d0f6886dbf..ef46001648 100644 --- a/public/docs/_examples/architecture/dart/lib/backend_service.dart +++ b/public/docs/_examples/architecture/dart/lib/backend_service.dart @@ -1,4 +1,5 @@ -// #docregion +import 'dart:async'; + import 'package:angular2/core.dart'; import 'hero.dart'; @@ -6,19 +7,22 @@ import 'logger_service.dart'; @Injectable() class BackendService { + static final _mockHeroes = [ + new Hero('Windstorm', 'Weather mastery'), + new Hero('Mr. Nice', 'Killing them with kindness'), + new Hero('Magneta', 'Manipulates metalic objects') + ]; + final Logger _logger; - List getAll(type) { - // TODO get from the database and return as a promise - if (type == Hero) { - return [ - new Hero('Windstorm', power: 'Weather mastery'), - new Hero('Mr. Nice', power: 'Killing them with kindness'), - new Hero('Magneta', power: 'Manipulates metalic objects') - ]; - } - _logger.error('Cannot get object of this type'); - throw new ArgumentError("TODO: put log content here"); - } BackendService(Logger this._logger); + + Future getAll(type) { + // TODO get from the database + if (type == Hero) return new Future.value(_mockHeroes); + + var msg = 'Cannot get object of this type'; + _logger.error(msg); + throw new Exception(msg); + } } diff --git a/public/docs/_examples/architecture/dart/lib/hero.dart b/public/docs/_examples/architecture/dart/lib/hero.dart index 1aa20e0ee8..8b9bf3dff3 100644 --- a/public/docs/_examples/architecture/dart/lib/hero.dart +++ b/public/docs/_examples/architecture/dart/lib/hero.dart @@ -1,11 +1,7 @@ -// #docregion class Hero { static int _nextId = 1; - int id; - String name; - String power; + final int id; + String name, power; - Hero(this.name, {this.power}) { - id = _nextId++; - } + Hero(this.name, [this.power = '']) : id = _nextId++; } diff --git a/public/docs/_examples/architecture/dart/lib/hero_detail_component.dart b/public/docs/_examples/architecture/dart/lib/hero_detail_component.dart index 94c26abbd0..16a22159d8 100644 --- a/public/docs/_examples/architecture/dart/lib/hero_detail_component.dart +++ b/public/docs/_examples/architecture/dart/lib/hero_detail_component.dart @@ -1,9 +1,11 @@ -// #docregion import 'package:angular2/core.dart'; import 'hero.dart'; -@Component(selector: 'hero-detail', templateUrl: 'hero_detail_component.html') +@Component( + selector: 'hero-detail', + templateUrl: 'hero_detail_component.html') class HeroDetailComponent { - @Input() Hero hero; + @Input() + Hero hero; } diff --git a/public/docs/_examples/architecture/dart/lib/hero_detail_component.html b/public/docs/_examples/architecture/dart/lib/hero_detail_component.html index 7dde3107e4..224de8bb86 100644 --- a/public/docs/_examples/architecture/dart/lib/hero_detail_component.html +++ b/public/docs/_examples/architecture/dart/lib/hero_detail_component.html @@ -2,8 +2,8 @@

{{hero.name}} Detail

Id: {{hero.id}}
Name: - -
- -
Power: + + +
+
Power:
diff --git a/public/docs/_examples/architecture/dart/lib/hero_list_component.dart b/public/docs/_examples/architecture/dart/lib/hero_list_component.dart index ba2b75de70..8d30a2344e 100644 --- a/public/docs/_examples/architecture/dart/lib/hero_list_component.dart +++ b/public/docs/_examples/architecture/dart/lib/hero_list_component.dart @@ -1,4 +1,3 @@ -// #docplaster import 'package:angular2/core.dart'; import 'hero.dart'; @@ -6,32 +5,31 @@ import 'hero_detail_component.dart'; import 'hero_service.dart'; // #docregion metadata -// #docregion providers @Component( -// #enddocregion providers selector: 'hero-list', templateUrl: 'hero_list_component.html', directives: const [HeroDetailComponent], -// #docregion providers - providers: const [HeroService]) -// #enddocregion providers -// #enddocregion metadata -/* -// #docregion metadata, providers -class HeroListComponent { ... } -// #enddocregion metadata, providers -*/ + // #docregion providers + providers: const [HeroService] + // #enddocregion providers + ) // #docregion class -class HeroListComponent { +class HeroListComponent implements OnInit { + // #enddocregion metadata List heroes; Hero selectedHero; -// #docregion ctor - HeroListComponent(HeroService heroService) { - heroes = heroService.getHeroes(); + // #docregion ctor + final HeroService _heroService; + + HeroListComponent(this._heroService); + // #enddocregion ctor + + void ngOnInit() { + heroes = _heroService.getHeroes(); } -// #enddocregion ctor - selectHero(Hero hero) { + + void selectHero(Hero hero) { selectedHero = hero; } + // #docregion metadata } -// #enddocregion class diff --git a/public/docs/_examples/architecture/dart/lib/hero_list_component.html b/public/docs/_examples/architecture/dart/lib/hero_list_component.html index e493e949fb..de60c4e376 100644 --- a/public/docs/_examples/architecture/dart/lib/hero_list_component.html +++ b/public/docs/_examples/architecture/dart/lib/hero_list_component.html @@ -1,8 +1,11 @@

Hero List

-
- {{hero.name}} -
+

Pick a hero from the list

+
    +
  • + {{hero.name}} +
  • +
diff --git a/public/docs/_examples/architecture/dart/lib/hero_list_component_1.html b/public/docs/_examples/architecture/dart/lib/hero_list_component_1.html index 7a08bd2f8b..eef5b9a3bf 100644 --- a/public/docs/_examples/architecture/dart/lib/hero_list_component_1.html +++ b/public/docs/_examples/architecture/dart/lib/hero_list_component_1.html @@ -1,10 +1,9 @@ -
{{hero.name}}
- -
...
+
  • {{hero.name}}
  • + +
  • -
    ...
    - - +
  • + diff --git a/public/docs/_examples/architecture/dart/lib/hero_service.dart b/public/docs/_examples/architecture/dart/lib/hero_service.dart index 794e79927e..a23734d327 100644 --- a/public/docs/_examples/architecture/dart/lib/hero_service.dart +++ b/public/docs/_examples/architecture/dart/lib/hero_service.dart @@ -4,16 +4,20 @@ import 'backend_service.dart'; import 'hero.dart'; import 'logger_service.dart'; -// #docregion class @Injectable() +// #docregion class class HeroService { final BackendService _backendService; final Logger _logger; - HeroService(Logger this._logger, BackendService this._backendService); + final List heroes = []; + + HeroService(this._logger, this._backendService); + List getHeroes() { - List heroes = _backendService.getAll(Hero); - _logger.log('Got ${heroes.length} heroes from the server.'); + _backendService.getAll(Hero).then((heroes) { + _logger.log('Fetched ${heroes.length} heroes.'); + this.heroes.addAll(heroes); // fill cache + }); return heroes; } } -// #enddocregion class diff --git a/public/docs/_examples/architecture/dart/lib/logger_service.dart b/public/docs/_examples/architecture/dart/lib/logger_service.dart index 2d6d1c4f75..2b8e19fde5 100644 --- a/public/docs/_examples/architecture/dart/lib/logger_service.dart +++ b/public/docs/_examples/architecture/dart/lib/logger_service.dart @@ -1,16 +1,11 @@ -// #docregion import 'dart:html'; import 'package:angular2/core.dart'; -/// A service for logging messages of various types. -/// -/// We could switch this implementation to use package:logging. @Injectable() +// #docregion class class Logger { void log(Object msg) => window.console.log(msg); - void error(Object msg) => window.console.error(msg); - void warn(Object msg) => window.console.warn(msg); } diff --git a/public/docs/_examples/architecture/dart/lib/sales_tax_component.dart b/public/docs/_examples/architecture/dart/lib/sales_tax_component.dart new file mode 100644 index 0000000000..7f5ed5036c --- /dev/null +++ b/public/docs/_examples/architecture/dart/lib/sales_tax_component.dart @@ -0,0 +1,28 @@ +import 'package:angular2/core.dart'; + +import 'sales_tax_service.dart'; +import 'tax_rate_service.dart'; + +@Component( + selector: 'sales-tax', + template: ''' +

    Sales Tax Calculator

    + Amount: + +
    + The sales tax is + {{ getTax(amountBox.value) | currency:'USD':false:'1.2-2' }} + +
    + ''', + providers: const [SalesTaxService, TaxRateService]) +class SalesTaxComponent { + SalesTaxService _salesTaxService; + + SalesTaxComponent(this._salesTaxService) {} + + num getTax(dynamic /* String | num */ value) => + this._salesTaxService.getVAT(value); +} diff --git a/public/docs/_examples/architecture/dart/lib/sales_tax_service.dart b/public/docs/_examples/architecture/dart/lib/sales_tax_service.dart new file mode 100644 index 0000000000..126f2c3033 --- /dev/null +++ b/public/docs/_examples/architecture/dart/lib/sales_tax_service.dart @@ -0,0 +1,14 @@ +import 'package:angular2/core.dart'; + +import 'tax_rate_service.dart'; + +@Injectable() +class SalesTaxService { + TaxRateService rateService; + + SalesTaxService(this.rateService); + + num getVAT(dynamic /* String | num */ value) => + rateService.getRate('VAT') * + (value is num ? value : num.parse(value, (_) => 0)); +} diff --git a/public/docs/_examples/architecture/dart/lib/tax_rate_service.dart b/public/docs/_examples/architecture/dart/lib/tax_rate_service.dart new file mode 100644 index 0000000000..87613acc4d --- /dev/null +++ b/public/docs/_examples/architecture/dart/lib/tax_rate_service.dart @@ -0,0 +1,6 @@ +import 'package:angular2/core.dart'; + +@Injectable() +class TaxRateService { + getRate(String rateName) => 0.10; +} diff --git a/public/docs/_examples/architecture/dart/web/index.html b/public/docs/_examples/architecture/dart/web/index.html index 17a00ffbed..a422e64542 100644 --- a/public/docs/_examples/architecture/dart/web/index.html +++ b/public/docs/_examples/architecture/dart/web/index.html @@ -1,12 +1,15 @@ - - Intro to Angular 2 - - - - + + Architecture of Angular 2 + + + + + + + - Loading... + Loading... diff --git a/public/docs/_examples/architecture/dart/web/main.dart b/public/docs/_examples/architecture/dart/web/main.dart index acb382ab8e..78397625f8 100644 --- a/public/docs/_examples/architecture/dart/web/main.dart +++ b/public/docs/_examples/architecture/dart/web/main.dart @@ -1,13 +1,14 @@ // #docregion import 'package:angular2/platform/browser.dart'; - +// #docregion import +import 'package:developer_guide_intro/app_component.dart'; +// #enddocregion import import 'package:developer_guide_intro/backend_service.dart'; -import 'package:developer_guide_intro/hero_list_component.dart'; import 'package:developer_guide_intro/hero_service.dart'; import 'package:developer_guide_intro/logger_service.dart'; -main() { +void main() { // #docregion bootstrap - bootstrap(HeroListComponent, [BackendService, HeroService, Logger]); + bootstrap(AppComponent, [BackendService, HeroService, Logger]); // #enddocregion bootstrap } diff --git a/public/docs/_examples/architecture/e2e-spec.ts b/public/docs/_examples/architecture/e2e-spec.ts index 152ffd322d..54bf9be8f2 100644 --- a/public/docs/_examples/architecture/e2e-spec.ts +++ b/public/docs/_examples/architecture/e2e-spec.ts @@ -1,63 +1,99 @@ /// 'use strict'; -describe('Architecture', function () { - let title = 'Hero List'; +const nameSuffix = 'X'; - beforeAll(function () { - browser.get(''); +class Hero { + id: number; + name: string; +} + +describe('Architecture', () => { + + const expectedTitle = 'Architecture of Angular 2'; + const expectedH2 = ['Hero List', 'Sales Tax Calculator']; + + beforeAll(() => browser.get('')); + + it(`has title '${expectedTitle}'`, () => { + expect(browser.getTitle()).toEqual(expectedTitle); }); - function itReset(name: string, func: () => any) { - it(name, function() { - browser.get('').then(func); - }); - } - - it(`should display correct title: ${title}`, function () { - expect(element(by.css('h2')).getText()).toEqual(title); - }); - - it('should display correct detail after selection', function() { - let detailView = element(by.css('hero-detail')); - expect(detailView.isPresent()).toBe(false); - // select the 2nd element - let selectEle = element.all(by.css('hero-list > div')).get(1); - selectEle.click().then(function() { - return selectEle.getText(); - }).then(function(selectedHeroName) { - // works but too specific if we change the app - // expect(selectedHeroName).toEqual('Mr. Nice'); - expect(detailView.isDisplayed()).toBe(true); - let detailTitleEle = element(by.css('hero-detail > h4')); - expect(detailTitleEle.getText()).toContain(selectedHeroName); - }); - }); - - itReset('should display correct detail after modification', function() { - let detailView = element(by.css('hero-detail')); - expect(detailView.isPresent()).toBe(false); - // select the 2nd element - let selectEle = element.all(by.css('hero-list > div')).get(1); - selectEle.click().then(function () { - return selectEle.getText(); - }).then(function (selectedHeroName) { - let detailTitleEle = element(by.css('hero-detail > h4')); - expect(detailTitleEle.getText()).toContain(selectedHeroName); - let heroNameEle = element.all(by.css('hero-detail input')).get(0); - - // check that both the initial selected item and the detail title reflect changes - // made to the input box. - // heroNameEle.sendKeys('foo'); - sendKeys(heroNameEle, 'foo'); - expect(detailTitleEle.getText()).toContain('foo'); - expect(selectEle.getText()).toContain('foo'); - - // getText on an input element always returns null - // http://stackoverflow.com/questions/20310442/how-to-gettext-on-an-input-in-protractor - // expect(heroNameEle.getText()).toEqual(selectedHeroName); - expect(heroNameEle.getAttribute('value')).toEqual(selectedHeroName + 'foo'); - }); + it(`has h2 '${expectedH2}'`, () => { + let h2 = element.all(by.css('h2')).map((elt) => elt.getText()); + expect(h2).toEqual(expectedH2); }); + describe('Hero', heroTests); + describe('Salex tax', salesTaxTests); }); + +function heroTests() { + + const targetHero: Hero = { id: 2, name: 'Mr. Nice' }; + + it('has the right number of heroes', () => { + let page = getPageElts(); + expect(page.heroes.count()).toEqual(3); + }); + + it('has no hero details initially', function () { + let page = getPageElts(); + expect(page.heroDetail.isPresent()).toBeFalsy('no hero detail'); + }); + + it('shows selected hero details', async () => { + await element(by.cssContainingText('li', targetHero.name)).click(); + let page = getPageElts(); + let hero = await heroFromDetail(page.heroDetail); + expect(hero.id).toEqual(targetHero.id); + expect(hero.name).toEqual(targetHero.name); + }); + + it(`shows updated hero name in details`, async () => { + let input = element.all(by.css('input')).first(); + await sendKeys(input, nameSuffix); + let page = getPageElts(); + let hero = await heroFromDetail(page.heroDetail); + let newName = targetHero.name + nameSuffix; + expect(hero.id).toEqual(targetHero.id); + expect(hero.name).toEqual(newName); + }); +} + +function salesTaxTests() { + it('has no sales tax initially', function () { + let page = getPageElts(); + expect(page.salesTaxDetail.isPresent()).toBeFalsy('no sales tax info'); + }); + + it('shows sales tax', async function () { + let page = getPageElts(); + await sendKeys(page.salesTaxAmountInput, '10'); + // Note: due to Dart bug USD is shown instead of $ + let re = /The sales tax is (\$|USD)1.00/; + expect(page.salesTaxDetail.getText()).toMatch(re); + }); +} + +// Helper functions + +function getPageElts() { + return { + heroes: element.all(by.css('my-app li')), + heroDetail: element(by.css('my-app hero-detail')), + salesTaxAmountInput: element(by.css('my-app sales-tax input')), + salesTaxDetail: element(by.css('my-app sales-tax div')) + }; +} + +async function heroFromDetail(detail: protractor.ElementFinder): Promise { + // Get hero id from the first
    + let _id = await detail.all(by.css('div')).first().getText(); + // Get name from the h2 + let _name = await detail.element(by.css('h4')).getText(); + return { + id: +_id.substr(_id.indexOf(' ') + 1), + name: _name.substr(0, _name.lastIndexOf(' ')) + }; +} diff --git a/public/docs/_examples/architecture/ts/app/hero-detail.component.html b/public/docs/_examples/architecture/ts/app/hero-detail.component.html index baa3e8d9f9..224de8bb86 100644 --- a/public/docs/_examples/architecture/ts/app/hero-detail.component.html +++ b/public/docs/_examples/architecture/ts/app/hero-detail.component.html @@ -2,8 +2,8 @@

    {{hero.name}} Detail

    Id: {{hero.id}}
    Name: - - - + + +
    -
    Power:
    \ No newline at end of file +
    Power:
    diff --git a/public/docs/_examples/architecture/ts/app/hero-list.component.1.html b/public/docs/_examples/architecture/ts/app/hero-list.component.1.html index d4d6b905fa..c6e6dd5133 100644 --- a/public/docs/_examples/architecture/ts/app/hero-list.component.1.html +++ b/public/docs/_examples/architecture/ts/app/hero-list.component.1.html @@ -1,12 +1,9 @@ -
    {{hero.name}}
    +
  • {{hero.name}}
  • -
    - +
  • -
    +
  • - - diff --git a/public/docs/_examples/architecture/ts/app/hero-list.component.html b/public/docs/_examples/architecture/ts/app/hero-list.component.html index f3c92b3141..b46a307bd3 100644 --- a/public/docs/_examples/architecture/ts/app/hero-list.component.html +++ b/public/docs/_examples/architecture/ts/app/hero-list.component.html @@ -2,8 +2,10 @@

    Hero List

    Pick a hero from the list

    -
    - {{hero.name}} -
    +
      +
    • + {{hero.name}} +
    • +
    diff --git a/public/docs/_examples/architecture/ts/app/hero-list.component.ts b/public/docs/_examples/architecture/ts/app/hero-list.component.ts index d7bc9e75d9..eaa21b45fe 100644 --- a/public/docs/_examples/architecture/ts/app/hero-list.component.ts +++ b/public/docs/_examples/architecture/ts/app/hero-list.component.ts @@ -1,4 +1,3 @@ -// #docplaster import { Component, OnInit } from '@angular/core'; import { Hero } from './hero'; @@ -6,35 +5,28 @@ import { HeroDetailComponent } from './hero-detail.component'; import { HeroService } from './hero.service'; // #docregion metadata -// #docregion providers @Component({ -// #enddocregion providers selector: 'hero-list', templateUrl: 'app/hero-list.component.html', directives: [HeroDetailComponent], -// #docregion providers + // #docregion providers providers: [HeroService] + // #enddocregion providers }) -// #enddocregion providers -// #enddocregion metadata -/* -// #docregion metadata, providers -export class HeroesComponent { ... } -// #enddocregion metadata, providers -*/ // #docregion class export class HeroListComponent implements OnInit { + // #enddocregion metadata heroes: Hero[]; selectedHero: Hero; -// #docregion ctor + // #docregion ctor constructor(private service: HeroService) { } -// #enddocregion ctor + // #enddocregion ctor ngOnInit() { this.heroes = this.service.getHeroes(); } selectHero(hero: Hero) { this.selectedHero = hero; } + // #docregion metadata } -// #enddocregion class diff --git a/public/docs/_examples/architecture/ts/app/hero.service.ts b/public/docs/_examples/architecture/ts/app/hero.service.ts index 027d4bfc6a..493f064e40 100644 --- a/public/docs/_examples/architecture/ts/app/hero.service.ts +++ b/public/docs/_examples/architecture/ts/app/hero.service.ts @@ -9,11 +9,9 @@ import { Logger } from './logger.service'; export class HeroService { private heroes: Hero[] = []; - // #docregion ctor constructor( private backend: BackendService, private logger: Logger) { } - // #enddocregion ctor getHeroes() { this.backend.getAll(Hero).then( (heroes: Hero[]) => { @@ -23,4 +21,3 @@ export class HeroService { return this.heroes; } } -// #enddocregion class diff --git a/public/docs/_examples/architecture/ts/app/logger.service.ts b/public/docs/_examples/architecture/ts/app/logger.service.ts index 2d66d202eb..9277ee8bc0 100644 --- a/public/docs/_examples/architecture/ts/app/logger.service.ts +++ b/public/docs/_examples/architecture/ts/app/logger.service.ts @@ -1,4 +1,3 @@ -// #docregion import { Injectable } from '@angular/core'; @Injectable() @@ -8,4 +7,3 @@ export class Logger { error(msg: any) { console.error(msg); } warn(msg: any) { console.warn(msg); } } -// #enddocregion class diff --git a/public/docs/_examples/architecture/ts/app/sales-tax.component.ts b/public/docs/_examples/architecture/ts/app/sales-tax.component.ts index 252f8e5b14..983e731dc7 100644 --- a/public/docs/_examples/architecture/ts/app/sales-tax.component.ts +++ b/public/docs/_examples/architecture/ts/app/sales-tax.component.ts @@ -1,14 +1,9 @@ -// #docplaster -// #docregion import { Component } from '@angular/core'; import { SalesTaxService } from './sales-tax.service'; import { TaxRateService } from './tax-rate.service'; -// #docregion metadata -// #docregion providers @Component({ -// #enddocregion providers selector: 'sales-tax', template: `

    Sales Tax Calculator

    @@ -19,24 +14,12 @@ import { TaxRateService } from './tax-rate.service'; {{ getTax(amountBox.value) | currency:'USD':true:'1.2-2' }}
    `, -// #docregion providers providers: [SalesTaxService, TaxRateService] }) -// #enddocregion providers -// #enddocregion metadata -/* -// #docregion metadata, providers -export class SalesTaxComponent { ... } -// #enddocregion metadata, providers -*/ -// #docregion class export class SalesTaxComponent { -// #docregion ctor constructor(private salesTaxService: SalesTaxService) { } -// #enddocregion ctor getTax(value: string | number) { return this.salesTaxService.getVAT(value); } } -// #enddocregion class diff --git a/public/docs/_examples/architecture/ts/app/sales-tax.service.ts b/public/docs/_examples/architecture/ts/app/sales-tax.service.ts index 5bf505548a..d859dc1595 100644 --- a/public/docs/_examples/architecture/ts/app/sales-tax.service.ts +++ b/public/docs/_examples/architecture/ts/app/sales-tax.service.ts @@ -1,20 +1,14 @@ -// #docregion import { Injectable } from '@angular/core'; import { TaxRateService } from './tax-rate.service'; -// #docregion class @Injectable() export class SalesTaxService { constructor(private rateService: TaxRateService) { } + getVAT(value: string | number) { - let amount: number; - if (typeof value === 'string') { - amount = parseFloat(value); - } else { - amount = value; - } + let amount = (typeof value === 'string') ? + parseFloat(value) : value; return (amount || 0) * this.rateService.getRate('VAT'); } } -// #enddocregion class diff --git a/public/docs/_examples/architecture/ts/app/tax-rate.service.ts b/public/docs/_examples/architecture/ts/app/tax-rate.service.ts index 334399f27a..fff2f4df8f 100644 --- a/public/docs/_examples/architecture/ts/app/tax-rate.service.ts +++ b/public/docs/_examples/architecture/ts/app/tax-rate.service.ts @@ -1,9 +1,6 @@ -// #docregion import { Injectable } from '@angular/core'; -// #docregion class @Injectable() export class TaxRateService { - getRate(rateName: string) {return 0.10; } // always 10% everywhere + getRate(rateName: string) { return 0.10; } // 10% everywhere } -// #enddocregion class diff --git a/public/docs/dart/latest/guide/animations.jade b/public/docs/dart/latest/guide/animations.jade new file mode 100644 index 0000000000..6778b6af28 --- /dev/null +++ b/public/docs/dart/latest/guide/animations.jade @@ -0,0 +1 @@ +!= partial("../../../_includes/_ts-temp") diff --git a/public/docs/dart/latest/guide/architecture.jade b/public/docs/dart/latest/guide/architecture.jade index 2c6f1b04bc..f5f63c07a8 100644 --- a/public/docs/dart/latest/guide/architecture.jade +++ b/public/docs/dart/latest/guide/architecture.jade @@ -1,451 +1,72 @@ -include ../_util-fns +extends ../../../ts/latest/guide/architecture.jade + +block includes + include ../_util-fns + - var _library_module = 'library' + - var _at_angular = 'angular2' :marked Angular 2 is a framework to help us build client applications in HTML and either JavaScript or a language (like Dart or TypeScript) that compiles to JavaScript. - Angular 2 for Dart is published as the `angular2` package, which - (like many other Dart packages) is available via the Pub tool. - With Angular, we write applications by composing HTML *templates* with Angularized markup, - writing *component* classes to manage those templates, adding application logic in *services*, - and handing the top root component to Angular's *bootstrapper*. - - Angular takes over, presenting our application content in a browser and responding to user interactions - according to the instructions we provided. - - -:marked - Of course there is more to it than this. - We're cruising at high altitude in this overview. - We're looking for landmarks. We should expect the object below to be fuzzy and obscured by occasional clouds. - Details become more clear and precise when we land in the chapters themselves. -
    - -:marked - An Angular 2 for Dart application rests on seven main building blocks: - 1. [Components](#component) - 1. [Templates](#template) - 1. [Metadata](#metadata) - 1. [Data binding](#data-binding) - 1. [Directives](#directive) - 1. [Services](#service) - 1. [Dependency injection](#dependency-injection) - -figure - img(src="/resources/images/devguide/architecture/overview.png" alt="overview" style="margin-left:-40px;" width="700") -:marked - Learn these seven and we're on our way. - -.l-main-section - -:marked - ## Components -figure - img(src="/resources/images/devguide/architecture/hero-component.png" alt="Component" align="left" style="width:200px; margin-left:-40px;margin-right:10px" ) -:marked - A **component** controls a patch of screen real estate that we could call a *view*. - A set of navigation links, a list of heroes, a hero editor ... - they're all views controlled by components. - - We define a component's application logic — what it does to support the view — inside a class. - The class interacts with the view through an API of properties and methods. - - - A `HeroListComponent`, for example, might have a `heroes` property that returns an array of heroes - that it acquired from a service. - It might have a `selectHero()` method that sets a `selectedHero` property when the user clicks to choose a hero from that list. - The component might be a class like this: - -+makeExample('architecture/dart/lib/hero_list_component.dart', 'class', 'lib/hero_list_component.dart') -:marked - Angular creates, updates, and destroys components as the user moves through the application. - The developer can take action at each moment in this lifecycle through optional lifecycle hooks. - - -.l-sub-section +block angular-parts :marked - We may wonder who is calling the component's constructor? Who provides the service parameter? - For the moment, have faith that Angular will call the constructor and deliver an - appropriate `HeroService` when we need it. + Angular 2 for Dart is published as the `angular2` package, which + (like many other Dart packages) is available via the Pub tool. -.l-main-section - -:marked - ## Templates -figure - img(src="/resources/images/devguide/architecture/template.png" alt="Template" align="left" style="width:200px; margin-left:-40px;margin-right:10px" ) -:marked - We define a component's view with its companion **template**. A template is a form of HTML - that tells Angular how to render the component. +block modules-in-dart + .callout.is-helpful + header Dart difference: Modules are compilation units or packages + :marked + In this guide, the term _module_ refers to a Dart compilation unit, such + as a library, or a package. (If a Dart file has no `library` or `part` + directive, then that file itself is a library and thus a compilation + unit.) For more information about compilation units, see + the chapter on "Libraries and Scripts" in the + [Dart Language Specification](https://www.dartlang.org/docs/spec/). - A template looks like regular HTML much of the time ... and then it gets a bit strange. Here is a - template for our `HeroListComponent`: -+makeExample('architecture/dart/lib/hero_list_component.html', null, 'lib/hero_list_component.html') -:marked - This template features typical HTML elements like `

    ` and `
    `. - But what are `*ngFor`, {‌{hero.name}}, `(click)`, `[hero]`, and ``? - They're examples of Angular's template syntax. - We'll grow accustomed to that syntax and may even learn to love it. +block modules-are-optional + //- N/A - Take a look at the last line, - which has the `` tag. - That tag adds a custom element representing a component we haven't seen yet, - a `HeroDetailComponent`. +block export-qualifier + .callout.is-helpful + header Dart difference: Public names are exported by default + :marked + Contrary to TypeScript, a Dart library always exports all names and + declarations in its **public** namespace, making explicit `export` + qualifiers unnecessary. + + When we say that a module _exports_ a declaration, we mean that the + declaration is _public_. For more details about name spaces and export + statements, see the section on "Exports" in the + [Dart Language Specification](https://www.dartlang.org/docs/spec/). - The `HeroDetailComponent` is a *different* component than the `HeroListComponent` we've seen. - The `HeroDetailComponent` (code not shown) presents facts about a particular hero, the - hero that the user selects from the list presented by the `HeroListComponent`. - The `HeroDetailComponent` is a **child** of the `HeroListComponent`. +block ts-import + //- N/A -figure - img(src="/resources/images/devguide/architecture/component-tree.png" alt="Metadata" align="left" style="width:300px; margin-left:-40px;margin-right:10px" ) -:marked - Notice how `` rests comfortably among native HTML elements. - We can and _will_ mix our custom components with native HTML in the same layouts. - - In this manner we'll compose complex component trees to build out our richly featured application. -
    - -.l-main-section - -:marked - ## Metadata -figure - img(src="/resources/images/devguide/architecture/metadata.png" alt="Metadata" align="left" style="width:150px; margin-left:-40px;margin-right:10px" ) -:marked -

    Metadata tells Angular how to process a class.

    -
    -:marked - [Looking back at the code](#component-code) for `HeroListComponent`, we see that it's just a class. - There is no evidence of a framework, no "Angular" in it at all. - - In fact, it really is *just a class*. It's not a component until we *tell Angular about it*. - - We tell Angular that `HeroListComponent` is a component by attaching **metadata** to the class. - - In Dart, we attach metadata by using an **annotation**. - Here's some metadata for `HeroListComponent`: - -+makeExample('architecture/dart/lib/hero_list_component.dart', 'metadata', 'lib/hero_list_component.dart') -:marked - Here we see the `@Component` annotation, which (no surprise) identifies the class - immediately below it as a component class. - - Annotations often have configuration parameters. - The `@Component` annotation takes parameters to provide the - information Angular needs to create and present the component and its view. - - Here we see a few of the possible `@Component` parameters: - - * `selector`: A CSS selector that tells Angular to create and insert an instance of this component - where it finds a `` tag in *parent* HTML. - For example, if an app's HTML contains ``, then - Angular inserts an instance of the `HeroListComponent` view between those tags. - - * `templateUrl`: The address of this component's template, which we showed [above](#the-template). - - * `directives`: An array of the components or directives that *this* template requires. - We saw in the last line of our template that we expect Angular to insert a `HeroDetailComponent` - in the space indicated by `` tags. - Angular will do so only if we mention the `HeroDetailComponent` in this `directives` array. - - * `providers`: An array of **dependency injection providers** for services that the component requires. - This is one way to tell Angular that our component's constructor requires a `HeroService` - so it can get the list of heroes to display. We'll get to dependency injection later. -figure - img(src="/resources/images/devguide/architecture/template-metadata-component.png" alt="Metadata" align="left" style="height:200px; margin-left:-40px;margin-right:10px" ) - -:marked - At runtime, Angular discovers the metadata specified by the `@Component` - annotation. That's how Angular learns how to do "the right thing". - - The template, metadata, and component together describe the view. - - We apply other metadata annotations in a similar fashion to guide Angular behavior. - `@Injectable`, `@Input`, `@Output`, and `@RouterConfig` are a few of the more popular annotations - we'll master as our Angular knowledge grows. -
    -:marked - The architectural takeaway is that we must add metadata to our code - so that Angular knows what to do. - -.l-main-section - -:marked - ## Data binding - Without a framework, we would be responsible for pushing data values into the HTML controls and turning user responses - into actions and value updates. Writing such push/pull logic by hand is tedious, error-prone, and a nightmare to - read as any experienced jQuery programmer can attest. -figure - img(src="/resources/images/devguide/architecture/databinding.png" alt="Data Binding" style="width:220px; float:left; margin-left:-40px;margin-right:20px" ) -:marked - Angular supports **data binding**, - a mechanism for coordinating parts of a template with parts of a component. - We add binding markup to the template HTML to tell Angular how to connect both sides. - - There are four forms of data binding syntax. Each form has a direction — to the DOM, from the DOM, or in both directions — - as indicated by the arrows in the diagram. -
    -:marked - We saw three forms of data binding in our [example](#template) template: -+makeExample('architecture/dart/lib/hero_list_component_1.html', 'binding')(format=".") -:marked - * The {‌{hero.name}} [interpolation](displaying-data.html#interpolation) - displays the component's `hero.name` property value within the `
    ` tags. - - * The `[hero]` property binding - passes the value of `selectedHero` from - the parent `HeroListComponent` to the `hero` property of the child `HeroDetailComponent`. - - * The `(click)` [event binding](user-input.html#click) calls the component's `selectHero` method when the user clicks a hero's name. - - **Two-way data binding** is an important fourth form - that combines property and event binding in a single notation, using the `ngModel` directive. - We didn't have a two-way binding in the `HeroListComponent` template; - here's an example from the `HeroDetailComponent` template: - -+makeExample('architecture/dart/lib/hero_detail_component.html', 'ng-model', 'lib/hero_detail_component.html (excerpt)')(format=".") -:marked - In two-way binding, a data property value flows to the input box from the component as with property binding. - The user's changes also flow back to the component, resetting the property to the latest value, - as with event binding. - - Angular processes *all* data bindings once per JavaScript event cycle, - depth-first from the root of the application component tree. - -figure - img(src="/resources/images/devguide/architecture/component-databinding.png" alt="Data Binding" style="float:left; width:300px; margin-left:-40px;margin-right:10px" ) -:marked - We don't know all the details yet, - but it's clear from these examples that data binding plays an important role in communication - between a template and its component. -
    -figure - img(src="/resources/images/devguide/architecture/parent-child-binding.png" alt="Parent/Child binding" style="float:left; width:300px; margin-left:-40px;margin-right:10px" ) -:marked - Data binding is also important for communication between parent and child components. -
    - -.l-main-section - -:marked - ## Directives -figure - img(src="/resources/images/devguide/architecture/directive.png" alt="Parent child" style="float:left; width:150px; margin-left:-40px;margin-right:10px" ) -:marked - Angular templates are *dynamic*. When Angular renders them, it transforms the DOM - according to the instructions given by **directives**. - - A directive is a class with directive metadata. In Dart we apply the `@Directive` annotation - to attach metadata to the class. -
    -:marked - We already met one form of directive: the component. A component is a *directive-with-a-template*; - a `@Component` annotation is actually a `@Directive` annotation extended with template-oriented features. - -.l-sub-section +block angular-library-modules :marked - While **a component is technically a directive**, - components are so distinctive and central to Angular applications that we chose - to separate components from directives in this architectural overview. -:marked - Two *other* kinds of directives exist: _structural_ and _attribute_ directives. + Angular ships as a collection of libraries within the + [**angular2**](https://pub.dartlang.org/packages/angular2) package. - They tend to appear within an element tag like attributes, - sometimes by name but more often as the target of an assignment or a binding. +block angular-imports + +makeExcerpt('app/app.component.ts', 'import') - **Structural** directives alter layout by adding, removing, and replacing elements in DOM. - - Our [example](#template) template uses two built-in structural directives: -+makeExample('architecture/dart/lib/hero_list_component_1.html', 'structural')(format=".") -:marked - * [`*ngFor`](displaying-data.html#ng-for) tells Angular to stamp out one `
    ` per hero in the `heroes` list. - * [`*ngIf`](displaying-data.html#ng-if) includes the `HeroDetail` component only if a selected hero exists. - -.l-sub-section +block ts-decorator :marked - In Dart, **the only value that is true is the boolean value `true`**; all - other values are false. JavaScript and TypeScript, in contrast, treat values - such as 1 and most non-null objects as true. For this reason, the JavaScript - and TypeScript versions of this app can use just `selectedHero` as the value - of the `*ngIf` expression. The Dart version must use a boolean operator such - as `!=` instead. + Annotations often have configuration parameters. + The `@Component` annotation takes parameters to provide the + information Angular needs to create and present the component and its view. -:marked - **Attribute** directives alter the appearance or behavior of an existing element. - In templates they look like regular HTML attributes, hence the name. + Here are a few of the possible `@Component` parameters: - The `ngModel` directive, which implements two-way data binding, is - an example of an attribute directive. `ngModel` modifies the behavior of - an existing element (typically an ``) - by setting its display value property and responding to change events. - -+makeExample('architecture/dart/lib/hero_detail_component.html', 'ng-model')(format=".") -:marked - Angular ships with a small number of other directives that either alter the layout structure - (for example, `ngSwitch`) - or modify aspects of DOM elements and components - (for example, `ngStyle` and `ngClass`). - - - Of course, we can also write our own directives. Components such as - `HeroListComponent` are one kind of custom directive. - - -.l-main-section - -:marked - ## Services -figure - img(src="/resources/images/devguide/architecture/service.png" alt="Service" style="float:left; margin-left:-40px;margin-right:10px" ) -:marked - _Services_ is a broad category encompassing any value, function, or feature that our application needs. - - Almost anything can be a service. - A service is typically a class with a narrow, well-defined purpose. It should do something specific and do it well. -
    -:marked - Examples include: - * logging service - * data service - * message bus - * tax calculator - * application configuration - - There is nothing specifically _Angular_ about services. Angular itself has no definition of a service. - There is no service base class, and no place to register a service. - - Yet services are fundamental to any Angular application. Our components are big consumers of services. - - We prefer our component classes lean. Our components don't fetch data from the server, - they don't validate user input, and they don't log directly to console. They delegate such tasks to services. - - A component's job is to enable the user experience and nothing more. It mediates between the view (rendered by the template) - and the application logic (which often includes some notion of a _model_). - A good component presents properties and methods for data binding. - It delegates everything nontrivial to services. - - Angular doesn't *enforce* these principles. - It won't complain if we write a "kitchen sink" component with 3000 lines. - - Angular does help us *follow* these principles by making it easy to factor our - application logic into services and make those services available to components through *dependency injection*. - -.l-main-section - -:marked - ## Dependency injection -figure - img(src="/resources/images/devguide/architecture/dependency-injection.png" alt="Service" style="float:left; width:200px; margin-left:-40px;margin-right:10px" ) -:marked - Dependency injection is a way to supply a new instance of a class - with the fully-formed dependencies it requires. Most dependencies are services. - Angular uses dependency injection to provide new components with the services they need. -
    -:marked - Angular can tell which services a component needs by looking at the types of its constructor parameters. - For example, the constructor of our `HeroListComponent` needs a `HeroService`: -+makeExample('architecture/dart/lib/hero_list_component.dart', 'ctor', 'lib/hero_list_component.dart (excerpt)')(format='.') -:marked - When Angular creates a component, it first asks an **injector** for - the services that the component requires. - - An injector maintains a container of service instances that it has previously created. - If a requested service instance is not in the container, the injector makes one and adds it to the container - before returning the service to Angular. - When all requested services have been resolved and returned, - Angular can call the component's constructor with those services as arguments. - This is what we mean by *dependency injection*. - - The process of `HeroService` injection looks a bit like this: -figure - img(src="/resources/images/devguide/architecture/injector-injects.png" alt="Service" ) -:marked - If the injector doesn't have a `HeroService`, how does it know how to make one? - - In brief, we must have previously registered a **provider** of the `HeroService` with the injector. - A provider is something that can create or return a service, typically the service class itself. - - We can register providers at any level of the application component tree. - We often do so at the root when we bootstrap the application so that - the same instance of a service is available everywhere. -+makeExample('architecture/dart/web/main.dart', 'bootstrap', 'web/main.dart (excerpt)')(format='.') -:marked - Alternatively, we might register at a component level: -+makeExample('architecture/dart/lib/hero_list_component.dart', 'providers', 'lib/hero_list_component.dart (excerpt)')(format='.') -:marked - Registering at a component level means we get a new instance of the - service with each new instance of that component. - - - - Points to remember about dependency injection: - - * Dependency injection is wired into the Angular framework and used everywhere. - - * The *injector* is the main mechanism. - * An injector maintains a *container* of service instances that it created. - * An injector can create a new service instance from a *provider*. - - * A *provider* is a recipe for creating a service. - - * We register *providers* with injectors. - - -.l-main-section -:marked - ## Other stuff - - We've learned just a bit about the seven main building blocks of an Angular application: - 1. [Components](#component) - 1. [Templates](#template) - 1. [Metadata](#metadata) - 1. [Data binding](#data-binding) - 1. [Directives](#directive) - 1. [Services](#service) - 1. [Dependency injection](#dependency-injection) - - That's a foundation for everything else in an Angular application, - and it's more than enough to get going. - But it doesn't include everything we'll need or want to know. - - Here is a brief, alphabetical list of other important Angular features and services. - Most of them are covered in this Developers Guide (or soon will be). - - >**Animations:** A forthcoming animation library makes it easy for developers to animate component behavior - without deep knowledge of animation techniques or CSS. - - >**Bootstrap:** A method to configure and launch the root application component. - - >**Change detection:** Learn how Angular decides that a component property value has changed and - when to update the screen. - Learn how it uses **zones** to intercept asynchronous activity and run its change detection strategies. - - >**Component router:** With the component Router service, users can navigate a multi-screen application - in a familiar web browsing style using URLs. - - >**Events:** The DOM raises events. So can components and services. Angular offers mechanisms for - publishing and subscribing to events including an implementation of the [RxJS Observable](https://github.com/zenparsing/es-observable) proposal. - - >**[Forms](forms.html):** Support complex data entry scenarios with HTML-based validation and dirty checking. - - >**HTTP:** Communicate with a server to get data, save data, and invoke server-side actions with this Angular HTTP client. - - >**Lifecycle hooks:** We can tap into key moments in the lifetime of a component, from its creation to its destruction, - by implementing the lifecycle hook interfaces. - - >**Pipes:** Services that transform values for display. - We can put pipes in our templates to improve the user experience. Consider - this `currency` pipe expression: -
    -code-example(language="javascript" linenumbers="."). - price | currency:'USD':true' -
    -:marked - >It displays a price of "42.33" as `$42.33`. - - >**Testing:** Angular provides a - [testing library](https://pub.dartlang.org/packages/angular2_testing) - to run unit tests on our application parts as they interact with the Angular framework. +block dart-bool + .callout.is-helpful + header Dart difference: Only true is true + :marked + In Dart, **the only value that is true is the boolean value `true`**; all + other values are false. JavaScript and TypeScript, in contrast, treat values + such as 1 and most non-null objects as true. For this reason, the JavaScript + and TypeScript versions of this app can use just `selectedHero` as the value + of the `*ngIf` expression. The Dart version must use a boolean operator such + as `!=` instead. diff --git a/public/docs/ts/latest/guide/architecture.jade b/public/docs/ts/latest/guide/architecture.jade index a341a79b26..915f3e52b8 100644 --- a/public/docs/ts/latest/guide/architecture.jade +++ b/public/docs/ts/latest/guide/architecture.jade @@ -1,190 +1,221 @@ -include ../_util-fns +block includes + include ../_util-fns + - var _library_module = 'library module' + - var _at_angular = '@angular' :marked - Angular 2 is a framework to help us build client applications in HTML and JavaScript. - - The framework consists of several cooperating libraries, some of them core and some optional. - - We write applications by composing HTML *templates* with Angularized-markup, - writing *component* classes to manage those templates, adding application logic in *services*, - and handing the top root component to Angular's *bootstrapper*. - - Angular takes over, presenting our application content in a browser and responding to user interactions - according to the instructions we provided. - - + Angular 2 is a framework to help us build client applications in HTML and + either JavaScript or a language (like Dart or TypeScript) that compiles to JavaScript. + +block angular-parts + :marked + The framework consists of several cooperating libraries, some of them core and some optional. + :marked - Of course there is more to it than this. We'll learn the details when we dive into the guide chapters. + With Angular, we write applications by composing HTML *templates* with Angularized-markup, + writing *component* classes to manage those templates, adding application logic in *services*, + and handing the top root component to Angular's *bootstrapper*. + + Angular takes over, presenting our application content in a browser and + responding to user interactions according to the instructions we provided. + + Of course there is more to it than this. + We'll learn the details when we dive into the guide chapters. Let's get the big picture first. figure img(src="/resources/images/devguide/architecture/overview2.png" alt="overview" style="margin-left:-40px;" width="700") + :marked The architecture diagram identifies the eight main building blocks of an Angular 2 application: - 1. [Module](#module) - 1. [Component](#component) - 1. [Template](#template) - 1. [Metadata](#metadata) - 1. [Data Binding](#data-binding) - 1. [Directive](#directive) - 1. [Service](#service) - 1. [Dependency Injection](#dependency-injection) - Learn these eight and we're on our way. + 1. [Modules](#modules) + 1. [Components](#components) + 1. [Templates](#templates) + 1. [Metadata](#metadata) + 1. [Data binding](#data-binding) + 1. [Directives](#directives) + 1. [Services](#services) + 1. [Dependency injection](#dependency-injection) + + Learn these, and we're on our way. .l-sub-section - :marked - The code referenced in this chapter is available as a [live example](/resources/live-examples/architecture/ts/plnkr.html). - + p The code referenced in this chapter is available as a #[+liveExampleLink2()]. + .l-main-section :marked - ## The Module + ## Modules figure img(src="/resources/images/devguide/architecture/module.png" alt="Component" align="left" style="width:240px; margin-left:-40px;margin-right:10px" ) :marked - Angular apps are modular. - + Angular apps are modular. + In general we assemble our application from many **modules**. - + A typical module is a cohesive block of code dedicated to a single purpose. A module **exports** something of value in that code, typically one thing such as a class.

    -.l-sub-section - :marked - ### Modules are optional - We highly recommend modular design. TypeScript has great support for ES2015 module syntax and our chapters assume we're taking a modular - approach using that syntax. That's why we list *Module* among the basic building blocks. - - Angular itself doesn't require a modular approach nor this particular syntax. Don't use it if you don't want it. - Each chapter has plenty to offer after you steer clear of the `import` and `export` statements. - - Find setup and organization clues in the JavaScript track (select it from the combo-box at the top of this page) - which demonstrates Angular 2 development with plain old JavaScript and no module system. + +block modules-in-dart + //- N/A + +block modules-are-optional + .l-sub-section + :marked + ### Modules are optional + We highly recommend modular design. TypeScript has great support for ES2015 module syntax and our chapters assume we're taking a modular + approach using that syntax. That's why we list *Module* among the basic building blocks. + + Angular itself doesn't require a modular approach nor this particular syntax. Don't use it if you don't want it. + Each chapter has plenty to offer after you steer clear of the `import` and `export` statements. + + Find setup and organization clues in the JavaScript track (select it from the combo-box at the top of this page) + which demonstrates Angular 2 development with plain old JavaScript and no module system. + +- var _app_comp_filename = _docsFor == 'dart' ? 'app_component.dart' : 'app.component.ts'; :marked - Perhaps the first module we meet is a module that exports a *component* class. + Perhaps the first module we meet is a module that exports a *component* class. The component is one of the basic Angular blocks, we write a lot of them, and we'll talk about components in the next segment. For the moment it is enough to know that a component class is the kind of thing we'd export from a module. - - Most applications have an `AppComponent`. By convention, we'll find it in a file named `app.component.ts`. - Look inside such a file and we'll see an `export` statement like this one. -+makeExample('architecture/ts/app/app.component.ts', 'export', 'app/app.component.ts (excerpt)')(format=".") + + Most applications have an `AppComponent`. By convention, we'll find it in a file named `!{_app_comp_filename}`. + Look inside such a file and we'll see a declaration such as this one. + ++makeExcerpt('app/app.component.ts ()', 'export') + +block export-qualifier + :marked + The `export` statement tells TypeScript that this is a module whose + `AppComponent` class is public and accessible to other modules of the application. + :marked - The `export` statement tells TypeScript that this is a module whose - `AppComponent` class is public and accessible to other modules of the application. - When we need a reference to the `AppComponent`, we **import** it like this: -+makeExample('architecture/ts/app/main.ts', 'import', 'app/main.ts (excerpt)')(format=".") + ++makeExcerpt('app/main.ts', 'import') + +block ts-import + :marked + The `import` statement tells the system it can get an `AppComponent` from a module named `app.component` + located in a neighboring file. + The **module name** (AKA module id) is often the same as the filename without its extension. + :marked - The `import` statement tells the system it can get an `AppComponent` from a module named `app.component` - located in a neighboring file. - The **module name** (AKA module id) is often the same as the filename without its extension. - ### Library Modules + ### Libraries + figure img(src="/resources/images/devguide/architecture/library-module.png" alt="Component" align="left" style="width:240px; margin-left:-40px;margin-right:10px" ) -:marked - Some modules are libraries of other modules. - - Angular itself ships as a collection of library modules within several npm packages. - Their names begin with the `@angular` prefix. - Each Angular library contains a [barrel](../glossary.html#barrel) module - that is actually a public façade over several logically-related private modules. - - The `@angular/core` library is the primary Angular library module from which we get most of what we need. -
    - - There are other important Angular library modules too such as `@angular/common`, `@angular/router`, and `@angular/http`. - We import what we need from an Angular library module in much the same way. - For example, we import the Angular **`Component` *function*** from the *@angular/core* module like this: -+makeExample('architecture/ts/app/app.component.ts', 'import')(format=".") -:marked - Compare that syntax to our previous import of `AppComponent`. -+makeExample('architecture/ts/app/main.ts', 'import')(format=".") -:marked - Notice the difference? - In the first case, when importing from an Angular library module, - the import statement refers to the bare module name, `@angular/core`, *without a path prefix*. - - When we import from one of *our* own files, we prefix the module name with the file path. - In this example we specify a relative file path (./). That means the - source module is in the same folder (./) as the module importing it. - We could path up and around the application folder structure if the source module were somewhere else. -.l-sub-section +block angular-library-modules :marked - We import and export in the ECMAScript 2015 (ES2015) module syntax. - Learn more about that syntax [here](http://www.2ality.com/2014/09/es6-modules-final.html) - and many other places on the web. - - The infrastructure *behind* module loading and importing is an important subject. - But it's a subject outside the scope of this introduction to Angular. - While we're focused on our application, *import* and *export* - is about all we need to know. + Some modules are _libraries_ of other modules. + Angular itself ships as a collection of library modules within several npm packages. + Their names begin with the `!{_at_angular}` prefix. + + Each Angular library contains a [barrel](../glossary.html#barrel) module + that is actually a public façade over several logically-related private modules. + +:marked + `!{_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}/animate`. + We import what we need from an Angular !{_library_module}. + +block angular-imports + :marked + For example, we import the Angular **`Component` *function*** from `@angular/core` like this: + +makeExcerpt('app/app.component.ts', 'import') + :marked + Compare that syntax to our previous import of `AppComponent`. + +makeExcerpt('app/main.ts', 'import') + + :marked + Notice the difference? + In the first case, when importing from an Angular library module, + the import statement refers to the bare module name, `@angular/core`, *without a path prefix*. + + When we import from one of *our* own files, we prefix the module name with the file path. + In this example we specify a relative file path (`./`). That means the + source module is in the same folder (`./`) as the module importing it. + We could path up and around the application folder structure if the source module were somewhere else. + .l-sub-section + :marked + We import and export in the ECMAScript 2015 (ES2015) module syntax. + Learn more about that syntax [here](http://www.2ality.com/2014/09/es6-modules-final.html) + and many other places on the web. + + The infrastructure *behind* module loading and importing is an important subject. + But it's a subject outside the scope of this introduction to Angular. + While we're focused on our application, *import* and *export* + is about all we need to know. + +- var _export = _docsFor == 'dart' ? 'publicly declare' : 'export'; +- var _declare = _docsFor == 'dart' ? 'declare' : 'export'; :marked The key take-aways are: * Angular apps are composed of modules. - * Modules export things — classes, function, values — that other modules import. + * Modules !{_export} things — classes, function, values — that other modules import. * We prefer to write our application as a collection of modules, each module exporting one thing. - - The first module we write will most likely export a component. + + The first module we write will most likely !{_declare} a component. + .l-main-section - :marked - ## The Component + ## Components figure img(src="/resources/images/devguide/architecture/hero-component.png" alt="Component" align="left" style="width:200px; margin-left:-40px;margin-right:10px" ) -:marked - A **Component** controls a patch of screen real estate that we could call a *view*. - The shell at the application root with navigation links, that list of heroes, the hero editor ... - they're all views controlled by Components. - - We define a Component's application logic - what it does to support the view - inside a class. - The class interacts with the view through an API of properties and methods. - - - A `HeroListComponent`, for example, might have a `heroes` property that returns an array of heroes - that it acquired from a service. - It might have a `selectHero()` method that sets a `selectedHero` property when the user clicks on a hero from that list. - It might be a class like this: -+makeExample('architecture/ts/app/hero-list.component.ts', 'class', 'app/hero-list.component.ts') +:marked + A **component** controls a patch of screen real estate that we could call a *view*. + The shell at the application root with navigation links, a list of heroes, a hero editor ... + they're all views controlled by components. + + We define a component's application logic — what it does to support the view — inside a class. + The class interacts with the view through an API of properties and methods. + + + A `HeroListComponent`, for example, might have a `heroes` property that returns !{_an} !{_array} of heroes + that it acquired from a service. + It might have a `selectHero()` method that sets a `selectedHero` property when the user clicks to choose a hero from that list. + The component might be a class like this: + ++makeExcerpt('app/hero-list.component.ts', 'class') :marked Angular creates, updates, and destroys components as the user moves through the application. - The developer can take action at each moment in this lifecycle through optional [Lifecycle Hooks](lifecycle-hooks.html). + The developer can take action at each moment in this lifecycle through optional [lifecycle hooks](lifecycle-hooks.html), like `ngOnInit()` declared above. .l-sub-section :marked - We're not showing those hooks in this example - but we are making a mental note to find out about them later. - - We may wonder who is calling that constructor? Who provides the service parameter? + We may wonder who is calling the component's constructor? Who provides the service parameter? For the moment, have faith that Angular will call the constructor and deliver an appropriate `HeroService` when we need it. .l-main-section - :marked - ## The Template + ## Templates figure img(src="/resources/images/devguide/architecture/template.png" alt="Template" align="left" style="width:200px; margin-left:-40px;margin-right:10px" ) :marked - We define a Component's view with its companion **template**. A template is a form of HTML - that tells Angular how to render the Component. + We define a component's view with its companion **template**. A template is a form of HTML + that tells Angular how to render the component. A template looks like regular HTML much of the time ... and then it gets a bit strange. Here is a - template for our `HeroList` component. -+makeExample('architecture/ts/app/hero-list.component.html',null,'app/hero-list.component.html') + template for our `HeroListComponent`: + ++makeExample('app/hero-list.component.html') + :marked - We recognize `

    ` and `
    `. - But there's other markup that no one told us about in school. - What are `*ngFor`, `{{hero.name}}`, `(click)`, `[hero]`, and ``? - - These are examples of Angular's [template syntax](template-syntax.html). + This template features typical HTML elements like `

    ` and `

    `. + But what are `*ngFor`, `{{hero.name}}`, `(click)`, `[hero]`, and ``? + + These are examples of Angular's [template syntax](template-syntax.html). We will grow accustomed to that syntax and may even learn to love it. We'll begin to explain it in a moment. - - Before we do, focus attention on the last line. + + Before we do, focus attention on the last line. The `` tag is a custom element representing the `HeroDetailComponent`. - + The `HeroDetailComponent` is a *different* component than the `HeroListComponent` we've been reviewing. The `HeroDetailComponent` (code not shown) presents facts about a particular hero, the hero that the user selects from the list presented by the `HeroListComponent`. @@ -193,196 +224,207 @@ figure figure img(src="/resources/images/devguide/architecture/component-tree.png" alt="Metadata" align="left" style="width:300px; margin-left:-40px;margin-right:10px" ) :marked - Notice how `` rests comfortably among the HTML elements we already know. - We can mix ... and will mix ... our custom components with native HTML in the same layouts. - - And in this manner we can and will compose complex component trees to build out our richly featured application. + Notice how `` rests comfortably among native HTML elements. + We can and _will_ mix our custom components with native HTML in the same layouts. + + In this manner we'll compose complex component trees to build out our richly featured application.
    .l-main-section - :marked - ## Angular Metadata + ## Metadata figure img(src="/resources/images/devguide/architecture/metadata.png" alt="Metadata" align="left" style="width:150px; margin-left:-40px;margin-right:10px" ) + :marked

    Metadata tells Angular how to process a class.


    :marked - [Looking back](#component-code) at the `HeroListComponent`, we see that it's just a class. + [Looking back at the code](#component-code) for `HeroListComponent`, we see that it's just a class. There is no evidence of a framework, no "Angular" in it at all. - + In fact, it really is *just a class*. It's not a component until we *tell Angular about it*. - + We tell Angular that `HeroListComponent` is a component by attaching **metadata** to the class. - - The easy way to attach metadata in TypeScript is with a **decorator**. + + In !{_Lang}, we attach metadata by using !{_a} **!{_decorator}**. Here's some metadata for `HeroListComponent`: -+makeExample('architecture/ts/app/hero-list.component.ts', 'metadata', 'app/hero-list.component.ts (metadata)') + ++makeExcerpt('app/hero-list.component.ts', 'metadata') + :marked - Here we see the `@Component` decorator which (no surprise) identifies the class - immediately below it as a Component class. - - A decorator is a function. Decorators often have a configuration parameter. - The `@Component` decorator takes a required configuration object with the - information Angular needs to create and present the component and its view. - - Here we see a few of the possible `@Component` configuration options: - - * `selector` - a css selector that tells Angular to create and insert an instance of this component - where it finds a `` tag in *parent* HTML. - If the template of the application shell (a Component) contained -
    -code-example(language="html"). - <hero-list></hero-list> -
    + Here we see the `@Component` !{_decorator} which (no surprise) identifies the class + immediately below it as a component class. + +block ts-decorator + :marked + A decorator is a function. Decorators often have a configuration parameter. + The `@Component` decorator takes a required configuration object with the + information Angular needs to create and present the component and its view. + + Here are a few of the possible `@Component` configuration options: + :marked - >Angular inserts an instance of the `HeroListComponent` view between those tags. - - * `templateUrl` - the address of this component's template which we showed [above](#template). - - * `directives` - an array of the Components or Directives that *this* template requires. + - `selector`: CSS selector that tells Angular to create and insert an instance of this component + where it finds a `` tag in *parent* HTML. + For example, if an app's HTML contains ``, then + Angular inserts an instance of the `HeroListComponent` view between those tags. + + - `templateUrl`: address of this component's template, which we showed [above](#templates). + + - `directives`: !{_array} of the components or directives that *this* template requires. We saw in the last line of our template that we expect Angular to insert a `HeroDetailComponent` - in the space indicated by `` tags. - Angular will do so only if we mention the `HeroDetailComponent` in this `directives` array. - - * `providers` - an array of **dependency injection providers** for services that the component requires. - This is one way to tell Angular that our component's constructor requires a `HeroService` - so it can get the list of heroes to display. We'll get to dependency injection in a moment. + in the space indicated by `` tags. + Angular will do so only if we mention the `HeroDetailComponent` in this `directives` !{_array}. + + - `providers`: !{_array} of **dependency injection providers** for services that the component requires. + This is one way to tell Angular that our component's constructor requires a `HeroService` + so it can get the list of heroes to display. We'll get to dependency injection later. + figure img(src="/resources/images/devguide/architecture/template-metadata-component.png" alt="Metadata" align="left" style="height:200px; margin-left:-40px;margin-right:10px" ) -:marked - The `@Component` function takes the configuration object and turns it into metadata that it attaches - to the component class definition. Angular discovers this metadata at runtime and thus knows how to do "the right thing". - - The template, metadata, and component together describe the view. - We apply other metadata decorators in a similar fashion to guide Angular behavior. - The `@Injectable`, `@Input`, `@Output`, `@RouterConfig` are a few of the more popular decorators +:marked + Angular reads the metadata specified by the `@Component` + annotation. That's how Angular learns to do "the right thing". + + The template, metadata, and component together describe a view. + + We apply other metadata !{_decorator}s in a similar fashion to guide Angular behavior. + `@Injectable`, `@Input`, and `@Output` are a few of the more popular !{_decorator}s we'll master as our Angular knowledge grows.
    :marked - The architectural take-away is that we must add metadata to our code + The architectural takeaway is that we must add metadata to our code so that Angular knows what to do. .l-main-section - :marked - ## Data Binding + ## Data binding Without a framework, we would be responsible for pushing data values into the HTML controls and turning user responses - into actions and value updates. Writing such push/pull logic by hand is tedious, error-prone and a nightmare to - read as the experienced jQuery programmer can attest. + into actions and value updates. Writing such push/pull logic by hand is tedious, error-prone, and a nightmare to + read as any experienced jQuery programmer can attest. figure img(src="/resources/images/devguide/architecture/databinding.png" alt="Data Binding" style="width:220px; float:left; margin-left:-40px;margin-right:20px" ) :marked - Angular supports **data binding**, + Angular supports **data binding**, a mechanism for coordinating parts of a template with parts of a component. We add binding markup to the template HTML to tell Angular how to connect both sides. - - There are four forms of data binding syntax. Each form has a direction - to the DOM, from the DOM, or in both directions - + + There are four forms of data binding syntax. Each form has a direction — to the DOM, from the DOM, or in both directions — as indicated by the arrows in the diagram.
    :marked - We saw three forms of data binding in our [example](#template) template: -+makeExample('architecture/ts/app/hero-list.component.1.html', 'binding', 'app/hero-list.component.html (excerpt)')(format=".") + We saw three forms of data binding in our [example](#templates) template: + ++makeExcerpt('app/hero-list.component.1.html', 'binding') + :marked - * The `{{hero.name}}` [*interpolation*](displaying-data.html#interpolation) - displays the component's `hero.name` property value within the `
    ` tags. - - * The `[hero]` [*property binding*](template-syntax.html#property-binding) passes the `selectedHero` from + * The `{{hero.name}}` [*interpolation*](displaying-data.html#interpolation) + displays the component's `hero.name` property value within the `
  • ` tags. + + * The `[hero]` [*property binding*](template-syntax.html#property-binding) passes the value of `selectedHero` from the parent `HeroListComponent` to the `hero` property of the child `HeroDetailComponent`. - - * The `(click)` [*event binding*](user-input.html#click) calls the Component's `selectHero` method when the user clicks - on a hero's name + + * The `(click)` [*event binding*](user-input.html#click) calls the component's `selectHero` method when the user clicks a hero's name. **Two-way data binding** is an important fourth form - that combines property and event binding in a single notation using the `ngModel` directive. - We didn't have a two-way binding in the `HeroListComponent` template; - here's an example from the `HeroDetailComponent` template (not shown): + that combines property and event binding in a single notation, using the `ngModel` directive. + We didn't have a two-way binding in the `HeroListComponent` template; + here's an example from the `HeroDetailComponent` template: + ++makeExcerpt('app/hero-detail.component.html', 'ngModel') -+makeExample('architecture/ts/app/hero-detail.component.html', 'ngModel')(format=".") :marked In two-way binding, a data property value flows to the input box from the component as with property binding. The user's changes also flow back to the component, resetting the property to the latest value, as with event binding. - - Angular processes *all* data bindings once per JavaScript event cycle, - depth-first from the root of the application component tree. + + Angular processes *all* data bindings once per JavaScript event cycle, + from the root of the application component tree down to the leaves. + figure img(src="/resources/images/devguide/architecture/component-databinding.png" alt="Data Binding" style="float:left; width:300px; margin-left:-40px;margin-right:10px" ) :marked - We don't know all the details yet - but it's clear from these examples that data binding plays an important role in communication - between a template and its component ... -
    + We don't know all the details yet, + but it's clear from these examples that data binding plays an important role in communication + between a template and its component. +
    figure img(src="/resources/images/devguide/architecture/parent-child-binding.png" alt="Parent/Child binding" style="float:left; width:300px; margin-left:-40px;margin-right:10px" ) :marked - ... ***and*** between parent and child components + Data binding is also important for communication between parent and child components.
    .l-main-section - :marked - ## The Directive + ## Directives figure img(src="/resources/images/devguide/architecture/directive.png" alt="Parent child" style="float:left; width:150px; margin-left:-40px;margin-right:10px" ) :marked - Our Angular templates are *dynamic*. When Angular renders them, it transforms the DOM - according to the instructions given by a **directive**. - - A directive is a class with directive metadata. In TypeScript we'd apply the `@Directive` decorator + Angular templates are *dynamic*. When Angular renders them, it transforms the DOM + according to the instructions given by **directives**. + + A directive is a class with directive metadata. In !{_Lang} we apply the `@Directive` !{_decorator} to attach metadata to the class.
    :marked - We already met one form of directive: the component. A component is a *directive-with-a-template* - and the `@Component` decorator is actually a `@Directive` decorator extended with template-oriented features. + We already met one form of directive: the component. A component is a *directive-with-a-template*; + a `@Component` !{_decorator} is actually a `@Directive` !{_decorator} extended with template-oriented features. .l-sub-section :marked - While the **component is technically a directive**, - it is so distinctive and central to Angular applications that we chose - to separate the component from the directive in our architectural overview. + While **a component is technically a directive**, + components are so distinctive and central to Angular applications that we chose + to separate components from directives in this architectural overview. :marked - There are two *other* kinds of directives as well that we call "structural" and "attribute" directives. - - They tend to appear within an element tag like attributes, + Two *other* kinds of directives exist: _structural_ and _attribute_ directives. + + They tend to appear within an element tag as attributes do, sometimes by name but more often as the target of an assignment or a binding. - + **Structural** directives alter layout by adding, removing, and replacing elements in DOM. - - We see two built-in structural directives at play in our [example](#template) template: -+makeExample('architecture/ts/app/hero-list.component.1.html', 'structural')(format=".") + + Our [example](#templates) template uses two built-in structural directives: + ++makeExcerpt('app/hero-list.component.1.html', 'structural') + :marked - * [`*ngFor`](displaying-data.html#ngFor) tells Angular to stamp out one `
    ` per hero in the `heroes` list. + * [`*ngFor`](displaying-data.html#ngFor) tells Angular to stamp out one `
  • ` per hero in the `heroes` list. * [`*ngIf`](displaying-data.html#ngIf) includes the `HeroDetail` component only if a selected hero exists. - - **Attribute** directives alter the appearance or behavior of an existing element. - In templates they look like regular HTML attributes, hence the name. - - The `ngModel` directive, which implements two-way data binding, is an example of an attribute directive. -+makeExample('architecture/ts/app/hero-detail.component.html', 'ngModel')(format=".") + +block dart-bool + //- N/A + :marked - It modifies the behavior of an existing element (typically an ``) + **Attribute** directives alter the appearance or behavior of an existing element. + In templates they look like regular HTML attributes, hence the name. + + The `ngModel` directive, which implements two-way data binding, is + an example of an attribute directive. `ngModel` modifies the behavior of + an existing element (typically an ``) by setting its display value property and responding to change events. - - Angular ships with a few other directives that either alter the layout structure - (e.g. [ngSwitch](template-syntax.html#ngSwitch)) - or modify aspects of DOM elements and components - (e.g. [ngStyle](template-syntax.html#ngStyle) and [ngClass](template-syntax.html#ngClass)). - - And of course we can write our own directives. + ++makeExcerpt('app/hero-detail.component.html', 'ngModel') +:marked + Angular ships with a small number of other directives that either alter the layout structure + (for example, [ngSwitch](template-syntax.html#ngSwitch)) + or modify aspects of DOM elements and components + (for example, [ngStyle](template-syntax.html#ngStyle) and [ngClass](template-syntax.html#ngClass)). + + Of course, we can also write our own directives. Components such as + `HeroListComponent` are one kind of custom directive. + .l-main-section - :marked - ## The Service + ## Services figure img(src="/resources/images/devguide/architecture/service.png" alt="Service" style="float:left; margin-left:-40px;margin-right:10px" ) :marked - "Service" is a broad category encompassing any value, function or feature that our application needs. - - Almost anything can be a service. + _Service_ is a broad category encompassing any value, function, or feature that our application needs. + + Almost anything can be a service. A service is typically a class with a narrow, well-defined purpose. It should do something specific and do it well.
    :marked @@ -392,151 +434,163 @@ figure * message bus * tax calculator * application configuration - - There is nothing specifically *Angular* about services. Angular itself has no definition of a *service*. - There is no *ServiceBase* class. - - Yet services are fundamental to any Angular application. - + + There is nothing specifically _Angular_ about services. Angular itself has no definition of a service. + There is no service base class, and no place to register a service. + + Yet services are fundamental to any Angular application. Our components are big consumers of services. + Here's an example of a service class that logs to the browser console -+makeExample('architecture/ts/app/logger.service.ts', 'class', 'app/logger.service.ts (class only)')(format=".") + ++makeExcerpt('app/logger.service.ts', 'class') + :marked - Here's a `HeroService` that fetches heroes and returns them in a resolved [promise](http://exploringjs.com/es6/ch_promises.html). + Here's a `HeroService` that fetches heroes and returns them in a resolved !{_PromiseLinked}. The `HeroService` depends on the `Logger` service and another `BackendService` that handles the server communication grunt work. -+makeExample('architecture/ts/app/hero.service.ts', 'class', 'app/hero.service.ts (class only)')(format=".") + ++makeExcerpt('app/hero.service.ts', 'class') + :marked - Services are everywhere. + Services are everywhere. - Our components are big consumers of services. They depend upon services to handle most chores. - They don't fetch data from the server, they don't validate user input, they don't log directly to the console. + We prefer our component classes lean. Our components don't fetch data from the server, + they don't validate user input, and they don't log directly to the console. They delegate such tasks to services. - - A component's job is to enable the user experience and nothing more. It mediates between the view (rendered by the template) - and the application logic (which often includes some notion of a "model"). A good component presents - properties and methods for data binding. It delegates everything non-trivial to services. - Angular doesn't *enforce* these principles. + A component's job is to enable the user experience and nothing more. It mediates between the view (rendered by the template) + and the application logic (which often includes some notion of a _model_). + A good component presents properties and methods for data binding. + It delegates everything nontrivial to services. + + Angular doesn't *enforce* these principles. It won't complain if we write a "kitchen sink" component with 3000 lines. - + Angular does help us *follow* these principles by making it easy to factor our application logic into services and make those services available to components through *dependency injection*. .l-main-section - :marked - ## Dependency Injection + ## Dependency injection figure img(src="/resources/images/devguide/architecture/dependency-injection.png" alt="Service" style="float:left; width:200px; margin-left:-40px;margin-right:10px" ) :marked - "Dependency Injection" is a way to supply a new instance of a class + _Dependency injection_ is a way to supply a new instance of a class with the fully-formed dependencies it requires. Most dependencies are services. Angular uses dependency injection to provide new components with the services they need.
    :marked - In TypeScript, Angular can tell which services a component needs by looking at the types of its constructor parameters. - For example, the constructor of our `HeroListComponent` needs the `HeroService`: -+makeExample('architecture/ts/app/hero-list.component.ts', 'ctor', 'app/hero-list.component (constructor)')(format=".") + Angular can tell which services a component needs by looking at the types of its constructor parameters. + For example, the constructor of our `HeroListComponent` needs a `HeroService`: + ++makeExcerpt('app/hero-list.component.ts (constructor)', 'ctor') + :marked - When Angular creates a component, it first asks an **Injector** for - the services that the component requires. - - An `Injector` maintains a container of service instances that it has previously created. + When Angular creates a component, it first asks an **injector** for + the services that the component requires. + + An injector maintains a container of service instances that it has previously created. If a requested service instance is not in the container, the injector makes one and adds it to the container - before returning the service to Angular. - When all requested services have been resolved and returned, + before returning the service to Angular. + When all requested services have been resolved and returned, Angular can call the component's constructor with those services as arguments. This is what we mean by *dependency injection*. - + The process of `HeroService` injection looks a bit like this: figure img(src="/resources/images/devguide/architecture/injector-injects.png" alt="Service" ) :marked - If the `Injector` doesn't have a `HeroService`, how does it know how to make one? - - In brief, we must have previously registered a **provider** of the `HeroService` with the `Injector`. + If the injector doesn't have a `HeroService`, how does it know how to make one? + + In brief, we must have previously registered a **provider** of the `HeroService` with the injector. A provider is something that can create or return a service, typically the service class itself. - + We can register providers at any level of the application component tree. We often do so at the root when we bootstrap the application so that the same instance of a service is available everywhere. -+makeExample('architecture/ts/app/main.ts', 'bootstrap','app/main.ts (excerpt)')(format=".") -:marked - Alternatively, we might register at a component level ... -+makeExample('architecture/ts/app/hero-list.component.ts', 'providers','app/hero-list.component.ts (excerpt)')(format=".") -:marked - ... in which case we get a new instance of the - service with each new instance of that component. - We've vastly over-simplified dependency injection for this overview. - We can learn the full story in the [Dependency Injection](dependency-injection.html) chapter. - - The points to remember are: - * dependency injection is wired into the framework and used everywhere.

    - * the `Injector` is the main mechanism. - * an injector maintains a *container* of service instances that it created. - * an injector can create a new service instance using a *provider*. - * a *provider* is a recipe for creating a service. - - * we register *providers* with injectors. ++makeExcerpt('app/main.ts', 'bootstrap') + +:marked + Alternatively, we might register at a component level, in the providers property of the `@Component` metadata: + ++makeExcerpt('app/hero-list.component.ts', 'providers') + +:marked + Registering at a component level means we get a new instance of the + service with each new instance of that component. + + + + Points to remember about dependency injection: + + * Dependency injection is wired into the Angular framework and used everywhere. + + * The *injector* is the main mechanism. + * An injector maintains a *container* of service instances that it created. + * An injector can create a new service instance from a *provider*. + + * A *provider* is a recipe for creating a service. + + * We register *providers* with injectors. - .l-main-section :marked ## Wrap up - We've learned just a bit about the eight main building blocks of an Angular application - - 1. [Module](#module) - 1. [Component](#component) - 1. [Template](#template) + + We've learned just a bit about the eight main building blocks of an Angular application: + + 1. [Modules](#modules) + 1. [Components](#components) + 1. [Templates](#templates) 1. [Metadata](#metadata) - 1. [Data Binding](#data-binding) - 1. [Directive](#directive) - 1. [Service](#service) - 1. [Dependency Injection](#dependency-injection) - - That's a foundation for everything else in an Angular application + 1. [Data binding](#data-binding) + 1. [Directives](#directives) + 1. [Services](#services) + 1. [Dependency injection](#dependency-injection) + + That's a foundation for everything else in an Angular application, and it's more than enough to get going. But it doesn't include everything we'll need or want to know. - - -.l-main-section -:marked - ## The Other Stuff - - Here is a brief, alphabetical list of other important Angular features and services. - Most of them are covered in this Developers Guide (or soon will be): - - >**Animations** - A forthcoming animation library makes it easy for developers to animate component behavior - without deep knowledge of animation techniques or css. - - >**Bootstrap** - A method to configure and launch the root application component. - - >**Change Detection** - Learn how Angular decides that a component property value has changed and - when to update the screen. - Learn how it uses **zones** to intercept asynchronous activity and run its change detection strategies. - - >**[Component Router](router.html)** - With the Component Router service, users can navigate a multi-screen application + + Here is a brief, alphabetical list of other important Angular features and services. + Most of them are covered in this Developers Guide (or soon will be). + + > [**Animations**](animations.html): The animation library makes it easy for developers to animate component behavior + without deep knowledge of animation techniques or CSS. + + > **Bootstrap**: A method to configure and launch the root application component. + + > **Change detection**: Learn how Angular decides that a component property value has changed and + when to update the screen. + Learn how it uses **zones** to intercept asynchronous activity and run its change detection strategies. + + > **Component router**: With the component Router service, users can navigate a multi-screen application in a familiar web browsing style using URLs. - - >**Events** - The DOM raises events. So can components and services. Angular offers mechanisms for - publishing and subscribing to events including an implementation of the [RxJS Observable](https://github.com/zenparsing/es-observable) proposal. - - >**[Forms](forms.html)** - Support complex data entry scenarios with HTML-based validation and dirty checking. - - >**[HTTP](server-communication.html)** - Communicate with a server to get data, save data, and invoke server-side actions with this Angular HTTP client. - - >**[Lifecycle Hooks](lifecycle-hooks.html)** - We can tap into key moments in the lifetime of a component, from its creation to its destruction, - by implementing the "Lifecycle Hook" interfaces. - - >**[Pipes](pipes.html)** - Services that transform values for display. - We can put pipes in our templates to improve the user experience. For example, - this `currency` pipe expression, + + > **Events**: The DOM raises events. So can components and services. Angular offers mechanisms for + publishing and subscribing to events. + + > [**Forms**](forms.html): Support complex data entry scenarios with HTML-based validation and dirty checking. + + > [**HTTP**](server-communication.html): Communicate with a server to get data, save data, and invoke server-side actions with an HTTP client. + + > [**Lifecycle hooks**](lifecycle-hooks.html): We can tap into key moments in the lifetime of a component, from its creation to its destruction, + by implementing the lifecycle hook interfaces. + + > [**Pipes**](pipes.html): Services that transform values for display. + We can put pipes in our templates to improve the user experience. Consider + this `currency` pipe expression:
    -code-example(language="javascript" linenumbers="."). +code-example(). price | currency:'USD':true
    :marked - >displays a price of "42.33" as `$42.33`. - - >**[Testing](testing.html)** - Angular provides a testing library for "unit testing" our application parts as they - interact with the Angular framework. + > It displays a price of "42.33" as `$42.33`. + + > [**Router**](router.html): Navigate from page to page within the client + application and never leave the browser. + + > [**Testing**](testing.html): Angular provides a + [testing library](https://pub.dartlang.org/packages/angular2_testing) + to run unit tests on our application parts as they interact with the Angular framework. From 51044705580b7c472685334ec04ff78dfc30ba93 Mon Sep 17 00:00:00 2001 From: Brandon Roberts Date: Tue, 5 Jul 2016 21:20:33 -0500 Subject: [PATCH 05/25] docs(router): Removed refs to deprecated router; lowerCamelCase constants closes #1834 --- .../ts/app/app.component.html | 2 +- .../ts/app/app.component.ts | 7 +- .../ts/app/app.routes.ts | 13 ++ .../cb-a1-a2-quick-reference/ts/app/main.1.ts | 5 + .../cb-a1-a2-quick-reference/ts/app/main.ts | 6 +- .../ts/app/movie-list.component.ts | 1 - .../ts/app/app.routes.ts | 7 + .../cb-dependency-injection/ts/app/main.ts | 8 +- .../router/ts/app/app.component.5.ts | 42 ---- .../_examples/router/ts/app/app.routes.1.ts | 2 +- .../_examples/router/ts/app/app.routes.2.ts | 2 +- .../style-guide/ts/app/app.routes.ts | 2 +- .../docs/_examples/style-guide/ts/app/main.ts | 4 +- .../_examples/toh-5/ts/app/app.routes.1.ts | 4 +- .../_examples/toh-5/ts/app/app.routes.2.ts | 2 +- .../docs/_examples/toh-5/ts/app/app.routes.ts | 4 +- public/docs/_examples/toh-5/ts/app/main.ts | 4 +- .../docs/_examples/toh-6/ts/app/app.routes.ts | 4 +- public/docs/_examples/toh-6/ts/app/main.ts | 6 +- .../cookbook/a1-a2-quick-reference.jade | 218 +++++++++--------- public/docs/ts/latest/guide/router.jade | 28 +-- public/docs/ts/latest/tutorial/toh-pt5.jade | 2 +- 22 files changed, 177 insertions(+), 196 deletions(-) create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.routes.ts create mode 100644 public/docs/_examples/cb-a1-a2-quick-reference/ts/app/main.1.ts create mode 100644 public/docs/_examples/cb-dependency-injection/ts/app/app.routes.ts delete mode 100644 public/docs/_examples/router/ts/app/app.component.5.ts diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.html b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.html index 9626afd5cb..72fd3de86f 100644 --- a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.html +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.html @@ -4,7 +4,7 @@

    Routed Movies

    diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.ts b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.ts index f2ca099297..cdb9d9fd81 100644 --- a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.ts +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.component.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core'; -import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/router-deprecated'; +import { ROUTER_DIRECTIVES } from '@angular/router'; import { MovieListComponent } from './movie-list.component'; import { MovieService } from './movie.service'; @@ -12,11 +12,8 @@ import { StringSafeDatePipe } from './date.pipe'; styleUrls: ['app/app.component.css'], directives: [MovieListComponent, ROUTER_DIRECTIVES], pipes: [StringSafeDatePipe], - providers: [MovieService, ROUTER_PROVIDERS] + providers: [MovieService] }) -@RouteConfig([ - {path: '/movies', name: 'Movies', component: MovieListComponent, useAsDefault: true} -]) export class AppComponent { angularDocsUrl = 'https://angular.io/'; diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.routes.ts b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.routes.ts new file mode 100644 index 0000000000..1fd2627996 --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/app.routes.ts @@ -0,0 +1,13 @@ +// #docregion +import { provideRouter, RouterConfig } from '@angular/router'; + +import { MovieListComponent } from './movie-list.component'; + +const routes: RouterConfig = [ + { path: '', redirectTo: '/movies', pathMatch: 'full' }, + { path: 'movies', component: MovieListComponent } +]; + +export const appRouterProviders = [ + provideRouter(routes) +]; diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/main.1.ts b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/main.1.ts new file mode 100644 index 0000000000..67de525937 --- /dev/null +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/main.1.ts @@ -0,0 +1,5 @@ +// #docregion +import { bootstrap } from '@angular/platform-browser-dynamic'; +import { AppComponent } from './app.component'; + +bootstrap(AppComponent); diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/main.ts b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/main.ts index 52b47899ef..7a1d58fad8 100644 --- a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/main.ts +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/main.ts @@ -1,6 +1,8 @@ // #docregion import { bootstrap } from '@angular/platform-browser-dynamic'; - import { AppComponent } from './app.component'; +import { appRouterProviders } from './app.routes'; -bootstrap(AppComponent); +bootstrap(AppComponent, [ + appRouterProviders +]); diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.ts b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.ts index 4157d8aa3a..67b0c2873d 100644 --- a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.ts +++ b/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie-list.component.ts @@ -2,7 +2,6 @@ // #docplaster // #docregion import import { Component } from '@angular/core'; -import { ROUTER_DIRECTIVES } from '@angular/router-deprecated'; // #enddocregion import import { MovieService } from './movie.service'; import { IMovie } from './movie'; diff --git a/public/docs/_examples/cb-dependency-injection/ts/app/app.routes.ts b/public/docs/_examples/cb-dependency-injection/ts/app/app.routes.ts new file mode 100644 index 0000000000..c8eb6ee683 --- /dev/null +++ b/public/docs/_examples/cb-dependency-injection/ts/app/app.routes.ts @@ -0,0 +1,7 @@ +import { provideRouter, RouterConfig } from '@angular/router'; + +const routes: RouterConfig = []; + +export const appRouterProviders = [ + provideRouter(routes) +]; diff --git a/public/docs/_examples/cb-dependency-injection/ts/app/main.ts b/public/docs/_examples/cb-dependency-injection/ts/app/main.ts index fd4646a055..c83f329e91 100644 --- a/public/docs/_examples/cb-dependency-injection/ts/app/main.ts +++ b/public/docs/_examples/cb-dependency-injection/ts/app/main.ts @@ -1,7 +1,7 @@ // #docregion -import { bootstrap } from '@angular/platform-browser-dynamic'; -import { XHRBackend } from '@angular/http'; -import { ROUTER_PROVIDERS } from '@angular/router-deprecated'; +import { bootstrap } from '@angular/platform-browser-dynamic'; +import { XHRBackend } from '@angular/http'; +import { appRouterProviders } from './app.routes'; import { LocationStrategy, HashLocationStrategy } from '@angular/common'; @@ -13,7 +13,7 @@ import { AppComponent } from './app.component'; // #docregion bootstrap bootstrap(AppComponent, [ - ROUTER_PROVIDERS, + appRouterProviders, { provide: LocationStrategy, useClass: HashLocationStrategy }, { provide: XHRBackend, useClass: InMemoryBackendService }, // in-mem server diff --git a/public/docs/_examples/router/ts/app/app.component.5.ts b/public/docs/_examples/router/ts/app/app.component.5.ts deleted file mode 100644 index 7ffb615027..0000000000 --- a/public/docs/_examples/router/ts/app/app.component.5.ts +++ /dev/null @@ -1,42 +0,0 @@ -// #docplaster -// #docregion -import { Component } from '@angular/core'; - -import { provideRouter, ROUTER_DIRECTIVES } from '@angular/router'; -import { routes } from './app.routes'; -// #docregion can-deactivate-guard -import { CanDeactivateGuard } from './interfaces'; -// #enddocregion can-deactivate-guard - -import { DialogService } from './dialog.service'; -import { HeroService } from './heroes/hero.service'; - -// Add these symbols to override the `LocationStrategy` -import { LocationStrategy, - HashLocationStrategy } from '@angular/common'; - - -@Component({ - selector: 'my-app', -// #docregion template - template: ` -

    Component Router

    - - - `, -// #enddocregion template - providers: [ - HeroService, - DialogService, - provideRouter(routes), - CanDeactivateGuard, - { provide: LocationStrategy, - useClass: HashLocationStrategy } // .../#/crisis-center/ - ], - directives: [ROUTER_DIRECTIVES] -}) -export class AppComponent { -} diff --git a/public/docs/_examples/router/ts/app/app.routes.1.ts b/public/docs/_examples/router/ts/app/app.routes.1.ts index f22d480744..14a0ebe946 100644 --- a/public/docs/_examples/router/ts/app/app.routes.1.ts +++ b/public/docs/_examples/router/ts/app/app.routes.1.ts @@ -14,7 +14,7 @@ import { HeroDetailComponent } from './heroes/hero-detail.component'; // #docregion // #docregion route-config -export const routes: RouterConfig = [ +const routes: RouterConfig = [ // #docregion route-defs { path: 'crisis-center', component: CrisisCenterComponent }, { path: 'heroes', component: HeroListComponent }, diff --git a/public/docs/_examples/router/ts/app/app.routes.2.ts b/public/docs/_examples/router/ts/app/app.routes.2.ts index c79e8ad17c..e2e3d1f9fc 100644 --- a/public/docs/_examples/router/ts/app/app.routes.2.ts +++ b/public/docs/_examples/router/ts/app/app.routes.2.ts @@ -8,7 +8,7 @@ import { CrisisListComponent } from './crisis-list.component'; import { HeroListComponent } from './hero-list.component'; // #docregion route-config -export const routes: RouterConfig = [ +const routes: RouterConfig = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'heroes', component: HeroListComponent } ]; diff --git a/public/docs/_examples/style-guide/ts/app/app.routes.ts b/public/docs/_examples/style-guide/ts/app/app.routes.ts index 9254169331..d3799a9390 100644 --- a/public/docs/_examples/style-guide/ts/app/app.routes.ts +++ b/public/docs/_examples/style-guide/ts/app/app.routes.ts @@ -56,6 +56,6 @@ const routes: RouterConfig = [ { path: '09-01', component: S0901 }, ]; -export const APP_ROUTER_PROVIDERS = [ +export const appRouterProviders = [ provideRouter(routes) ]; diff --git a/public/docs/_examples/style-guide/ts/app/main.ts b/public/docs/_examples/style-guide/ts/app/main.ts index b58fbb68dd..759f9e261b 100644 --- a/public/docs/_examples/style-guide/ts/app/main.ts +++ b/public/docs/_examples/style-guide/ts/app/main.ts @@ -4,12 +4,12 @@ import { HashLocationStrategy, LocationStrategy } from '@angular/common'; import { InMemoryBackendService, SEED_DATA } from 'angular2-in-memory-web-api'; import 'rxjs/add/operator/map'; -import { APP_ROUTER_PROVIDERS } from './app.routes'; +import { appRouterProviders } from './app.routes'; import { HeroData } from './hero-data'; import { AppComponent } from './app.component'; bootstrap(AppComponent, [ - APP_ROUTER_PROVIDERS, + appRouterProviders, HTTP_PROVIDERS, { provide: LocationStrategy, useClass: HashLocationStrategy }, { provide: XHRBackend, useClass: InMemoryBackendService }, diff --git a/public/docs/_examples/toh-5/ts/app/app.routes.1.ts b/public/docs/_examples/toh-5/ts/app/app.routes.1.ts index 8b4d582680..0c34add29c 100644 --- a/public/docs/_examples/toh-5/ts/app/app.routes.1.ts +++ b/public/docs/_examples/toh-5/ts/app/app.routes.1.ts @@ -6,7 +6,7 @@ import { HeroesComponent } from './heroes.component'; import { HeroDetailComponent } from './hero-detail.component'; // #enddocregion hero-detail-import -export const routes: RouterConfig = [ +const routes: RouterConfig = [ // #docregion redirect-route { path: '', @@ -32,6 +32,6 @@ export const routes: RouterConfig = [ } ]; -export const APP_ROUTER_PROVIDERS = [ +export const appRouterProviders = [ provideRouter(routes) ]; diff --git a/public/docs/_examples/toh-5/ts/app/app.routes.2.ts b/public/docs/_examples/toh-5/ts/app/app.routes.2.ts index 47311fcd8d..075cc37496 100644 --- a/public/docs/_examples/toh-5/ts/app/app.routes.2.ts +++ b/public/docs/_examples/toh-5/ts/app/app.routes.2.ts @@ -9,6 +9,6 @@ const routes: RouterConfig = [ } ]; -export const APP_ROUTER_PROVIDERS = [ +export const appRouterProviders = [ provideRouter(routes) ]; diff --git a/public/docs/_examples/toh-5/ts/app/app.routes.ts b/public/docs/_examples/toh-5/ts/app/app.routes.ts index 33097804eb..c6074c3607 100644 --- a/public/docs/_examples/toh-5/ts/app/app.routes.ts +++ b/public/docs/_examples/toh-5/ts/app/app.routes.ts @@ -7,7 +7,7 @@ import { HeroesComponent } from './heroes.component'; import { HeroDetailComponent } from './hero-detail.component'; // #enddocregion hero-detail-import -export const routes: RouterConfig = [ +const routes: RouterConfig = [ { path: '', redirectTo: '/dashboard', @@ -27,6 +27,6 @@ export const routes: RouterConfig = [ } ]; -export const APP_ROUTER_PROVIDERS = [ +export const appRouterProviders = [ provideRouter(routes) ]; diff --git a/public/docs/_examples/toh-5/ts/app/main.ts b/public/docs/_examples/toh-5/ts/app/main.ts index da35003df1..f04d528627 100644 --- a/public/docs/_examples/toh-5/ts/app/main.ts +++ b/public/docs/_examples/toh-5/ts/app/main.ts @@ -2,8 +2,8 @@ import { bootstrap } from '@angular/platform-browser-dynamic'; import { AppComponent } from './app.component'; -import { APP_ROUTER_PROVIDERS } from './app.routes'; +import { appRouterProviders } from './app.routes'; bootstrap(AppComponent, [ - APP_ROUTER_PROVIDERS + appRouterProviders ]); diff --git a/public/docs/_examples/toh-6/ts/app/app.routes.ts b/public/docs/_examples/toh-6/ts/app/app.routes.ts index 1d9adf33fd..e143b2a3bf 100644 --- a/public/docs/_examples/toh-6/ts/app/app.routes.ts +++ b/public/docs/_examples/toh-6/ts/app/app.routes.ts @@ -5,7 +5,7 @@ import { DashboardComponent } from './dashboard.component'; import { HeroesComponent } from './heroes.component'; import { HeroDetailComponent } from './hero-detail.component'; -export const routes: RouterConfig = [ +const routes: RouterConfig = [ { path: '', redirectTo: '/dashboard', @@ -25,6 +25,6 @@ export const routes: RouterConfig = [ } ]; -export const APP_ROUTER_PROVIDERS = [ +export const appRouterProviders = [ provideRouter(routes) ]; diff --git a/public/docs/_examples/toh-6/ts/app/main.ts b/public/docs/_examples/toh-6/ts/app/main.ts index 948e2ca5ba..bda66d0377 100644 --- a/public/docs/_examples/toh-6/ts/app/main.ts +++ b/public/docs/_examples/toh-6/ts/app/main.ts @@ -12,20 +12,20 @@ import { bootstrap } from '@angular/platform-browser-dynamic'; import { HTTP_PROVIDERS } from '@angular/http'; import { AppComponent } from './app.component'; -import { APP_ROUTER_PROVIDERS } from './app.routes'; +import { appRouterProviders } from './app.routes'; // #enddocregion v1, final /* // #docregion v1 bootstrap(AppComponent, [ - APP_ROUTER_PROVIDERS, + appRouterProviders, HTTP_PROVIDERS ]); // #enddocregion v1 */ // #docregion final bootstrap(AppComponent, [ - APP_ROUTER_PROVIDERS, + appRouterProviders, HTTP_PROVIDERS, { provide: XHRBackend, useClass: InMemoryBackendService }, // in-mem server { provide: SEED_DATA, useClass: InMemoryDataService } // in-mem server data 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 1e03e145d2..980e4ecb84 100644 --- a/public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade +++ b/public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade @@ -11,18 +11,18 @@ a(id="top") ## Contents This chapter covers * [Template Basics](#template-basics) - binding and local variables - + * [Template Directives](#template-directives) - built-in directives `ngIf` and `ngClass` - + * [Filters/Pipes](#filters-pipes) - built-in *filters*, known as *pipes* in Angular 2 - - * [Controllers/Components](#controllers-components) - *controllers* are *components* in Angular 2. + + * [Controllers/Components](#controllers-components) - *controllers* are *components* in Angular 2. Also covers modules. - + * [Style Sheets](#style-sheets) - more options for CSS in Angular 2. - + * [String date pipe](#string-dates) - a tip for displaying string date values. - + .l-main-section :marked ## Template Basics @@ -33,7 +33,7 @@ a(id="top") - var top="vertical-align:top" table(width="100%") col(width="50%") - col(width="50%") + col(width="50%") tr th Angular 1 th Angular 2 @@ -47,7 +47,7 @@ table(width="100%") In Angular 1, an expression in curly braces denotes one-way binding. This binds the value of the element to a property in the controller associated with this template. - + When using the `controller as` syntax, the binding is prefixed with the controller alias (`vm`) because we have to be specific about the source of the binding. @@ -60,7 +60,7 @@ table(width="100%") This binds the value of the element to a property of the component. The context of the binding is implied and is always the associated component, so it needs no reference variable. - + For more information see [Template Syntax](../guide/template-syntax.html#interpolation). tr(style=top) td @@ -70,7 +70,7 @@ table(width="100%") <td>{{movie.title | uppercase}}</td> :marked To filter output in our templates in Angular 1, we use the pipe character (|) and one or more filters. - + In this example, we filter the `title` property to uppercase. td :marked @@ -80,7 +80,7 @@ table(width="100%") In Angular 2, we use similar syntax with the pipe (|) character to filter output, but now we call them **pipes**. Many (but not all) of the built-in filters from Angular 1 are built-in pipes in Angular 2. - + See the heading [Filters / Pipes](#Pipes) below for more information. tr(style=top) td @@ -98,21 +98,21 @@ table(width="100%") +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'local')(format="." ) :marked In Angular 2, we have true template input variables that are explicitly defined using the `let` keyword. - + For more information see [ngFor micro-syntax](../guide/template-syntax.html#ngForMicrosyntax). :marked [Back to top](#top) - + .l-main-section :marked ## Template Directives - Angular 1 provides over seventy built-in directives for use in our templates. - Many of them are no longer needed in Angular 2 because of its more capable and expressive binding system. + Angular 1 provides over seventy built-in directives for use in our templates. + Many of them are no longer needed in Angular 2 because of its more capable and expressive binding system. The following are some of the key Angular 1 built-in directives and the equivalent feature in Angular 2. table(width="100%") col(width="50%") - col(width="50%") + col(width="50%") tr th Angular 1 th Angular 2 @@ -121,22 +121,22 @@ table(width="100%") :marked ### ng-app code-example. - <body ng-app="movieHunter"> + <body ng-app="movieHunter"> :marked The application startup process is called **bootstrapping**. - + Although we can bootstrap an Angular 1 app in code, many applications bootstrap declaratively with the `ng-app` directive, giving it the name of the application's module (`movieHunter`). td :marked ### Bootstrapping - +makeExample('cb-a1-a2-quick-reference/ts/app/main.ts')(format="." ) + +makeExample('cb-a1-a2-quick-reference/ts/app/main.1.ts')(format="." ) :marked Angular 2 does not have a bootstrap directive. We always launch the app in code by explicitly calling a bootstrap function and passing it the name of the application's module (`AppComponent`). - + For more information see [Quick Start](../quickstart.html). tr(style=top) td @@ -144,32 +144,32 @@ table(width="100%") ### ng-class code-example(format=""). <div ng-class="{active: isActive}"> - <div ng-class="{active: isActive, + <div ng-class="{active: isActive, shazam: isImportant}"> :marked In Angular 1, the `ng-class` directive includes/excludes CSS classes based on an expression. That expression is often a key-value control object with each key of the object defined as a CSS class name, and each value defined as a template expression that evaluates to a Boolean value. - + In the first example, the `active` class is applied to the element if `isActive` is true. - + We can specify multiple classes as shown in the second example. td :marked ### ngClass +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'ngClass')(format="." ) :marked - In Angular 2, the `ngClass` directive works similarly. - It includes/excludes CSS classes based on an expression. - + In Angular 2, the `ngClass` directive works similarly. + It includes/excludes CSS classes based on an expression. + In the first example, the `active` class is applied to the element if `isActive` is true. - + We can specify multiple classes as shown in the second example. - - Angular 2 also has **class binding**, which is a good way to add or remove a single class + + Angular 2 also has **class binding**, which is a good way to add or remove a single class as shown in the third example. - + For more information see [Template Syntax](../guide/template-syntax.html#other-bindings). tr(style=top) @@ -181,9 +181,9 @@ table(width="100%") <button ng-click="vm.toggleImage($event)"> :marked In Angular 1, the `ng-click` directive allows us to specify custom behavior when an element is clicked. - + In the first example, when the button is clicked, the `toggleImage()` method in the controller referenced by the `vm` `controller as` alias is executed. - + The second example demonstrates passing in the `$event` object, which provides details about the event to the controller. td @@ -191,21 +191,21 @@ table(width="100%") ### bind to the `click` event +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'event-binding')(format="." ) :marked - The Angular 1 event-based directives do not exist in Angular 2. + The Angular 1 event-based directives do not exist in Angular 2. Rather, we define one-way binding from the template view to the component using **event binding**. - + For event binding, we define the name of the target event within parenthesis and specify a template statement in quotes to the right of the equals. Angular 2 then sets up an event handler for the target event. When the event is raised, the handler executes the template statement. - + In the first example, when the button is clicked, the `toggleImage()` method in the associated component is executed. - + The second example demonstrates passing in the `$event` object, which provides details about the event to the component. - + For a list of DOM events, see: https://developer.mozilla.org/en-US/docs/Web/Events. - + For more information see [Template Syntax](../guide/template-syntax.html#event-binding). tr(style=top) @@ -215,17 +215,17 @@ table(width="100%") code-example(format=""). <div ng-controller="MovieListCtrl as vm"> :marked - In Angular 1, the `ng-controller` directive attaches a controller to the view. + In Angular 1, the `ng-controller` directive attaches a controller to the view. Using the `ng-controller` (or defining the controller as part of the routing) ties the - view to the controller code associated with that view. + view to the controller code associated with that view. td :marked ### Component decorator +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'component')(format="." ) :marked - In Angular 2, the template no longer specifies its associated controller. + In Angular 2, the template no longer specifies its associated controller. Rather, the component specifies its associated template as part of the component class decorator. - + For more information see [Architecture Overview](../guide/architecture.html#component). tr(style=top) @@ -262,9 +262,9 @@ table(width="100%") :marked In Angular 2, we use property binding; there is no built-in *href* directive. We place the element's `href` property in square brackets and set it to a quoted template expression. - + For more information on property binding see [Template Syntax](../guide/template-syntax.html#property-binding). - + In Angular 2, `href` is no longer used for routing. Routing uses `routerLink` as shown in the third example. +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'router-link')(format="." ) :marked @@ -279,18 +279,18 @@ table(width="100%") :marked In Angular 1, the `ng-if` directive removes or recreates a portion of the DOM based on an expression. If the expression is false, the element is removed from the DOM. - + In this example, the `table` element is removed from the DOM unless the `movies` array has a length greater than zero. td :marked ### *ngIf +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'ngIf')(format="." ) :marked - The `*ngIf` directive in Angular 2 works the same as the `ng-if` directive in Angular 1, + The `*ngIf` directive in Angular 2 works the same as the `ng-if` directive in Angular 1, it removes or recreates a portion of the DOM based on an expression. In this example, the `table` element is removed from the DOM unless the `movies` array has a length. - + The (*) before `ngIf` is required in this example. For more information see [Structural Directives](../guide/structural-directives.html). tr(style=top) @@ -309,9 +309,9 @@ table(width="100%") +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'ngModel')(format="." ) :marked In Angular 2, **two-way binding** is denoted with [()], descriptively referred to as a "banana in a box". - This syntax is a short-cut for defining both property binding (from the component to the view) + This syntax is a short-cut for defining both property binding (from the component to the view) and event binding (from the view to the component), thereby giving us two-way binding. - + For more information on two-way binding with ngModel see [Template Syntax](../guide/template-syntax.html#ngModel). tr(style=top) td @@ -322,23 +322,23 @@ table(width="100%") :marked In Angular 1, the `ng-repeat` directive repeats the associated DOM element for each item from the specified collection. - + In this example, the table row (`tr`) element is repeated for each movie object in the collection of movies. td :marked ### *ngFor +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'ngFor')(format="." ) :marked - The `*ngFor` directive in Angular 2 is similar to the `ng-repeat` directive in Angular 1. + The `*ngFor` directive in Angular 2 is similar to the `ng-repeat` directive in Angular 1. It repeats the associated DOM element for each item from the specified collection. More accurately, it turns the defined element (`tr` in this example) and its contents into a template and uses that template to instantiate a view for each item in the list. - + Notice the other syntax differences: The (*) before `ngFor` is required; the `let` keyword identifies `movie` as an input variable; the list preposition is `of`, not `in`. - + For more information see [Structural Directives](../guide/structural-directives.html). tr(style=top) td @@ -351,7 +351,7 @@ table(width="100%") :marked In Angular 1, the `ng-show` directive shows or hides the associated DOM element based on an expression. - + In this example, the `div` element is shown if the `favoriteHero` variable is truthy. td :marked @@ -360,12 +360,12 @@ table(width="100%") :marked In Angular 2, we use property binding; there is no built-in *show* directive. For hiding and showing elements, we bind to the HTML `hidden` property. - - To conditionally display an element, place the element's `hidden` property in square brackets and + + To conditionally display an element, place the element's `hidden` property in square brackets and set it to a quoted template expression that evaluates to the *opposite* of *show*. In this example, the `div` element is hidden if the `favoriteHero` variable is not truthy. - + For more information on property binding see [Template Syntax](../guide/template-syntax.html#property-binding). tr(style=top) td @@ -384,7 +384,7 @@ table(width="100%") :marked In Angular 2, we use property binding; there is no built-in *src* directive. We place the `src` property in square brackets and set it to a quoted template expression. - + For more information on property binding see [Template Syntax](../guide/template-syntax.html#property-binding). tr(style=top) td @@ -397,28 +397,28 @@ table(width="100%") based on an expression. That expression is often a key-value control object with each key of the object defined as a CSS style name, and each value defined as an expression that evaluates to a value appropriate for the style. - + In the example, the `color` style is set to the current value of the `colorPreference` variable. td :marked ### ngStyle +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'ngStyle')(format="." ) :marked - In Angular 2, the `ngStyle` directive works similarly. It sets a CSS style on an HTML element based on an expression. - + In Angular 2, the `ngStyle` directive works similarly. It sets a CSS style on an HTML element based on an expression. + In the first example, the `color` style is set to the current value of the `colorPreference` variable. - + Angular 2 also has **style binding**, which is good way to set a single style. This is shown in the second example. - + For more information on style binding see [Template Syntax](../guide/template-syntax.html#style-binding). - + For more information on the ngStyle directive see [Template Syntax](../guide/template-syntax.html#ngStyle). tr(style=top) td :marked ### ng-switch code-example(format=""). - <div ng-switch="vm.favoriteHero && + <div ng-switch="vm.favoriteHero && vm.checkMovieHero(vm.favoriteHero)"> <div ng-switch-when="true"> Excellent choice! @@ -433,7 +433,7 @@ table(width="100%") :marked In Angular 1, the `ng-switch` directive swaps the contents of an element by selecting one of the templates based on the current value of an expression. - + In this example, if `favoriteHero` is not set, the template displays "Please enter ...". If the `favoriteHero` is set, it checks the movie hero by calling a controller method. If that method returns `true`, the template displays "Excellent choice!". @@ -443,21 +443,21 @@ table(width="100%") ### ngSwitch +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'ngSwitch')(format="." ) :marked - In Angular 2, the `ngSwitch` directive works similarly. + In Angular 2, the `ngSwitch` directive works similarly. It displays an element whose `*ngSwitchCase` matches the current `ngSwitch` expression value. - + In this example, if `favoriteHero` is not set, the `ngSwitch` value is `null` and we see the `*ngSwitchDefault` paragraph, "Please enter ...". If the `favoriteHero` is set, it checks the movie hero by calling a component method. If that method returns `true`, we see "Excellent choice!". If that methods returns `false`, we see "No movie, sorry!". - + The (*) before `ngSwitchCase` and `ngSwitchDefault` is required in this example. - + For more information on the ngSwitch directive see [Template Syntax](../guide/template-syntax.html#ngSwitch). :marked [Back to top](#top) - + a(id="filters-pipes") .l-main-section :marked @@ -468,7 +468,7 @@ a(id="filters-pipes") table(width="100%") col(width="50%") - col(width="50%") + col(width="50%") tr th Angular 1 th Angular 2 @@ -513,9 +513,9 @@ table(width="100%") :marked ### none There is no comparable pipe in Angular 2 for performance reasons. - Filtering should be coded in the component. - Consider building a custom pipe if the same filtering code - will be reused in several templates. + Filtering should be coded in the component. + Consider building a custom pipe if the same filtering code + will be reused in several templates. tr(style=top) td @@ -546,7 +546,7 @@ table(width="100%") +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'slice')(format=".") :marked The `SlicePipe` does the same thing but the *order of the parameters is reversed* in keeping - with the JavaScript `Slice` method. + with the JavaScript `Slice` method. The first parameter is the starting index; the second is the limit. As in Angular 1, performance may improve if we code this operation within the component instead. tr(style=top) @@ -577,9 +577,9 @@ table(width="100%") +makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'number')(format=".") :marked The Angular 2 `number` pipe is similar. - It provides more functionality when defining + It provides more functionality when defining the decimal places as shown in the second example above. - + Angular 2 also has a `percent` pipe which formats a number as a local percentage as shown in the third example. tr(style=top) @@ -589,31 +589,31 @@ table(width="100%") code-example. <tr ng-repeat="movie in movieList | orderBy : 'title'"> :marked - Orders the collection as specified by the expression. + Orders the collection as specified by the expression. In this example, the movieList is ordered by the movie title. td :marked ### none There is no comparable pipe in Angular 2 for performance reasons. - Ordering/sorting the results should be coded in the component. - Consider building a custom pipe if the same ordering/sorting code + Ordering/sorting the results should be coded in the component. + Consider building a custom pipe if the same ordering/sorting code will be reused in several templates. :marked [Back to top](#top) - + a(id="controllers-components") .l-main-section :marked ## Controllers / Components In Angular 1, we write the code that provides the model and the methods for the view in a **controller**. In Angular 2, we build a **component**. - + Because much of our Angular 1 code is in JavaScript, JavaScript code is shown in the Angular 1 column. The Angular 2 code is shown using TypeScript. table(width="100%") col(width="50%") - col(width="50%") + col(width="50%") tr th Angular 1 th Angular 2 @@ -627,13 +627,13 @@ table(width="100%") }()); :marked In Angular 1, we often defined an immediately invoked function expression (or IIFE) around our controller code. - This kept our controller code out of the global namespace. + This kept our controller code out of the global namespace. td :marked ### none We don't need to worry about this in Angular 2 because we use ES 2015 modules and modules handle the namespacing for us. - + For more information on modules see [Architecture Overview](../guide/architecture.html#module). tr(style=top) td @@ -652,9 +652,9 @@ table(width="100%") :marked Angular 2 does not have its own module system. Instead we use ES 2015 modules. ES 2015 modules are file based, so each code file is its own module. - + We `import` what we need from the module files. - + For more information on modules see [Architecture Overview](../guide/architecture.html#module). tr(style=top) td @@ -668,10 +668,10 @@ table(width="100%") MovieListCtrl]); :marked In Angular 1, we have code in each controller that looks up an appropriate Angular module - and registers the controller with that module. - + and registers the controller with that module. + The first argument is the controller name. The second argument defines the string names of - all dependencies injected into this controller, and a reference to the controller function. + all dependencies injected into this controller, and a reference to the controller function. td :marked ### Component Decorator @@ -680,9 +680,9 @@ table(width="100%") In Angular 2, we add a decorator to the component class to provide any required metadata. The Component decorator declares that the class is a component and provides metadata about that component, such as its selector (or tag) and its template. - + This is how we associate a template with code, which is defined in the component class. - + For more information on components see [Architecture Overview](../guide/architecture.html#component). tr(style=top) td @@ -692,17 +692,17 @@ table(width="100%") function MovieListCtrl(movieService) { } :marked - In Angular 1, we write the code for the model and methods in a controller function. + In Angular 1, we write the code for the model and methods in a controller function. td :marked ### Component class +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'class')(format=".") :marked In Angular 2, we create a component class. - + NOTE: If you are using TypeScript with Angular 1 then the only difference here is that the component class must be exported using the `export` keyword. - + For more information on components see [Architecture Overview](../guide/architecture.html#component). tr(style=top) td @@ -715,8 +715,8 @@ table(width="100%") :marked In Angular 1, we pass in any dependencies as controller function arguments. In this example, we inject a `MovieService`. - - We also guard against minification problems by telling Angular explicitly + + We also guard against minification problems by telling Angular explicitly that it should inject an instance of the `MovieService` in the first parameter. td :marked @@ -724,13 +724,13 @@ table(width="100%") +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'di')(format=".") :marked In Angular 2, we pass in dependencies as arguments to the component class constructor. - In this example, we inject a `MovieService`. + In this example, we inject a `MovieService`. The first parameter's TypeScript type tells Angular what to inject even after minification. - + For more information on dependency injection see [Architecture Overview](../guide/architecture.html#dependency-injection). :marked [Back to top](#top) - + a(id="style-sheets") .l-main-section :marked @@ -743,7 +743,7 @@ a(id="style-sheets") also encapculate a style sheet within a specific component. table(width="100%") col(width="50%") - col(width="50%") + col(width="50%") tr th Angular 1 th Angular 2 @@ -755,7 +755,7 @@ table(width="100%") <link href="styles.css" rel="stylesheet" /> :marked In Angular 1, we use a `link` tag in the head section of our `index.html` file - to define the styles for our application. + to define the styles for our application. td :marked ### Link tag @@ -765,11 +765,11 @@ table(width="100%") But we can now also encapsulate styles for our components. :marked ### StyleUrls - In Angular 2, we can use the `styles` or `styleUrls` property of the `@Component` metadata to define + In Angular 2, we can use the `styles` or `styleUrls` property of the `@Component` metadata to define a style sheet for a particular component. +makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'style-url')(format=".") :marked - This allows us to set appropriate styles for individual components that won’t leak into + This allows us to set appropriate styles for individual components that won’t leak into other parts of the application. :marked [Back to top](#top) @@ -778,10 +778,10 @@ a(id="string-dates") .l-main-section :marked ## Appendix: String dates - + Currently the Angular 2 `date` pipe does not process string dates such as "2015-12-19T00:00:00". - + As a work around, subclass the Angular `DatePipe` with a version that can convert strings and substitute that pipe in the HTML: @@ -789,7 +789,7 @@ a(id="string-dates") :marked Then import and declare that pipe in the `@Component` metadata `pipes` array: :marked -+makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'date-pipe')(format=".") ++makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'date-pipe')(format=".") :marked [Back to top](#top) diff --git a/public/docs/ts/latest/guide/router.jade b/public/docs/ts/latest/guide/router.jade index 0f4ed85a2a..3d67dc1622 100644 --- a/public/docs/ts/latest/guide/router.jade +++ b/public/docs/ts/latest/guide/router.jade @@ -111,7 +111,7 @@ include ../_util-fns We pass the configuration array to the `provideRouter()` function which returns (among other things) a configured *Router* [service provider](dependency-injection.html#!#injector-providers). - Finally, we export this provider in the `APP_ROUTER_PROVIDERS` array + Finally, we export this provider in the `appRouterProviders` array so we can simplify registration of router dependencies later in `main.ts`. We don't have any other providers to register right now. But we will. :marked @@ -382,9 +382,9 @@ h4#provideRouter Call provideRouter `Router` service provider ... and some other, unseen providers that the routing library requires. :marked - We add the `provideRouter` array to an `APP_ROUTER_PROVIDERS` array and export it. + We add the `provideRouter` array to an `appRouterProviders` array and export it. - We could add *additional* service providers to `APP_ROUTER_PROVIDERS` — + We could add *additional* service providers to `appRouterProviders` — providers that are specific to our routing configuration. We don't have any yet. We will have some later in this chapter. @@ -397,7 +397,7 @@ h4#register-providers Register routing in bootstrap Our app launches from the `main.ts` file in the `/app` folder. It's short and not much different from the default `main.ts`. - The important difference: we import the `APP_ROUTER_PROVIDERS` array + The important difference: we import the `appRouterProviders` array and pass it as the second parameter of the `bootstrap` function. +makeExample('router/ts/app/main.1.ts','all', 'main.ts')(format=".") :marked @@ -978,7 +978,7 @@ code-example(format=""). We prefer that the application display the list of crises as it would if the user clicked the "Crisis Center" link or pasted `localhost:3000/crisis-center/` into the address bar. This is our intended default route. - The preferred solution is to add a `redirect` route that transparently translates from the initial relative URL (`''`) + The preferred solution is to add a `redirect` route that transparently translates from the initial relative URL (`''`) to the desired default path (`/crisis-center`): +makeExample('router/ts/app/crisis-center/crisis-center.routes.2.ts', 'redirect', 'app/crisis-center/crisis-center.routes.ts (redirect route)' )(format='.') @@ -989,21 +989,21 @@ code-example(format=""). .l-sub-section :marked - Technically, `pathMatch = 'full'` results in a route hit when the *remaining*, unmatched segments of the URL match `''`. + Technically, `pathMatch = 'full'` results in a route hit when the *remaining*, unmatched segments of the URL match `''`. In our example, the redirect is at the top level of the route configuration tree so the *remaining* URL and the *entire* URL are the same thing. - The other possible `pathMatch` value is `'prefix'` which tells the router + The other possible `pathMatch` value is `'prefix'` which tells the router to match the redirect route when the *remaining* URL ***begins*** with the redirect route's _prefix_ path. - - That's not what we want to do here. If the `pathMatch` value were `'prefix'`, - _every_ URL would match `''`. - We could never navigate to `/crisis-center/1` because the redirect route would match first and + + That's not what we want to do here. If the `pathMatch` value were `'prefix'`, + _every_ URL would match `''`. + We could never navigate to `/crisis-center/1` because the redirect route would match first and send us to the `CrisisListComponent`. - + We should redirect to the `CrisisListComponent` _only_ when the _entire (remaining)_ url is `''`. - Learn more in Victor Savkin's blog + Learn more in Victor Savkin's blog [post on redirects](http://victorsavkin.com/post/146722301646/angular-router-empty-paths-componentless-routes). We'll discuss redirects in more detail in a future update to this chapter. @@ -1228,7 +1228,7 @@ h3#can-deactivate-guard CanDeactivate: handling unsaved changes +makeExample('router/ts/app/crisis-center/crisis-center.routes.4.ts', '', 'crisis-center.routes.ts') :marked - We also need to add the `Guard` to our main `APP_ROUTER_PROVIDERS` so the `Router` can inject it during the navigation process. + We also need to add the `Guard` to our main `appRouterProviders` so the `Router` can inject it during the navigation process. +makeExample('router/ts/app/app.routes.ts', '', 'app.routes.ts') :marked diff --git a/public/docs/ts/latest/tutorial/toh-pt5.jade b/public/docs/ts/latest/tutorial/toh-pt5.jade index d576064f2c..9f17e0811a 100644 --- a/public/docs/ts/latest/tutorial/toh-pt5.jade +++ b/public/docs/ts/latest/tutorial/toh-pt5.jade @@ -178,7 +178,7 @@ code-example(language="bash"). :marked ### Make the router available. - The *Component Router* is a service. We have to import our `APP_ROUTER_PROVIDERS` which + The *Component Router* is a service. We have to import our `appRouterProviders` which contains our configured router and make it available to the application by adding it to the `bootstrap` array. +makeExample('toh-5/ts/app/main.ts', '', 'app/main.ts')(format=".") From 98e5d4af775fca095b67f43c8b37361821e39f40 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Wed, 6 Jul 2016 14:39:14 -0700 Subject: [PATCH 06/25] docs(all): link cleanup - broken and outdated closes #1841 Fixes all broken links except genuine errors (see #1840), have been resolved as of 2016-07-06 (https://github.com/angular/angular/commit/2708ce6a17667a2369c83bcf244c9 366b058d4c9). Fixes #1574 --- .../docs/dart/latest/cookbook/dynamic-form-deprecated.html | 1 + public/docs/dart/latest/guide/component-styles.jade | 2 +- public/docs/dart/latest/guide/forms-deprecated.html | 1 + public/docs/dart/latest/guide/forms.jade | 2 +- public/docs/dart/latest/guide/server-communication.jade | 2 +- public/docs/dart/latest/guide/template-syntax.jade | 4 ++-- public/docs/dart/latest/quickstart.jade | 4 ++-- public/docs/dart/latest/tutorial/toh-pt5.jade | 2 +- public/docs/js/latest/cookbook/dynamic-form-deprecated.html | 1 + public/docs/js/latest/guide/animations.jade | 1 + public/docs/js/latest/guide/forms-deprecated.jade | 2 +- public/docs/js/latest/guide/forms.jade | 4 ++-- public/docs/ts/latest/cookbook/set-document-title.jade | 2 +- public/docs/ts/latest/guide/dependency-injection.jade | 2 +- public/docs/ts/latest/guide/forms-deprecated.jade | 6 +++--- public/docs/ts/latest/guide/forms.jade | 2 +- public/docs/ts/latest/guide/pipes.jade | 6 +++--- public/docs/ts/latest/guide/router-deprecated.jade | 2 +- public/docs/ts/latest/guide/server-communication.jade | 2 +- public/docs/ts/latest/guide/style-guide.jade | 2 +- 20 files changed, 27 insertions(+), 23 deletions(-) create mode 100644 public/docs/dart/latest/cookbook/dynamic-form-deprecated.html create mode 100644 public/docs/dart/latest/guide/forms-deprecated.html create mode 100644 public/docs/js/latest/cookbook/dynamic-form-deprecated.html create mode 100644 public/docs/js/latest/guide/animations.jade diff --git a/public/docs/dart/latest/cookbook/dynamic-form-deprecated.html b/public/docs/dart/latest/cookbook/dynamic-form-deprecated.html new file mode 100644 index 0000000000..f8df2a84a6 --- /dev/null +++ b/public/docs/dart/latest/cookbook/dynamic-form-deprecated.html @@ -0,0 +1 @@ +!= partial("../../../_includes/_ts-temp") \ No newline at end of file diff --git a/public/docs/dart/latest/guide/component-styles.jade b/public/docs/dart/latest/guide/component-styles.jade index 71507a7d01..967dc2d8b0 100644 --- a/public/docs/dart/latest/guide/component-styles.jade +++ b/public/docs/dart/latest/guide/component-styles.jade @@ -19,7 +19,7 @@ block css-import-url .alert.is-important :marked URLs are currently not interpreted in this way, see - [issue 8518](href="https://github.com/angular/angular/issues/8518"). + [issue 8518](https://github.com/angular/angular/issues/8518). Until this issue is fixed, absolute package-reference style URLs must be given as is illustrated below. diff --git a/public/docs/dart/latest/guide/forms-deprecated.html b/public/docs/dart/latest/guide/forms-deprecated.html new file mode 100644 index 0000000000..f8df2a84a6 --- /dev/null +++ b/public/docs/dart/latest/guide/forms-deprecated.html @@ -0,0 +1 @@ +!= partial("../../../_includes/_ts-temp") \ No newline at end of file diff --git a/public/docs/dart/latest/guide/forms.jade b/public/docs/dart/latest/guide/forms.jade index e78d9c19eb..19b7d09aa5 100644 --- a/public/docs/dart/latest/guide/forms.jade +++ b/public/docs/dart/latest/guide/forms.jade @@ -517,7 +517,7 @@ figure.image-display Recall from the previous section that `ngControl` registered this input box with the `NgForm` directive as "name". - We didn't add the **[`NgForm`](../api/common/NgForm-directive.html) directive* + We didn't add the **[`NgForm`](../api/common/index/NgForm-directive.html) directive* explicitly. Angular added it surreptitiously, wrapping it around the `
    ` element. The `NgForm` directive supplements the `` element with additional features. diff --git a/public/docs/dart/latest/guide/server-communication.jade b/public/docs/dart/latest/guide/server-communication.jade index 1c3ad3155c..4064b7ec97 100644 --- a/public/docs/dart/latest/guide/server-communication.jade +++ b/public/docs/dart/latest/guide/server-communication.jade @@ -33,7 +33,7 @@ block http-providers block getheroes-and-addhero :marked The hero service `getHeroes()` and `addHero()` asynchronous methods return the - [`Future`](https://api.dartlang.org/stable/1.16.0/dart-async/Future-class.html) + [`Future`](https://api.dartlang.org/stable/dart-async/Future-class.html) values of the current hero list and the newly added hero, respectively. The hero list component methods of the same name specifying the actions to be taken when the asynchronous method calls succeed or fail. diff --git a/public/docs/dart/latest/guide/template-syntax.jade b/public/docs/dart/latest/guide/template-syntax.jade index 8ba4989112..71878e7b94 100644 --- a/public/docs/dart/latest/guide/template-syntax.jade +++ b/public/docs/dart/latest/guide/template-syntax.jade @@ -5,7 +5,7 @@ block includes - var _JavaScript = 'Dart'; - var __chaining_op = ';'; - var __new_op = 'new or const'; - - var mapApiRef = 'https://api.dartlang.org/stable/1.16.0/dart-core/Map-class.html'; + - var mapApiRef = 'https://api.dartlang.org/stable/dart-core/Map-class.html'; - var __objectAsMap = 'Map' block notable-differences @@ -69,7 +69,7 @@ block style-property-name-dart-diff and `setProperty()`. Hence, we recommend only using dash-case for style property names. - [CssSD]: https://api.dartlang.org/stable/1.16.1/dart-html/CssStyleDeclaration-class.html + [CssSD]: https://api.dartlang.org/stable/dart-html/CssStyleDeclaration-class.html block dart-no-truthy-falsey diff --git a/public/docs/dart/latest/quickstart.jade b/public/docs/dart/latest/quickstart.jade index 7352d90826..e2a026d4f7 100644 --- a/public/docs/dart/latest/quickstart.jade +++ b/public/docs/dart/latest/quickstart.jade @@ -17,8 +17,8 @@ block setup-tooling You can also download [Dart plugins for other IDEs and editors][DT]. [WS]: https://confluence.jetbrains.com/display/WI/Getting+started+with+Dart - [DT]: https://www.dartlang.org/tools - [pub]: https://www.dartlang.org/tools/pub + [DT]: https://www.dartlang.org/tools/ + [pub]: https://www.dartlang.org/tools/pub/ block download-source // exclude this section from Dart diff --git a/public/docs/dart/latest/tutorial/toh-pt5.jade b/public/docs/dart/latest/tutorial/toh-pt5.jade index c2923c1a05..ae8c6ef823 100644 --- a/public/docs/dart/latest/tutorial/toh-pt5.jade +++ b/public/docs/dart/latest/tutorial/toh-pt5.jade @@ -439,7 +439,7 @@ code-example(format=''). :marked Going back too far could take us out of the application. That's acceptable in a demo. We'd guard against it in a real application, - perhaps with the [*routerCanDeactivate* hook](../api/router/CanDeactivate-interface.html). + perhaps with the [*routerCanDeactivate* hook](../api/router/index/CanDeactivate-interface.html). :marked Then we wire this method with an event binding to a *Back* button that we add to the bottom of the component template. +makeExample('toh-5/dart/lib/hero_detail_component.html', 'back-button')(format=".") diff --git a/public/docs/js/latest/cookbook/dynamic-form-deprecated.html b/public/docs/js/latest/cookbook/dynamic-form-deprecated.html new file mode 100644 index 0000000000..f8df2a84a6 --- /dev/null +++ b/public/docs/js/latest/cookbook/dynamic-form-deprecated.html @@ -0,0 +1 @@ +!= partial("../../../_includes/_ts-temp") \ No newline at end of file diff --git a/public/docs/js/latest/guide/animations.jade b/public/docs/js/latest/guide/animations.jade new file mode 100644 index 0000000000..6778b6af28 --- /dev/null +++ b/public/docs/js/latest/guide/animations.jade @@ -0,0 +1 @@ +!= partial("../../../_includes/_ts-temp") diff --git a/public/docs/js/latest/guide/forms-deprecated.jade b/public/docs/js/latest/guide/forms-deprecated.jade index 185b25dee5..e17b9fe46c 100644 --- a/public/docs/js/latest/guide/forms-deprecated.jade +++ b/public/docs/js/latest/guide/forms-deprecated.jade @@ -493,7 +493,7 @@ figure.image-display :marked ### The NgForm directive We just set a template local variable with the value of an `NgForm` directive. - Why did that work? We didn't add the **[`NgForm`](../api/common/NgForm-directive.html) directive** explicitly. + Why did that work? We didn't add the **[`NgForm`](../api/common/index/NgForm-directive.html) directive** explicitly. Angular added it surreptitiously, wrapping it around the `` element diff --git a/public/docs/js/latest/guide/forms.jade b/public/docs/js/latest/guide/forms.jade index a02c2a53b3..2613b7b6b7 100644 --- a/public/docs/js/latest/guide/forms.jade +++ b/public/docs/js/latest/guide/forms.jade @@ -491,7 +491,7 @@ figure.image-display .l-sub-section :marked Why "ngModel"? - A directive's [exportAs](../api/core/DirectiveMetadata-class.html#!#exportAs) property + A directive's [exportAs](../api/core/index/DirectiveMetadata-class.html#!#exportAs) property tells Angular how to link the reference variable to the directive. We set `name` to `ngModel` because the `ngModel` directive's `exportAs` property happens to be "ngModel". @@ -503,7 +503,7 @@ figure.image-display :marked ### The NgForm directive We just set a template local variable with the value of an `NgForm` directive. - Why did that work? We didn't add the **[`NgForm`](../api/common/NgForm-directive.html) directive** explicitly. + Why did that work? We didn't add the **[`NgForm`](../api/common/index/NgForm-directive.html) directive** explicitly. Angular added it surreptitiously, wrapping it around the `` element diff --git a/public/docs/ts/latest/cookbook/set-document-title.jade b/public/docs/ts/latest/cookbook/set-document-title.jade index 8218b50b8b..7424b1632c 100644 --- a/public/docs/ts/latest/cookbook/set-document-title.jade +++ b/public/docs/ts/latest/cookbook/set-document-title.jade @@ -34,7 +34,7 @@ code-example(format='') :marked ## Use the *Title* service Fortunately, Angular 2 bridges the gap by providing a `Title` service as part of the *Browser platform*. - The [Title](../api/platform/browser/Title-class.html) service is a simple class that provides an API + The [Title](../api/platform-browser/index/Title-class.html) service is a simple class that provides an API for getting and setting the current HTML document title: * `getTitle() : string` — Gets the title of the current HTML document. diff --git a/public/docs/ts/latest/guide/dependency-injection.jade b/public/docs/ts/latest/guide/dependency-injection.jade index 2175d5cf65..759f303791 100644 --- a/public/docs/ts/latest/guide/dependency-injection.jade +++ b/public/docs/ts/latest/guide/dependency-injection.jade @@ -525,7 +525,7 @@ code-example(format="nocode"). that creates a new instance of the - [Provider](../api/core/Provider-class.html) class: + [Provider](../api/core/index/Provider-class.html) class: +makeExample('dependency-injection/ts/app/providers.component.ts','providers-3') diff --git a/public/docs/ts/latest/guide/forms-deprecated.jade b/public/docs/ts/latest/guide/forms-deprecated.jade index ed3699f402..0be1f0bfff 100644 --- a/public/docs/ts/latest/guide/forms-deprecated.jade +++ b/public/docs/ts/latest/guide/forms-deprecated.jade @@ -380,7 +380,7 @@ figure.image-display We'll talk about `NgForm` [later in the chapter](#ngForm). The `ngControl` *attribute* in our template actually maps to the - [NgControlName](../api/common/NgControlName-directive.html) directive. + [NgControlName](../api/common/index/NgControlName-directive.html) directive. There is also a `NgControl` *abstract* directive which is *not the same thing*. We often ignore this technical distinction and refer to `NgControlName` more conveniently (albeit incorrectly) as the *NgControl* directive. @@ -483,7 +483,7 @@ figure.image-display .l-sub-section :marked Why "ngForm"? - A directive's [exportAs](../api/core/DirectiveMetadata-class.html#!#exportAs) property + A directive's [exportAs](../api/core/index/DirectiveMetadata-class.html#!#exportAs) property tells Angular how to link the reference variable to the directive. We set `name` to `ngForm` because the `NgControlName` directive's `exportAs` property happens to be "ngForm". @@ -589,7 +589,7 @@ figure.image-display .l-sub-section :marked ### The NgForm directive - What `NgForm` directive? We didn't add an [NgForm](../api/common/NgForm-directive.html) directive! + What `NgForm` directive? We didn't add an [NgForm](../api/common/index/NgForm-directive.html) directive! Angular did. Angular creates and attaches an `NgForm` directive to the `` tag automatically. diff --git a/public/docs/ts/latest/guide/forms.jade b/public/docs/ts/latest/guide/forms.jade index e2321b231c..929a7ad0dd 100644 --- a/public/docs/ts/latest/guide/forms.jade +++ b/public/docs/ts/latest/guide/forms.jade @@ -593,7 +593,7 @@ figure.image-display .l-sub-section :marked ### The NgForm directive - What `NgForm` directive? We didn't add an [NgForm](../api/common/NgForm-directive.html) directive! + What `NgForm` directive? We didn't add an [NgForm](../api/common/index/NgForm-directive.html) directive! Angular did. Angular creates and attaches an `NgForm` directive to the `` tag automatically. diff --git a/public/docs/ts/latest/guide/pipes.jade b/public/docs/ts/latest/guide/pipes.jade index 8d7857e09a..744674ac3c 100644 --- a/public/docs/ts/latest/guide/pipes.jade +++ b/public/docs/ts/latest/guide/pipes.jade @@ -36,7 +36,7 @@ block includes :marked Inside the interpolation expression we flow the component's `birthday` value through the - [pipe operator](./template-syntax.html#pipe) ( | ) to the [Date pipe](../api/common/DatePipe-class.html) + [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-main-section @@ -95,7 +95,7 @@ figure.image-display .l-sub-section :marked - Learn more about the `DatePipes` format options in the [API Docs](../api/common/DatePipe-class.html). + Learn more about the `DatePipes` format options in the [API Docs](../api/common/index/DatePipe-class.html). :marked ## Chaining pipes @@ -395,7 +395,7 @@ figure.image-display .callout.is-helpful header Debugging with the json pipe :marked - The [JsonPipe](../api/common/JsonPipe-class.html) + The [JsonPipe](../api/common/index/JsonPipe-class.html) provides an easy way to diagnosis a mysteriously failing data binding or inspect an object for future binding. diff --git a/public/docs/ts/latest/guide/router-deprecated.jade b/public/docs/ts/latest/guide/router-deprecated.jade index d55523a082..35c485bb7f 100644 --- a/public/docs/ts/latest/guide/router-deprecated.jade +++ b/public/docs/ts/latest/guide/router-deprecated.jade @@ -1465,7 +1465,7 @@ code-example(format=".", language="bash"). .l-sub-section :marked - Learn about the [APP_BASE_HREF](../api/router/APP_BASE_HREF-let.html) + Learn about the [APP_BASE_HREF](../api/router-deprecated/index/APP_BASE_HREF-let.html) in the API Guide. :marked ### *HashLocationStrategy* diff --git a/public/docs/ts/latest/guide/server-communication.jade b/public/docs/ts/latest/guide/server-communication.jade index ada653e58f..c254ff9377 100644 --- a/public/docs/ts/latest/guide/server-communication.jade +++ b/public/docs/ts/latest/guide/server-communication.jade @@ -392,7 +392,7 @@ code-example(format="." language="javascript"). +ifDocsFor('ts') :marked - [Headers](../api/http/Headers-class.html) are one of the [RequestOptions](../api/http/RequestOptions-class.html). + [Headers](../api/http/index/Headers-class.html) are one of the [RequestOptions](../api/http/index/RequestOptions-class.html). Compose the options object and pass it in as the *third* parameter of the `post` method, as shown above. :marked diff --git a/public/docs/ts/latest/guide/style-guide.jade b/public/docs/ts/latest/guide/style-guide.jade index e24feff721..0a166fa6c3 100644 --- a/public/docs/ts/latest/guide/style-guide.jade +++ b/public/docs/ts/latest/guide/style-guide.jade @@ -63,7 +63,7 @@ a(id='toc') :marked ## Single Responsibility - We apply the [Single Responsibility Principle](https:\/\/en.wikipedia.org/wiki/Single_responsibility_principle) to all Components, Services, and other symbols we create. This helps make our app cleaner, easier to read and maintain, and more testable. + We apply the [Single Responsibility Principle](https://wikipedia.org/wiki/Single_responsibility_principle) to all Components, Services, and other symbols we create. This helps make our app cleaner, easier to read and maintain, and more testable. ### Rule of One #### Style 01-01 From 50b51f6bdce468f690ba19d93b952c9b146dd9fe Mon Sep 17 00:00:00 2001 From: Foxandxss Date: Thu, 7 Jul 2016 00:04:19 +0200 Subject: [PATCH 07/25] docs(router): fix broken links in router chapters closes #1843 --- public/docs/ts/latest/guide/router-deprecated.jade | 2 +- public/docs/ts/latest/guide/router.jade | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/docs/ts/latest/guide/router-deprecated.jade b/public/docs/ts/latest/guide/router-deprecated.jade index 35c485bb7f..5e758ce887 100644 --- a/public/docs/ts/latest/guide/router-deprecated.jade +++ b/public/docs/ts/latest/guide/router-deprecated.jade @@ -1465,7 +1465,7 @@ code-example(format=".", language="bash"). .l-sub-section :marked - Learn about the [APP_BASE_HREF](../api/router-deprecated/index/APP_BASE_HREF-let.html) + Learn about the [APP_BASE_HREF](../api/common/index/APP_BASE_HREF-let.html) in the API Guide. :marked ### *HashLocationStrategy* diff --git a/public/docs/ts/latest/guide/router.jade b/public/docs/ts/latest/guide/router.jade index 3d67dc1622..c3199aff0c 100644 --- a/public/docs/ts/latest/guide/router.jade +++ b/public/docs/ts/latest/guide/router.jade @@ -361,7 +361,7 @@ h4#define-routes Define routes Our first configuration defines an array of two routes with simple paths leading to the `CrisisListComponent` and `HeroListComponent` components. - Each definition translates to a [Route](../api/router/index/Route-class.html) object which has a + Each definition translates to a [Route](../api/router/index/Route-interface.html) object which has a `path`, the URL path segment for this route, and a `component`, the component associated with this route. From 961f5c8994057e70d5fda457683b2cebee1a3870 Mon Sep 17 00:00:00 2001 From: Foxandxss Date: Thu, 7 Jul 2016 12:07:31 +0200 Subject: [PATCH 08/25] chore: make animation test wait a bit longer closes #1844 --- public/docs/_examples/animations/e2e-spec.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/public/docs/_examples/animations/e2e-spec.ts b/public/docs/_examples/animations/e2e-spec.ts index 2450e7699b..e2e9b64b9b 100644 --- a/public/docs/_examples/animations/e2e-spec.ts +++ b/public/docs/_examples/animations/e2e-spec.ts @@ -255,7 +255,7 @@ describe('Animation Tests', () => { expect(li.getCssValue('transform')).toMatch(NO_TRANSFORM_MATRIX_REGEX); expect(li.getCssValue('opacity')).toMatch('1'); - removeHero(); + removeHero(700); expect(li.isPresent()).toBe(false); }); @@ -289,19 +289,22 @@ describe('Animation Tests', () => { }); }); - function addActiveHero() { + function addActiveHero(sleep?: number) { + sleep = sleep || 500; element(by.buttonText('Add active hero')).click(); - browser.driver.sleep(500); + browser.driver.sleep(sleep); } - function addInactiveHero() { + function addInactiveHero(sleep?: number) { + sleep = sleep || 500; element(by.buttonText('Add inactive hero')).click(); - browser.driver.sleep(500); + browser.driver.sleep(sleep); } - function removeHero() { + function removeHero(sleep?: number) { + sleep = sleep || 500; element(by.buttonText('Remove hero')).click(); - browser.driver.sleep(500); + browser.driver.sleep(sleep); } function getScaleX(el: protractor.ElementFinder) { From f15b40f513d40bb55f8dc6e921d8f91ccd8af723 Mon Sep 17 00:00:00 2001 From: Sekib Omazic Date: Mon, 11 Jul 2016 12:17:40 +0200 Subject: [PATCH 09/25] fix(package.webpack.json): add angular2-template-loader closes #1864 Add missing angular2-template-loader dependency --- public/docs/_examples/webpack/ts/package.webpack.json | 1 + 1 file changed, 1 insertion(+) diff --git a/public/docs/_examples/webpack/ts/package.webpack.json b/public/docs/_examples/webpack/ts/package.webpack.json index 8d7fa67496..e383ba3355 100644 --- a/public/docs/_examples/webpack/ts/package.webpack.json +++ b/public/docs/_examples/webpack/ts/package.webpack.json @@ -24,6 +24,7 @@ "zone.js": "0.6.12" }, "devDependencies": { + "angular2-template-loader": "^0.4.0", "css-loader": "^0.23.1", "extract-text-webpack-plugin": "^1.0.1", "file-loader": "^0.8.5", From b669e30187356c7a6ff64add8f7c5d3c939f0a06 Mon Sep 17 00:00:00 2001 From: Thomas Shafer Date: Fri, 8 Jul 2016 10:29:21 -0700 Subject: [PATCH 10/25] docs(toh-4): change var keyword to const for HEROES constant closes #1858 HEROES is a `const` and is defined as a `const` originally: https://github.com/angular/angular.io/blob/master/public/docs/_examples/toh-2/ts/app/app.component.ts#L10 --- public/docs/_examples/toh-4/ts/app/mock-heroes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/docs/_examples/toh-4/ts/app/mock-heroes.ts b/public/docs/_examples/toh-4/ts/app/mock-heroes.ts index 69afde3d34..6f7c5d83a0 100644 --- a/public/docs/_examples/toh-4/ts/app/mock-heroes.ts +++ b/public/docs/_examples/toh-4/ts/app/mock-heroes.ts @@ -1,7 +1,7 @@ // #docregion import { Hero } from './hero'; -export var HEROES: Hero[] = [ +export const HEROES: Hero[] = [ {id: 11, name: 'Mr. Nice'}, {id: 12, name: 'Narco'}, {id: 13, name: 'Bombasto'}, From be23e90095003ff806f03ebe14a409fc9d66743b Mon Sep 17 00:00:00 2001 From: Naomi Black Date: Mon, 11 Jul 2016 22:38:25 -0700 Subject: [PATCH 11/25] launch(china): announce angular.cn --- public/_includes/_footer.jade | 2 +- public/_includes/_hero-home.jade | 9 ++++++++- public/news.jade | 16 ++++++++-------- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/public/_includes/_footer.jade b/public/_includes/_footer.jade index 4fc97501c9..7f77d739f3 100644 --- a/public/_includes/_footer.jade +++ b/public/_includes/_footer.jade @@ -49,7 +49,7 @@ else h3.text-headline LANGUAGES ul.text-body - li 中文版 + li 中文版 footer(class="background-steel") small.text-caption Powered by Google ©2010-2016. Code licensed under an MIT-style License. Documentation licensed under CC BY 4.0. diff --git a/public/_includes/_hero-home.jade b/public/_includes/_hero-home.jade index 7fdccb9f29..176d94e207 100644 --- a/public/_includes/_hero-home.jade +++ b/public/_includes/_hero-home.jade @@ -3,4 +3,11 @@ header(class="background-sky") h1.text-headline.hero-logo #{title}
    #{subtitle} .hero-cta - a(href="/docs/ts/latest/quickstart.html" class="md-raised button button-large button-plain" md-button) Get Started \ No newline at end of file + a(href="/docs/ts/latest/quickstart.html" class="md-raised button button-large button-plain" md-button) Get Started + + .banner.banner-floaty + .banner-ng-annoucement + div(class="banner-text" align="center") + p Angular Content in Chinese
    Angular中文内容 + div(class="banner-button") + a(href="https://angular.cn" target="_blank" class="button md-button") Visit angular.cn \ No newline at end of file diff --git a/public/news.jade b/public/news.jade index 5fb3ea3766..182fd5a279 100644 --- a/public/news.jade +++ b/public/news.jade @@ -44,7 +44,7 @@ target="_blank" href="http://www.bennadel.com/blog/3116-using-an-item-template-with-an-html-dropdown-menu-component-in-angular-2-rc-3.htm" ) Using An Item Template With An HTML Dropdown Menu Component - p A while ago, I played around with trying to create an HTML Dropdown menu component in Angular 2. I discovered that you could pass Template references into components for dynamic rendering.... + p A while ago, I played around with trying to create an HTML Dropdown menu component in Angular 2. I discovered that you could pass Template references into components for dynamic rendering... .author img(src="/resources/images/bios/shield-bio-placeholder.png") .posted Posted by Ben Nadel @@ -70,23 +70,23 @@ target="_blank" href="http://blog.mgechev.com/2016/06/26/tree-shaking-angular2-production-build-rollup-javascript/" ) Building an Angular 2 Application for Production - p During the keynote of ng-conf, the core team managed to drop the size of the “Hello world!” app to less than 50K! In this blog post we’ll explain all the steps we need to go through in order to achieve such results!. + p During the keynote of ng-conf, the core team managed to drop the size of the “Hello world!” app to less than 50K! In this blog post we’ll explain all the steps we need to go through in order to achieve such results! .author img(src="/resources/images/bios/shield-bio-placeholder.png") .posted Posted by Minko Gechev .c6 .article-card - .date June 14, 2016 + .date June 22, 2016 .title a( target="_blank" - href="http://blog.thoughtram.io/angular/2016/06/14/routing-in-angular-2-revisited.html" - ) Routing in Angular 2 Revisited - p Just recently, the Angular team announced yet another version of the new router. Take a first look at the new and better APIs, touching on the most common scenarios... + href="https://mp.weixin.qq.com/s?__biz=MzIwNjQwMzUwMQ==&mid=2247483837&idx=1&sn=932b359504eec2ae50a3bcba2964b3c2&scene=2&srcid=0622Tab8nj3W3cAkphohB8wM" + ) Why I chose Angular 2 / 我为什么选择Angular 2 (in Chinese) + p Ralph Wang, a senior developer with 18 years’ experience in China, tells why he chooses Angular 2. No choice is painful, but too many choices can be chaotic and cause even more pain... .author - img(src="/resources/images/bios/pascalprecht.jpg") - .posted Posted by Pascal Precht + img(src="/resources/images/bios/angular-gde-bio-placeholder.png") + .posted Posted by Ralph Wang .grid-fluid.l-space-bottom-2.l-space-top-4 From 9aa664a49d70695b4b396b5437c069b2bdbf6f89 Mon Sep 17 00:00:00 2001 From: Naomi Black Date: Mon, 11 Jul 2016 22:54:00 -0700 Subject: [PATCH 12/25] chore(news): add link to china blog announcment --- public/news.jade | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/public/news.jade b/public/news.jade index 182fd5a279..9f1c60923c 100644 --- a/public/news.jade +++ b/public/news.jade @@ -4,6 +4,19 @@ .clear .grid-fluid + .c6 + .article-card + .date July 11, 2016 + .title + a( + target="_blank" + href="http://angularjs.blogspot.com/2016/07/angular-in-china-and-beyond-introducing.html" + ) Angular in China and beyond: Introducing angular.cn + p We're excited to share the newly-launched angular.cn with you! Read on to learn how we did it, and how you can get involved in bringing Angular to your locale.... + + .author + img(src="/resources/images/bios/naomi.jpg") + .posted Posted by Naomi Black .c6 .article-card .date June 30, 2016 @@ -17,20 +30,6 @@ img(src="/resources/images/bios/stephenfluin.jpg") .posted Posted by Stephen Fluin - .c6 - .article-card - .date June 21, 2016 - .title - a( - target="_blank" - href="http://angularjs.blogspot.com/2016/06/rc3-now-available.html" - ) RC3 Now Available - p Today we’re happy to announce that we are shipping Angular 2.0.0-rc3. This release includes a fix for a major performance regression in RC2... - - .author - img(src="/resources/images/bios/stephenfluin.jpg") - .posted Posted by Stephen Fluin - .grid-fluid.l-space-bottom-2.l-space-top-4 .c12.text-center h3.text-headline.text-uppercase Developer Community From 5da6dff3ecdf42e41e0345312b3bf83702651337 Mon Sep 17 00:00:00 2001 From: Naomi Black Date: Mon, 11 Jul 2016 23:03:01 -0700 Subject: [PATCH 13/25] launch(chinese): update the banner translation --- public/_includes/_hero-home.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/_includes/_hero-home.jade b/public/_includes/_hero-home.jade index 176d94e207..5b94c046e0 100644 --- a/public/_includes/_hero-home.jade +++ b/public/_includes/_hero-home.jade @@ -8,6 +8,6 @@ header(class="background-sky") .banner.banner-floaty .banner-ng-annoucement div(class="banner-text" align="center") - p Angular Content in Chinese
    Angular中文内容 + p Angular Content in Chinese
    Angular 中文资源 div(class="banner-button") a(href="https://angular.cn" target="_blank" class="button md-button") Visit angular.cn \ No newline at end of file From aacab562cb86225645b02a2dc3aa1a3db4ca23a7 Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Tue, 12 Jul 2016 13:40:27 -0700 Subject: [PATCH 14/25] chore(check-deploy): update dgeni to v.0.13.1 See angular issue https://github.com/angular/angular/issues/9990 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2645f4a367..44d1d2da1a 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "codelyzer": "0.0.22", "del": "^2.2.0", "dgeni": "^0.4.0", - "dgeni-packages": "^0.13.0", + "dgeni-packages": "^0.13.1", "diff": "^2.1.3", "fs-extra": "^0.30.0", "globby": "^4.0.0", From 253ab01031b14943a89db4930de0b21ef1017622 Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Thu, 14 Jul 2016 12:27:11 -0700 Subject: [PATCH 15/25] chore(gulpfile): add install-example-angular task to install build packages Use build packages: gulp install-example-angular --build Restore release packages: gulp install-example-angular Documented the command in the README --- README.md | 15 +++++++++++++++ gulpfile.js | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1e0d3095f5..ea535d755a 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,21 @@ Also, there is a script available for Linux and OSX users that will setup the pr - `./scripts/install.sh` +### Run with current build instead of release packages +Can switch the `@angular` packages in `~/public/docs/_examples/node_modules` to the current build packages with +``` +gulp install-example-angular --build +``` +Restore to RELEASE packages with +``` +gulp install-example-angular +``` +>These commands will fail if something is locking any of the packages ... as an IDE often does. +> +>The symptom typically is an error trying to `rm -rf node_modules/@angular`. +> +>_Solution_: unlock the hold on the package(s). In VS Code, re-load the window (`cmd-P` then enter `>relow`). + ## Technology Used - Angular 1.x: The production ready version of Angular diff --git a/gulpfile.js b/gulpfile.js index dc10189b26..464e68c010 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -451,6 +451,34 @@ gulp.task('remove-example-boilerplate', function() { deleteExampleBoilerPlate(); }); +// Npm install Angular libraries into examples/node_modules, +// either release or current build packages +// Examples: +// gulp install-example-angular --build // use current build packages +// gulp install-example-angular // restore release packages +gulp.task('install-example-angular', installExampleAngular); + +function installExampleAngular() { + var sources; + var template; + var libs = [ + 'core', 'common', 'compiler', + 'platform-browser', 'platform-browser-dynamic', + 'forms', 'http', 'router']; + + // Like: "angular/core-builds" or "@angular/core" + sources = libs.map( lib => argv.build ? `angular/${lib}-builds` : `@angular/${lib}`); + + gutil.log(`Installing Angular npm packages from ${argv.build ? 'BUILD' : 'RELEASE'}`); + + var spawnInfo = spawnExt('rm', ['-rf', 'node_modules/@angular'], { cwd: EXAMPLES_PATH}); + return spawnInfo.promise + .then(() => { + spawnInfo = spawnExt('npm', ['install', ...sources], {cwd: EXAMPLES_PATH}); + return spawnInfo.promise + }); +} + // deletes boilerplate files that were added by copyExampleBoilerplate // from locations where an example app is found gulp.task('_delete-example-boilerplate', deleteExampleBoilerPlate); @@ -602,7 +630,7 @@ gulp.task('link-checker', function(done) { '*/dart/latest/api/*', // Somehow the link checker sees ng1 {{...}} in the resource page; ignore it 'resources/%7B%7Bresource.url%7D%7D', - // API docs have links directly into GitHub repo sources; these can + // API docs have links directly into GitHub repo sources; these can // quickly become invalid, so ignore them for now: '*/angular/tree/*' ]; @@ -786,7 +814,7 @@ function linkChecker(options) { var outputFile = path.join(process.cwd(), 'link-checker-results.txt'); var header = 'Link checker results for: ' + siteUrl + '\nStarted: ' + (new Date()).toLocaleString() + - '\nExcluded links (blc file globs): ' + blcOptions.excludedKeywords + + '\nExcluded links (blc file globs): ' + blcOptions.excludedKeywords + '\nExcluded links (custom --exclude-bad regex): ' + excludeBad.toString() + '\n\n'; gutil.log(header); fs.writeFileSync(outputFile, header); From 02cd26bda6b41b5939011f6cb3c3e58ba61c40bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesu=CC=81s=20Rodri=CC=81guez?= Date: Thu, 14 Jul 2016 21:35:06 +0200 Subject: [PATCH 16/25] chore: install upgrade with install-example-angular --- gulpfile.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gulpfile.js b/gulpfile.js index 464e68c010..41bfdf83a3 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -464,11 +464,13 @@ function installExampleAngular() { var libs = [ 'core', 'common', 'compiler', 'platform-browser', 'platform-browser-dynamic', - 'forms', 'http', 'router']; + 'forms', 'http', 'router', 'upgrade']; // Like: "angular/core-builds" or "@angular/core" sources = libs.map( lib => argv.build ? `angular/${lib}-builds` : `@angular/${lib}`); + sources.push('@angular/router-deprecated'); + gutil.log(`Installing Angular npm packages from ${argv.build ? 'BUILD' : 'RELEASE'}`); var spawnInfo = spawnExt('rm', ['-rf', 'node_modules/@angular'], { cwd: EXAMPLES_PATH}); From 8ddc93d21180c40ac49de1cc773a74d1ebb9f4f6 Mon Sep 17 00:00:00 2001 From: Foxandxss Date: Fri, 8 Jul 2016 17:49:06 +0200 Subject: [PATCH 17/25] docs(style-guide): create a route redirection closes #1857 --- public/docs/_examples/style-guide/ts/app/app.routes.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/public/docs/_examples/style-guide/ts/app/app.routes.ts b/public/docs/_examples/style-guide/ts/app/app.routes.ts index d3799a9390..644e86bffd 100644 --- a/public/docs/_examples/style-guide/ts/app/app.routes.ts +++ b/public/docs/_examples/style-guide/ts/app/app.routes.ts @@ -28,6 +28,7 @@ import { AppComponent as S0704 } from '../07-04/app'; import { AppComponent as S0901 } from '../09-01/app'; const routes: RouterConfig = [ + { path: '', redirectTo: '/01-01', pathMatch: 'full' }, { path: '01-01', component: S0101 }, { path: '02-07', component: S0207 }, { path: '02-08', component: S0208 }, From abd860c3cae99e926b9036b263861a650f55a050 Mon Sep 17 00:00:00 2001 From: Foxandxss Date: Wed, 6 Jul 2016 18:19:10 +0200 Subject: [PATCH 18/25] chore: update testing example to RC4 closes #1839 --- .../testing/ts/app/app.component.spec.ts | 7 +- .../testing/ts/app/bad-tests.spec.ts | 16 ++-- .../docs/_examples/testing/ts/app/bag.spec.ts | 91 +++++-------------- .../ts/app/dashboard.component.spec.ts | 16 ++-- .../_examples/testing/ts/app/expect-proper.ts | 9 -- .../testing/ts/app/http-hero.service.spec.ts | 16 ++-- 6 files changed, 49 insertions(+), 106 deletions(-) delete mode 100644 public/docs/_examples/testing/ts/app/expect-proper.ts diff --git a/public/docs/_examples/testing/ts/app/app.component.spec.ts b/public/docs/_examples/testing/ts/app/app.component.spec.ts index 9cf6d82e1a..f6c30b0e76 100644 --- a/public/docs/_examples/testing/ts/app/app.component.spec.ts +++ b/public/docs/_examples/testing/ts/app/app.component.spec.ts @@ -5,13 +5,10 @@ import { By } from '@angular/platform-browser'; import { DebugElement } from '@angular/core'; import { - beforeEach, beforeEachProviders, - describe, ddescribe, xdescribe, - expect, it, iit, xit, async, inject } from '@angular/core/testing'; -import { ComponentFixture, TestComponentBuilder } from '@angular/compiler/testing'; +import { ComponentFixture, TestComponentBuilder } from '@angular/core/testing'; import { Hero, HeroService, MockHeroService } from './mock-hero.service'; @@ -45,7 +42,7 @@ describe('AppComponent', () => { it('can get title from template', () => { fixture.detectChanges(); let titleEl = fixture.debugElement.query(By.css('h1')).nativeElement; - expect(titleEl).toHaveText(comp.title); + expect(titleEl.textContent).toContain(comp.title); }); it('can get RouterLinks from template', () => { diff --git a/public/docs/_examples/testing/ts/app/bad-tests.spec.ts b/public/docs/_examples/testing/ts/app/bad-tests.spec.ts index 1251185160..d73882372c 100644 --- a/public/docs/_examples/testing/ts/app/bad-tests.spec.ts +++ b/public/docs/_examples/testing/ts/app/bad-tests.spec.ts @@ -19,13 +19,11 @@ import { DebugElement } from '@angular/core'; import { By } from '@angular/platform-browser'; import { - beforeEach, beforeEachProviders, - describe, ddescribe, xdescribe, - expect, it, iit, xit, + addProviders, async, inject } from '@angular/core/testing'; -import { ComponentFixture, TestComponentBuilder } from '@angular/compiler/testing'; +import { ComponentFixture, TestComponentBuilder } from '@angular/core/testing'; import { ViewMetadata } from '@angular/core'; import { Observable } from 'rxjs/Rx'; @@ -143,20 +141,20 @@ xdescribe('async & inject testing errors', () => { restoreJasmineIt(); }, 10000); - describe('using beforeEachProviders', () => { - beforeEachProviders(() => [{ provide: FancyService, useValue: new FancyService() }]); + describe('using addProviders', () => { + addProviders([{ provide: FancyService, useValue: new FancyService() }]); beforeEach( inject([FancyService], (service: FancyService) => { expect(service.value).toEqual('real value'); })); - describe('nested beforeEachProviders', () => { + describe('nested addProviders', () => { it('should fail when the injector has already been used', () => { patchJasmineBeforeEach(); expect(() => { - beforeEachProviders(() => [{ provide: FancyService, useValue: new FancyService() }]); + addProviders([{ provide: FancyService, useValue: new FancyService() }]); }) - .toThrowError('beforeEachProviders was called after the injector had been used ' + + .toThrowError('addProviders was called after the injector had been used ' + 'in a beforeEach or it block. This invalidates the test injector'); restoreJasmineBeforeEach(); }); diff --git a/public/docs/_examples/testing/ts/app/bag.spec.ts b/public/docs/_examples/testing/ts/app/bag.spec.ts index 80790fca67..7218e91f1b 100644 --- a/public/docs/_examples/testing/ts/app/bag.spec.ts +++ b/public/docs/_examples/testing/ts/app/bag.spec.ts @@ -1,7 +1,7 @@ // Based on https://github.com/angular/angular/blob/master/modules/angular2/test/testing/testing_public_spec.ts /* tslint:disable */ import { - BadTemplateUrl, ButtonComp, + ButtonComp, ChildChildComp, ChildComp, ChildWithChildComp, ExternalTemplateComp, FancyService, MockFancyService, @@ -16,14 +16,12 @@ import { DebugElement } from '@angular/core'; import { By } from '@angular/platform-browser'; import { - beforeEach, beforeEachProviders, - describe, ddescribe, xdescribe, - expect, it, iit, xit, - async, inject, + addProviders, + inject, async, fakeAsync, tick, withProviders } from '@angular/core/testing'; -import { ComponentFixture, TestComponentBuilder } from '@angular/compiler/testing'; +import { ComponentFixture, TestComponentBuilder } from '@angular/core/testing'; import { ViewMetadata } from '@angular/core'; @@ -31,47 +29,6 @@ import { Observable } from 'rxjs/Rx'; //////// SPECS ///////////// -/// Verify can use Angular testing's DOM abstraction to access DOM - -describe('angular2 jasmine matchers', () => { - describe('toHaveCssClass', () => { - it('should assert that the CSS class is present', () => { - let el = document.createElement('div'); - el.classList.add('bombasto'); - expect(el).toHaveCssClass('bombasto'); - }); - - it('should assert that the CSS class is not present', () => { - let el = document.createElement('div'); - el.classList.add('bombasto'); - expect(el).not.toHaveCssClass('fatias'); - }); - }); - - describe('toHaveCssStyle', () => { - it('should assert that the CSS style is present', () => { - let el = document.createElement('div'); - expect(el).not.toHaveCssStyle('width'); - - el.style.setProperty('width', '100px'); - expect(el).toHaveCssStyle('width'); - }); - - it('should assert that the styles are matched against the element', () => { - let el = document.createElement('div'); - expect(el).not.toHaveCssStyle({width: '100px', height: '555px'}); - - el.style.setProperty('width', '100px'); - expect(el).toHaveCssStyle({width: '100px'}); - expect(el).not.toHaveCssStyle({width: '100px', height: '555px'}); - - el.style.setProperty('height', '555px'); - expect(el).toHaveCssStyle({height: '555px'}); - expect(el).toHaveCssStyle({width: '100px', height: '555px'}); - }); - }); -}); - describe('using the async helper', () => { let actuallyDone = false; @@ -101,7 +58,7 @@ describe('using the async helper', () => { p.catch(() => { actuallyDone = true; }); })); - it('should run async test with successful Observable', async(() => { + xit('should run async test with successful Observable', async(() => { let source = Observable.of(true).delay(10); source.subscribe( val => {}, @@ -114,9 +71,11 @@ describe('using the async helper', () => { describe('using the test injector with the inject helper', () => { describe('setting up Providers with FancyService', () => { - beforeEachProviders(() => [ - { provide: FancyService, useValue: new FancyService() } - ]); + beforeEach(() => { + addProviders([ + { provide: FancyService, useValue: new FancyService() } + ]); + }); it('should use FancyService', inject([FancyService], (service: FancyService) => { @@ -142,7 +101,7 @@ describe('using the test injector with the inject helper', () => { ); }))); - it('test should wait for FancyService.getObservableDelayValue', + xit('test should wait for FancyService.getObservableDelayValue', async(inject([FancyService], (service: FancyService) => { service.getObservableDelayValue().subscribe( value => { expect(value).toEqual('observable delay value'); } @@ -197,7 +156,7 @@ describe('test component builder', function() { tcb.createAsync(ChildComp).then(fixture => { fixture.detectChanges(); - expect(fixture.nativeElement).toHaveText('Original Child'); + expect(fixture.nativeElement.textContent).toContain('Original Child'); }); }))); @@ -206,11 +165,11 @@ describe('test component builder', function() { tcb.createAsync(MyIfComp).then(fixture => { fixture.detectChanges(); - expect(fixture.nativeElement).toHaveText('MyIf()'); + expect(fixture.nativeElement.textContent).toContain('MyIf()'); fixture.debugElement.componentInstance.showMore = true; fixture.detectChanges(); - expect(fixture.nativeElement).toHaveText('MyIf(More)'); + expect(fixture.nativeElement.textContent).toContain('MyIf(More)'); }); }))); @@ -262,7 +221,7 @@ describe('test component builder', function() { .createAsync(MockChildComp) .then(fixture => { fixture.detectChanges(); - expect(fixture.nativeElement).toHaveText('Mock'); + expect(fixture.nativeElement.textContent).toContain('Mock'); }); }))); @@ -276,7 +235,7 @@ describe('test component builder', function() { .createAsync(ChildComp) .then(fixture => { fixture.detectChanges(); - expect(fixture.nativeElement).toHaveText('Modified Child'); + expect(fixture.nativeElement.textContent).toContain('Modified Child'); }); }))); @@ -288,7 +247,7 @@ describe('test component builder', function() { .createAsync(ParentComp) .then(fixture => { fixture.detectChanges(); - expect(fixture.nativeElement).toHaveText('Parent(Mock)'); + expect(fixture.nativeElement.textContent).toContain('Parent(Mock)'); }); }))); @@ -302,8 +261,8 @@ describe('test component builder', function() { .createAsync(ParentComp) .then(fixture => { fixture.detectChanges(); - expect(fixture.nativeElement) - .toHaveText('Parent(Original Child(ChildChild Mock))'); + expect(fixture.nativeElement.textContent) + .toContain('Parent(Original Child(ChildChild Mock))'); }); }))); @@ -318,8 +277,8 @@ describe('test component builder', function() { .createAsync(TestProvidersComp) .then(fixture => { fixture.detectChanges(); - expect(fixture.nativeElement) - .toHaveText('injected value: mocked out value'); + expect(fixture.nativeElement.textContent) + .toContain('injected value: mocked out value'); }); }))); @@ -333,8 +292,8 @@ describe('test component builder', function() { .createAsync(TestViewProvidersComp) .then(fixture => { fixture.detectChanges(); - expect(fixture.nativeElement) - .toHaveText('injected value: mocked out value'); + expect(fixture.nativeElement.textContent) + .toContain('injected value: mocked out value'); }); }))); @@ -344,8 +303,8 @@ describe('test component builder', function() { tcb.createAsync(ExternalTemplateComp) .then(fixture => { fixture.detectChanges(); - expect(fixture.nativeElement) - .toHaveText('from external template\n'); + expect(fixture.nativeElement.textContent) + .toContain('from external template\n'); }); })), 10000); // Long timeout because this test makes an actual XHR. diff --git a/public/docs/_examples/testing/ts/app/dashboard.component.spec.ts b/public/docs/_examples/testing/ts/app/dashboard.component.spec.ts index 803ea00535..1b573c32f3 100644 --- a/public/docs/_examples/testing/ts/app/dashboard.component.spec.ts +++ b/public/docs/_examples/testing/ts/app/dashboard.component.spec.ts @@ -4,13 +4,11 @@ import { DashboardComponent } from './dashboard.component'; import { By } from '@angular/platform-browser'; import { - beforeEach, beforeEachProviders, - describe, ddescribe, xdescribe, - expect, it, iit, xit, + addProviders, async, inject } from '@angular/core/testing'; -import { ComponentFixture, TestComponentBuilder } from '@angular/compiler/testing'; +import { ComponentFixture, TestComponentBuilder } from '@angular/core/testing'; import { Hero, HeroService, MockHeroService } from './mock-hero.service'; import { Router, MockRouter } from './mock-router'; @@ -70,13 +68,13 @@ describe('DashboardComponent', () => { let comp: DashboardComponent; let mockHeroService: MockHeroService; - beforeEachProviders(() => { + beforeEach(() => { mockHeroService = new MockHeroService(); - return [ + addProviders([ { provide: Router, useClass: MockRouter}, { provide: MockRouter, useExisting: Router}, { provide: HeroService, useValue: mockHeroService } - ]; + ]); }); it('can instantiate it', @@ -138,8 +136,8 @@ describe('DashboardComponent', () => { expect(heroNames.length).toEqual(4, 'should display 4 heroes'); // the 4th displayed hero should be the 5th mock hero - expect(heroNames[3].nativeElement) - .toHaveText(mockHeroService.mockHeroes[4].name); + expect(heroNames[3].nativeElement.textContent) + .toContain(mockHeroService.mockHeroes[4].name); }); }); diff --git a/public/docs/_examples/testing/ts/app/expect-proper.ts b/public/docs/_examples/testing/ts/app/expect-proper.ts deleted file mode 100644 index 77f3deb928..0000000000 --- a/public/docs/_examples/testing/ts/app/expect-proper.ts +++ /dev/null @@ -1,9 +0,0 @@ -// See https://github.com/angular/angular/issues/9017 -import { expect as expectCore } from '@angular/core/testing'; -import { NgMatchers } from '@angular/platform-browser/testing'; - -export function expect(spy: Function): NgMatchers; -export function expect(actual: any): NgMatchers; -export function expect(actual: any): NgMatchers { - return expectCore(actual) as NgMatchers; -} diff --git a/public/docs/_examples/testing/ts/app/http-hero.service.spec.ts b/public/docs/_examples/testing/ts/app/http-hero.service.spec.ts index 0c79f7f3aa..375efde560 100644 --- a/public/docs/_examples/testing/ts/app/http-hero.service.spec.ts +++ b/public/docs/_examples/testing/ts/app/http-hero.service.spec.ts @@ -1,12 +1,10 @@ /* tslint:disable:no-unused-variable */ import { - beforeEach, beforeEachProviders, - describe, ddescribe, xdescribe, - expect, it, iit, xit, + addProviders, async, inject, withProviders } from '@angular/core/testing'; -import { TestComponentBuilder } from '@angular/compiler/testing'; +import { TestComponentBuilder } from '@angular/core/testing'; import { MockBackend, @@ -42,10 +40,12 @@ const makeResponseData = (data: {}) => {return { data }; }; //////// SPECS ///////////// describe('Http-HeroService (mockBackend)', () => { - beforeEachProviders(() => [ - HTTP_PROVIDERS, - { provide: XHRBackend, useClass: MockBackend } - ]); + beforeEach(() => { + addProviders([ + HTTP_PROVIDERS, + { provide: XHRBackend, useClass: MockBackend } + ]); + }); it('can instantiate service when inject service', withProviders(() => [HeroService]) From abe9dbe09252ea2af722c8399c285043cb936b87 Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Mon, 11 Jul 2016 15:54:29 +0100 Subject: [PATCH 19/25] chore(ci): add check-deploy to CI closes #1867 --- .travis.yml | 20 ++++++++++++-------- README.md | 4 ++-- gulpfile.js | 14 +++++++------- scripts/deploy-install-preview.sh | 6 ++++++ scripts/deploy-install.sh | 5 +++++ scripts/examples-install-preview.sh | 6 ++++++ scripts/{install.sh => examples-install.sh} | 1 - 7 files changed, 38 insertions(+), 18 deletions(-) create mode 100755 scripts/deploy-install-preview.sh create mode 100755 scripts/deploy-install.sh create mode 100755 scripts/examples-install-preview.sh rename scripts/{install.sh => examples-install.sh} (91%) diff --git a/.travis.yml b/.travis.yml index b0f7d92a6a..c6cadbafa5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,20 +10,24 @@ env: - DBUS_SESSION_BUS_ADDRESS=/dev/null - DISPLAY=:99.0 - CHROME_BIN=chromium-browser + - LATEST_RELEASE=2.0.0-rc.4 matrix: - - SCRIPT=lint - - SCRIPT="run-e2e-tests --fast" - - SCRIPT="run-e2e-tests --fast" PREVIEW=true + - TASK=lint + - TASK="run-e2e-tests --fast" SCRIPT=examples-install.sh + - TASK="run-e2e-tests --fast" SCRIPT=examples-install-preview.sh + - TASK=harp-compile SCRIPT=deploy-install.sh + - TASK=harp-compile SCRIPT=deploy-install-preview.sh matrix: fast_finish: true allow_failures: - - env: "SCRIPT=\"run-e2e-tests --fast\" PREVIEW=true" + - env: "TASK=\"run-e2e-tests --fast\" SCRIPT=examples-install-preview.sh" + - env: "TASK=harp-compile SCRIPT=deploy-install-preview.sh" before_install: - npm install -g gulp --no-optional +install: + - npm install --no-optional + - if [[ $SCRIPT ]]; then ./scripts/$SCRIPT; fi before_script: - sh -e /etc/init.d/xvfb start -install: - - ./scripts/install.sh - - if [[ $PREVIEW == true ]]; then npm install --prefix public/docs/_examples angular/{core,common,compiler,platform-browser,platform-browser-dynamic,http,forms,router-deprecated,router,upgrade}-builds; fi script: - - gulp $SCRIPT + - gulp $TASK diff --git a/README.md b/README.md index ea535d755a..5522be95c7 100644 --- a/README.md +++ b/README.md @@ -117,9 +117,9 @@ This project generates a lot of untracked files, if you wish to reset it to a mi - `git clean -xdf` -Also, there is a script available for Linux and OSX users that will setup the project using the steps shown in this section: +Also, there is a script available for Linux, OSX and Windows Gitbash users that will setup the project using the steps shown in this section: -- `./scripts/install.sh` +- `npm install --no-optional && ./scripts/examples-install.sh` ### Run with current build instead of release packages Can switch the `@angular` packages in `~/public/docs/_examples/node_modules` to the current build packages with diff --git a/gulpfile.js b/gulpfile.js index 41bfdf83a3..70a02b70be 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -594,16 +594,16 @@ gulp.task('git-changed-examples', ['_shred-devguide-examples'], function(){ }); }); +gulp.task('harp-compile', ['build-docs'], function() { + return harpCompile(); +}); + gulp.task('check-deploy', ['build-docs'], function() { return harpCompile().then(function() { gutil.log('compile ok'); - if(argv.dryRun) { - return false; - } else { - gutil.log('running live server ...'); - execPromise('npm run live-server ./www'); - return askDeploy(); - } + gutil.log('running live server ...'); + execPromise('npm run live-server ./www'); + return askDeploy(); }).then(function(shouldDeploy) { if (shouldDeploy) { gutil.log('deploying...'); diff --git a/scripts/deploy-install-preview.sh b/scripts/deploy-install-preview.sh new file mode 100755 index 0000000000..b4998f6717 --- /dev/null +++ b/scripts/deploy-install-preview.sh @@ -0,0 +1,6 @@ + #!/usr/bin/env bash + +set -ex -o pipefail + +./scripts/deploy-install.sh +(cd ../angular && git checkout master) \ No newline at end of file diff --git a/scripts/deploy-install.sh b/scripts/deploy-install.sh new file mode 100755 index 0000000000..38cf6c7d19 --- /dev/null +++ b/scripts/deploy-install.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -ex -o pipefail + +(cd ../ && git clone https://github.com/angular/angular.git --branch $LATEST_RELEASE) \ No newline at end of file diff --git a/scripts/examples-install-preview.sh b/scripts/examples-install-preview.sh new file mode 100755 index 0000000000..cd2beddd07 --- /dev/null +++ b/scripts/examples-install-preview.sh @@ -0,0 +1,6 @@ + #!/usr/bin/env bash + +set -ex -o pipefail + +./scripts/examples-install.sh +(cd public/docs/_examples && npm install angular/{core,common,compiler,platform-browser,platform-browser-dynamic,http,forms,router-deprecated,router,upgrade}-builds --no-optional) \ No newline at end of file diff --git a/scripts/install.sh b/scripts/examples-install.sh similarity index 91% rename from scripts/install.sh rename to scripts/examples-install.sh index 15c2e4c89d..2501ad2b8d 100755 --- a/scripts/install.sh +++ b/scripts/examples-install.sh @@ -2,7 +2,6 @@ set -ex -o pipefail -npm install --no-optional (cd public/docs/_examples && npm install --no-optional) (cd public/docs/_examples/_protractor && npm install --no-optional) npm run webdriver:update --prefix public/docs/_examples/_protractor From 4ff714c99f68fa12ca1ed093d26d49c3cb9a46a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Rodr=C3=ADguez?= Date: Thu, 14 Jul 2016 16:10:23 +0200 Subject: [PATCH 20/25] refactor: some changes to plunkerBuilder closes #1885 --- tools/plunker-builder/plunkerBuilder.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/tools/plunker-builder/plunkerBuilder.js b/tools/plunker-builder/plunkerBuilder.js index 7318a01857..588341d241 100644 --- a/tools/plunker-builder/plunkerBuilder.js +++ b/tools/plunker-builder/plunkerBuilder.js @@ -9,7 +9,7 @@ var mkdirp = require('mkdirp'); var indexHtmlTranslator = require('./indexHtmlTranslator'); var regionExtractor = require('../doc-shredder/regionExtractor'); -var COPYRIGHT, COPYRIGHT_JS, COPYRIGHT_HTML; +var COPYRIGHT, COPYRIGHT_JS_CSS, COPYRIGHT_HTML; var SYSTEMJS_CONFIG; // content of systemjs.config.js for plunkers that use systemjs var TSCONFIG; // content of tsconfig.json for plunkers that use systemjs @@ -32,11 +32,8 @@ function buildCopyrightStrings() { function buildPlunkers(basePath, destPath, options) { getSystemJsConfigPlunker(basePath); var errFn = options.errFn || function(e) { console.log(e); }; - var configExtns = ['plnkr.json', '*plnkr.json']; - var gpaths = configExtns.map(function(extn) { - return path.join(basePath, '**/' + extn); - }); - var fileNames = globby.sync(gpaths, { ignore: "**/node_modules/**"}); + var plunkerPaths = path.join(basePath, '**/*plnkr.json'); + var fileNames = globby.sync(plunkerPaths, { ignore: "**/node_modules/**"}); fileNames.forEach(function(configFileName) { try { buildPlunkerFrom(configFileName, basePath, destPath); @@ -51,7 +48,7 @@ function buildPlunkers(basePath, destPath, options) { // description: optional string - description of this plunker - defaults to the title in the index.html page. // tags: [] - optional array of strings // main: string - filename of what will become index.html in the plunker - defaults to index.html -function buildPlunkerFrom(configFileName, basePath, destPath ) { +function buildPlunkerFrom(configFileName, basePath, destPath) { // replace ending 'plnkr.json' with 'plnkr.no-link.html' to create output file name; var outputFileName = configFileName.substr(0, configFileName.length - 'plnkr.json'.length) + 'plnkr.no-link.html'; var altFileName; @@ -90,8 +87,7 @@ function buildPlunkerFrom(configFileName, basePath, destPath ) { function addSystemJsConfig(config, postData){ if (config.basePath.indexOf('/ts') > -1) { // uses systemjs.config.js so add plunker version - var relativeFileName = 'systemjs.config.js'; - postData['files[' + relativeFileName + ']'] = SYSTEMJS_CONFIG; + postData['files[systemjs.config.js]'] = SYSTEMJS_CONFIG; postData['files[tsconfig.json]'] = TSCONFIG; } } From a8091f5b848bd7e4195a3cb8099be73ce9abfeb4 Mon Sep 17 00:00:00 2001 From: Foxandxss Date: Fri, 8 Jul 2016 17:18:59 +0200 Subject: [PATCH 21/25] docs(style-guide): remove routing from TOC closes #1856 --- public/docs/ts/latest/guide/style-guide.jade | 1 - 1 file changed, 1 deletion(-) diff --git a/public/docs/ts/latest/guide/style-guide.jade b/public/docs/ts/latest/guide/style-guide.jade index 0a166fa6c3..0feeb5f8f8 100644 --- a/public/docs/ts/latest/guide/style-guide.jade +++ b/public/docs/ts/latest/guide/style-guide.jade @@ -56,7 +56,6 @@ a(id='toc') 1. [Services](#services) 1. [Data Services](#data-services) 1. [Lifecycle Hooks](#lifecycle-hooks) - 1. [Routing](#routing) 1. [Appendix](#appendix) .l-main-section From 4da23bfe578e5aa208bd6a438ebc5e74d5b2816f Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Thu, 7 Jul 2016 21:35:40 -0700 Subject: [PATCH 22/25] chore(api-builder): linkDevGuide -> linkDocs;linkDocs can default the lang closes #1849 1) Rename linkDevGuide to linkDocs Rename the specialized API docs `@linkDevGuide` tag to `@linkDocs` since it is meant to be used to refer to all angular.io docs, not just the developer guide. 2) let linkDocs links resolve to proper language The old linkDevGuide required URIs to be given in the form 'ts/latest/guide/architecture' which forced all language versions of the API pages to refer to the ts versions of the doc pages they linked to. This PR fixes that problem. URIs are now given in the form 'guide/architecture' and then rendered properly for each language. Of course, when needed, it is still possible to give a language specific URI. chore(api-builder): minor code cleanup --- gulpfile.js | 10 ++- tools/api-builder/links-package/index.js | 6 +- .../links-package/inline-tag-defs/example.js | 10 --- .../inline-tag-defs/linkDevGuide.js | 53 ------------- .../links-package/inline-tag-defs/linkDocs.js | 75 +++++++++++++++++++ 5 files changed, 85 insertions(+), 69 deletions(-) delete mode 100644 tools/api-builder/links-package/inline-tag-defs/linkDevGuide.js create mode 100644 tools/api-builder/links-package/inline-tag-defs/linkDocs.js diff --git a/gulpfile.js b/gulpfile.js index 70a02b70be..6f784956fb 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -403,7 +403,9 @@ gulp.task('add-example-boilerplate', function() { // copies boilerplate files to locations // where an example app is found -gulp.task('_copy-example-boilerplate', copyExampleBoilerplate); +gulp.task('_copy-example-boilerplate', function () { + if (!argv.fast) copyExampleBoilerplate(); +}); // copies boilerplate files to locations @@ -1066,7 +1068,7 @@ function buildApiDocs(targetLanguage) { try { // Build a specialized package to generate different versions of the API docs var package = new Package('apiDocs', [require(path.resolve(TOOLS_PATH, 'api-builder/angular.io-package'))]); - package.config(function(log, targetEnvironments, writeFilesProcessor, readTypeScriptModules) { + package.config(function(log, targetEnvironments, writeFilesProcessor, readTypeScriptModules, linkDocsInlineTagDef) { log.level = _dgeniLogLevel; ALLOWED_LANGUAGES.forEach(function(target) { targetEnvironments.addAllowed(target); }); if (targetLanguage) { @@ -1076,7 +1078,9 @@ function buildApiDocs(targetLanguage) { // Don't read TypeScript modules if we are not generating API docs - Dart I am looking at you! readTypeScriptModules.$enabled = false; } - writeFilesProcessor.outputFolder = targetLanguage + '/latest/api'; + linkDocsInlineTagDef.lang = targetLanguage; + linkDocsInlineTagDef.vers = 'latest'; + writeFilesProcessor.outputFolder = path.join(targetLanguage, linkDocsInlineTagDef.vers, 'api'); } }); diff --git a/tools/api-builder/links-package/index.js b/tools/api-builder/links-package/index.js index 3036c2441b..5391399055 100644 --- a/tools/api-builder/links-package/index.js +++ b/tools/api-builder/links-package/index.js @@ -3,7 +3,7 @@ var Package = require('dgeni').Package; module.exports = new Package('links', []) .factory(require('./inline-tag-defs/link')) -.factory(require('./inline-tag-defs/linkDevGuide')) +.factory(require('./inline-tag-defs/linkDocs')) .factory(require('./inline-tag-defs/example')) .factory(require('./inline-tag-defs/exampleTabs')) .factory(require('dgeni-packages/links/services/getAliases')) @@ -12,9 +12,9 @@ module.exports = new Package('links', []) .factory(require('./services/parseArgString')) .factory(require('./services/getApiFragmentFileName')) -.config(function(inlineTagProcessor, linkInlineTagDef, linkDevGuideInlineTagDef, exampleInlineTagDef, exampleTabsInlineTagDef) { +.config(function(inlineTagProcessor, linkInlineTagDef, linkDocsInlineTagDef, exampleInlineTagDef, exampleTabsInlineTagDef) { inlineTagProcessor.inlineTagDefinitions.push(linkInlineTagDef); - inlineTagProcessor.inlineTagDefinitions.push(linkDevGuideInlineTagDef); + inlineTagProcessor.inlineTagDefinitions.push(linkDocsInlineTagDef); inlineTagProcessor.inlineTagDefinitions.push(exampleInlineTagDef); inlineTagProcessor.inlineTagDefinitions.push(exampleTabsInlineTagDef); }); diff --git a/tools/api-builder/links-package/inline-tag-defs/example.js b/tools/api-builder/links-package/inline-tag-defs/example.js index caaccfd61f..1df3f0223f 100644 --- a/tools/api-builder/links-package/inline-tag-defs/example.js +++ b/tools/api-builder/links-package/inline-tag-defs/example.js @@ -40,18 +40,8 @@ module.exports = function exampleInlineTagDef(getLinkInfo, parseArgString, getAp }; }; -// Examples of what @example and @exampleTabs markup looks like in the angular/angular source. -//* -//* {@example core/application_spec.ts hello-app -title='Sample component' } -//* -//* {@exampleTabs core/application_spec.ts,core/application_spec.ts "hello-app,hello-app2" -titles="Hello app1, Hello app2" } -//* - - function quote(str) { if (str == null || str.length === 0) return str; str = str.replace("'","'\'"); return "'" + str + "'"; } - - diff --git a/tools/api-builder/links-package/inline-tag-defs/linkDevGuide.js b/tools/api-builder/links-package/inline-tag-defs/linkDevGuide.js deleted file mode 100644 index 1e40227e81..0000000000 --- a/tools/api-builder/links-package/inline-tag-defs/linkDevGuide.js +++ /dev/null @@ -1,53 +0,0 @@ -var path = require('canonical-path'); -var fs = require("fs"); -var jsonFile = require('jsonfile'); - -var INLINE_LINK = /(\S+)(?:\s+([\s\S]+))?/; - -/** - * @dgService linkDevGuideInlineTagDef - * @description - * Process inline link tags (of the form {@linkDevGuide some/uri 'Some Title'}), replacing them with HTML anchors. - * The uri should point to a jade page in the DevGuide without the .jade extension ( under public/docs ). - * If the title is omitted an attempt will be made to determine the title of the jade page being pointed to. If not found - * the the title will simply be the last part of the link. - * Examples - * {@linkDevGuide ts/latest/guide/gettingStarted } - * {@linkDevGuide js/latest/guide/gettingStarted 'Javascript version of getting started' } - * {@linkDevGuide ts/latest/guide/gettingStarted title="Typescript version of getting started" } - * @kind function - */ -module.exports = function linkDevGuideInlineTagDef(parseArgString, createDocMessage, log) { - return { - name: 'linkDevGuide', - description: 'Process inline link tags (of the form {@link some/uri "Some Title"}), replacing them with HTML anchors', - handler: function(doc, tagName, tagDescription) { - - // Parse out the uri and title - var tagArgs = parseArgString(tagDescription); - var unnamedArgs = tagArgs._; - var uri = unnamedArgs[0]; - var title = tagArgs.title || (unnamedArgs.length > 1 ? unnamedArgs[1] : null); - - var jadePath = path.join('./public/docs', uri + '.jade'); - var key = path.basename(jadePath, '.jade'); - if ( !fs.existsSync(jadePath)) { - log.warn(createDocMessage('Invalid DevGuide example (unable to locate jade file: "' + jadePath + '")', doc)); - } else { - if (!title) { - var jsonFilePath = path.join(path.dirname(jadePath), '_data.json'); - if ( fs.existsSync(jsonFilePath)) { - var jsonObj = jsonFile.readFileSync(jsonFilePath); - title = jsonObj[key] && jsonObj[key].title; - } - } - } - var url = path.join('/docs', uri + '.html'); - title = title || key || url; - - return "" + title + ""; - - } - }; -}; - diff --git a/tools/api-builder/links-package/inline-tag-defs/linkDocs.js b/tools/api-builder/links-package/inline-tag-defs/linkDocs.js new file mode 100644 index 0000000000..6254fc2d2f --- /dev/null +++ b/tools/api-builder/links-package/inline-tag-defs/linkDocs.js @@ -0,0 +1,75 @@ +var path = require('canonical-path'); +var fs = require("fs"); +var jsonFile = require('jsonfile'); + +/** + * @dgService linkDocsInlineTagDef + * @description + * Process inline link tags (of the form {@linkDocs some/uri 'Some Title'}), replacing them with HTML anchors. + * The uri should point to a jade page in the Docs without the .jade extension ( under public/docs ). + * If the title is omitted an attempt will be made to determine the title of the jade page being pointed to. If not found + * the the title will simply be the last part of the link. + * Examples + * {@linkDocs guide/gettingStarted 'QuickStart'} + * {@linkDocs ts/latest/guide/quickstart } + * {@linkDocs js/latest/guide/quickstart 'Javascript version of getting started' } + * {@linkDocs ts/latest/guide/quickstart title="Typescript version of getting started" } + * @kind function + * @property {string} lang Default docs API page language when not explicitly given in URI; one of ts|js|dart. + * @property {string} vers Default docs version. Currently only 'latest'. + */ +module.exports = function linkDocsInlineTagDef(parseArgString, createDocMessage, log) { + var _self = { + name: 'linkDocs', + lang: 'ts', + vers: 'latest', + description: 'Process inline link tags (of the form {@linkDocs some/uri [title=]"Some Title"}), replacing them with HTML anchors', + + handler: function(doc, tagName, tagDescription) { + // Parse out the uri and title + var tagArgs = parseArgString(tagDescription); + var unnamedArgs = tagArgs._; + var uri = unnamedArgs[0]; + var title = tagArgs.title || (unnamedArgs.length > 1 ? unnamedArgs[1] : null); + + // Are there parameters and/or an anchor? + var matches, paramAnchor = ''; + if (matches = uri.match(/([^\#\?]*)([\#\?].*)/)) { + uri = matches[1]; + paramAnchor = matches[2]; + } + + // Is this a chapter-relative uri like 'guide/...'? + if (!uri.match(/^(ts|js|dart)/)) { + var lang = _self.lang; + var vers = _self.vers; + var prevUri = uri; + uri = path.join(lang, vers, uri); + log.info('Ajusted linkDocs chapter-relative uri (' + doc.fileInfo.baseName + '): ' + prevUri + ' -> ' + uri); + } + + var isValid = false; + var jadePath = path.join('./public/docs', uri + '.jade'); + var key = path.basename(jadePath, '.jade'); + if ( !fs.existsSync(jadePath)) { + log.warn(createDocMessage('Invalid docs link (unable to locate jade file: "' + jadePath + '")', doc)); + } else { + isValid = true; + if (!title) { + var jsonFilePath = path.join(path.dirname(jadePath), '_data.json'); + if ( fs.existsSync(jsonFilePath)) { + var jsonObj = jsonFile.readFileSync(jsonFilePath); + title = jsonObj[key] && jsonObj[key].title; + } + } + } + var url = path.join('/docs', uri + '.html' + paramAnchor); + title = title || key || url; + + return isValid ? + '' + title + '' : + '' + title + ''; + } + }; + return _self; +}; From 285ecf495f41eec47fa9e2846114e899a58a4eaf Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 8 Jul 2016 11:02:08 +0100 Subject: [PATCH 23/25] chore(api-builder): add configurable link disambuators & put to work closes #1852 Add configurable link disambuators Add a service to disambiguate docs by module Add a service to disambiguate docs that are deprecated --- tools/api-builder/links-package/index.js | 7 +++++++ .../services/deprecatedDocsLinkDisambiguator.js | 13 +++++++++++++ .../links-package/services/getLinkInfo.js | 15 ++++++++++++++- .../services/moduleScopeLinkDisambiguator.js | 15 +++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 tools/api-builder/links-package/services/deprecatedDocsLinkDisambiguator.js create mode 100644 tools/api-builder/links-package/services/moduleScopeLinkDisambiguator.js diff --git a/tools/api-builder/links-package/index.js b/tools/api-builder/links-package/index.js index 5391399055..4d4a06c82b 100644 --- a/tools/api-builder/links-package/index.js +++ b/tools/api-builder/links-package/index.js @@ -10,6 +10,8 @@ module.exports = new Package('links', []) .factory(require('dgeni-packages/links/services/getDocFromAlias')) .factory(require('./services/getLinkInfo')) .factory(require('./services/parseArgString')) +.factory(require('./services/moduleScopeLinkDisambiguator')) +.factory(require('./services/deprecatedDocsLinkDisambiguator')) .factory(require('./services/getApiFragmentFileName')) .config(function(inlineTagProcessor, linkInlineTagDef, linkDocsInlineTagDef, exampleInlineTagDef, exampleTabsInlineTagDef) { @@ -17,4 +19,9 @@ module.exports = new Package('links', []) inlineTagProcessor.inlineTagDefinitions.push(linkDocsInlineTagDef); inlineTagProcessor.inlineTagDefinitions.push(exampleInlineTagDef); inlineTagProcessor.inlineTagDefinitions.push(exampleTabsInlineTagDef); +}) + +.config(function(getLinkInfo, moduleScopeLinkDisambiguator, deprecatedDocsLinkDisambiguator) { + getLinkInfo.disambiguators.push(moduleScopeLinkDisambiguator); + getLinkInfo.disambiguators.push(deprecatedDocsLinkDisambiguator); }); diff --git a/tools/api-builder/links-package/services/deprecatedDocsLinkDisambiguator.js b/tools/api-builder/links-package/services/deprecatedDocsLinkDisambiguator.js new file mode 100644 index 0000000000..3db79ffbd6 --- /dev/null +++ b/tools/api-builder/links-package/services/deprecatedDocsLinkDisambiguator.js @@ -0,0 +1,13 @@ +var _ = require('lodash'); + +module.exports = function deprecatedDocsLinkDisambiguator() { + return function(url, title, currentDoc, docs) { + if (docs.length != 2) return docs; + + var filteredDocs = _.filter(docs, function(doc) { + return !doc.fileInfo.relativePath.match(/\/(\w+)-deprecated\//); + }); + + return filteredDocs.length > 0 ? filteredDocs : docs; + }; +}; diff --git a/tools/api-builder/links-package/services/getLinkInfo.js b/tools/api-builder/links-package/services/getLinkInfo.js index a180984c69..c0dad0025a 100644 --- a/tools/api-builder/links-package/services/getLinkInfo.js +++ b/tools/api-builder/links-package/services/getLinkInfo.js @@ -10,10 +10,17 @@ var path = require('canonical-path'); * @return {Object} The link information * * @property {boolean} relativeLinks Whether we expect the links to be relative to the originating doc + * @property {array 1 ) { linkInfo.valid = false; @@ -68,4 +80,5 @@ module.exports = function getLinkInfo(getDocFromAlias, encodeCodeBlock, log) { return linkInfo; }; + }; \ No newline at end of file diff --git a/tools/api-builder/links-package/services/moduleScopeLinkDisambiguator.js b/tools/api-builder/links-package/services/moduleScopeLinkDisambiguator.js new file mode 100644 index 0000000000..ec1758fe99 --- /dev/null +++ b/tools/api-builder/links-package/services/moduleScopeLinkDisambiguator.js @@ -0,0 +1,15 @@ +var _ = require('lodash'); + +module.exports = function moduleScopeLinkDisambiguator() { + return function(url, title, currentDoc, docs) { + if (docs.length > 1) { + // filter out target docs that are not in the same module as the source doc + var filteredDocs = _.filter(docs, function(doc) { + return doc.moduleDoc === currentDoc.moduleDoc; + }); + // if all target docs are in a different module then just return the full collection of ambiguous docs + return filteredDocs.length > 0 ? filteredDocs : docs; + } + return docs; + }; +}; From cc689ce980c951f74fcc05c846ace0f57bd73aa2 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Fri, 8 Jul 2016 12:41:48 -0700 Subject: [PATCH 24/25] chore(api doc gen): log 'no api docs' as info not warning closes #1860 There are too many undocumented interfaces to consider lack of API docs in a source file to be worth a warning. The original author even questions whether there should be such a warning. It is now logged at the `info` level. --- .../docs-package/processors/addNotYetDocumentedProperty.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/api-builder/docs-package/processors/addNotYetDocumentedProperty.js b/tools/api-builder/docs-package/processors/addNotYetDocumentedProperty.js index ed3b29b22b..e4e2c0540d 100644 --- a/tools/api-builder/docs-package/processors/addNotYetDocumentedProperty.js +++ b/tools/api-builder/docs-package/processors/addNotYetDocumentedProperty.js @@ -23,8 +23,7 @@ module.exports = function addNotYetDocumentedProperty(EXPORT_DOC_TYPES, log, cre } if (doc.notYetDocumented) { - // TODO: (ericjim) should I remove this? - log.warn(createDocMessage("Not yet documented", doc)); + log.info(createDocMessage("Not yet documented", doc)); } }); @@ -35,4 +34,4 @@ module.exports = function addNotYetDocumentedProperty(EXPORT_DOC_TYPES, log, cre function notYetDocumented(doc) { return !doc.noDescription && doc.description.trim().length == 0; -} \ No newline at end of file +} From 08d051d2f6d3bdcab94ec84b708e308ee5b1bbcf Mon Sep 17 00:00:00 2001 From: Chris Grieger Date: Thu, 23 Jun 2016 09:41:39 +0200 Subject: [PATCH 25/25] docs(testing): refer to 'lite-server' instead of 'live-server'. closes #1737 Since the QuickStart uses 'lite-server', this should also be used for the testing guide. --- .../testing/ts/liteserver-test-config.json | 3 +++ .../ts/latest/testing/first-app-tests.jade | 20 ++++++++++++++----- .../latest/testing/jasmine-testing-101.jade | 2 +- .../testing/testing-an-angular-pipe.jade | 2 +- 4 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 public/docs/_examples/testing/ts/liteserver-test-config.json diff --git a/public/docs/_examples/testing/ts/liteserver-test-config.json b/public/docs/_examples/testing/ts/liteserver-test-config.json new file mode 100644 index 0000000000..6b1a2b5466 --- /dev/null +++ b/public/docs/_examples/testing/ts/liteserver-test-config.json @@ -0,0 +1,3 @@ +{ + "startPath": "unit-tests.html" +} \ No newline at end of file diff --git a/public/docs/ts/latest/testing/first-app-tests.jade b/public/docs/ts/latest/testing/first-app-tests.jade index 9824bf2b17..90560ad51f 100644 --- a/public/docs/ts/latest/testing/first-app-tests.jade +++ b/public/docs/ts/latest/testing/first-app-tests.jade @@ -15,7 +15,7 @@ include ../_util-fns We're also assuming that you're already comfortable with basic Angular 2 concepts and the tools we introduced in the [QuickStart](../quickstart.html) and the [Tour of Heroes](../tutorial/) tutorial - such as npm, gulp, and live-server. + such as npm, gulp, and lite-server. .l-main-section :marked @@ -41,16 +41,26 @@ pre.prettyprint.lang-bash .alert.is-important Be sure to install jasmine-core , not jasmine! +.l-main-section +:marked + ## Configure `lite-server` for serving our test harness + +:marked + First create a configuration file for serving up our test harness through `lite-server`. + ++makeExample('testing/ts/liteserver-test-config.json', '', 'liteserver-test-config.json') + :marked Let's make one more change to the `package.json` script commands. - **Open the `package.json` ** and scroll to the `scripts` node and add in a new one: + **Open the `package.json` ** and scroll to the `scripts` node and add the following two entries: code-example(format=""). - "test": "live-server --open=unit-tests.html" + "lite-server-test": "lite-server --config=liteserver-test-config.json", + "test": "tsc && concurrently \"npm run tsc:w\" \"npm run lite-server-test\" " :marked - That command will launch `live-server` and open a browser to the `unit-tests.html` page we just wrote. + The `npm test` command will launch `lite-server` and open a browser to the `unit-tests.html` page we just wrote. It will also take care of recompiling your source code and reloading your browser after any change. .l-main-section :marked @@ -127,7 +137,7 @@ code-example(format=""). :marked ### Run and Fail - Look over at the browser (live-server will have reloaded it). The browser displays + Look over at the browser (lite-server will have reloaded it). The browser displays figure.image-display img(src='/resources/images/devguide/first-app-tests/Jasmine-not-running-tests.png' style="width:400px;" alt="Jasmine not running any tests") diff --git a/public/docs/ts/latest/testing/jasmine-testing-101.jade b/public/docs/ts/latest/testing/jasmine-testing-101.jade index fbf0c47697..082d2d0883 100644 --- a/public/docs/ts/latest/testing/jasmine-testing-101.jade +++ b/public/docs/ts/latest/testing/jasmine-testing-101.jade @@ -113,7 +113,7 @@ pre.prettyprint.lang-bash We’ll be evolving these tests rapidly and it would be nice to have the browser refresh automatically as we make changes and recompile. - Let’s launch with **live-server** in a second terminal window: + Let’s launch with **lite-server** in a second terminal window: pre.prettyprint.lang-bash code npm start diff --git a/public/docs/ts/latest/testing/testing-an-angular-pipe.jade b/public/docs/ts/latest/testing/testing-an-angular-pipe.jade index d98845e571..dcd68a54d9 100644 --- a/public/docs/ts/latest/testing/testing-an-angular-pipe.jade +++ b/public/docs/ts/latest/testing/testing-an-angular-pipe.jade @@ -48,7 +48,7 @@ include ../_util-fns We're also assuming that you're already comfortable with basic Angular 2 concepts and the tools we introduced in the [QuickStart](../quickstart.html) and the [Tour of Heroes](../tutorial/) tutorial - such as npm, gulp, and live-server. + such as npm, gulp, and lite-server. :marked ## Add another spec file