Compare commits

..

132 Commits

Author SHA1 Message Date
58698d7806 release: cut the v6.1.1 release 2018-08-02 14:02:59 -07:00
e26c25a062 Revert "docs: refactor http module import for style guide app.module (#25001)" (#25263)
This reverts commit 88da8f3d52.

PR Close #25263
2018-08-02 09:20:12 -07:00
0a6434b066 test(common): TokenExtractor should extend HttpXsrfTokenExtractor in xsrf spec (#24649)
PR Close #24649
2018-08-02 08:34:15 -07:00
ff3550c304 test(common): remove unused import in xsrf spec (#24649)
PR Close #24649
2018-08-02 08:34:15 -07:00
6d4a14082c docs(docs-infra): adds note according to Symlink problem (#24714)
docs: adds note according to Symlink problem

Closes #24709
docs(docs-infra): adds section "Developing on Windows"


Merge remote-tracking branch 'origin/aioREADME' into aioREADME


docs(docs-infra): adds information about admin rights


docs(docs-infra): adds hint


docs(docs-infra): Change to link


PR Close #24714
2018-08-02 08:33:24 -07:00
9ddf269c2c docs(elements): add section about custom element typings in elements guide (#25219)
PR Close #25219
2018-08-02 08:32:59 -07:00
25a76a1492 docs(elements): add link to full example in elements guide (#25219)
PR Close #25219
2018-08-02 08:32:59 -07:00
8439a6ec2a docs(elements): remove unnecessary whitespace in elements guide (#25219)
PR Close #25219
2018-08-02 08:32:59 -07:00
1ef2eae3aa feat(docs-infra): support sending Google Analytics events (#25042)
PR Close #25042
2018-08-01 17:04:19 -07:00
d5d034a0ff docs: update reactiveconf 2018 in events (#24739)
PR Close #24739
2018-08-01 16:15:18 -07:00
5ca35b3cd2 docs: Update the link to the Jasmine docs (#25175)
Solves #24462.

Also update the http part of the link to to https.

PR Close #25175
2018-08-01 16:12:44 -07:00
0a6a3f3163 ci: update pullapprove groups and add docs (#25257)
With this update to permissions the docs team can easily identify the technical reviewer for a particular doc, which should streamline the reviews.

I also added Jennifer into all groups that contain docs, so that she can approve changes that contain only editorial changes.

Closes #21692

PR Close #25257
2018-08-01 15:53:41 -07:00
3a601382e6 test(upgrade): run tests against AngularJS v1.7.x as well (#25231)
PR Close #25231
2018-08-01 14:10:21 -07:00
7a1fdde69e build(bazel): entry point file couldn't be resolved [ts-api-guardian] (#25052)
* When using `ts-api-guardian` on Windows, the input file can't be found due to wrong normalized path delimiters.

PR Close #25052
2018-08-01 13:29:27 -07:00
cbc2ea1b1a build: update hello_world__closure to google-closure-compiler 20180716.0.0 (#25236)
PR Close #25236
2018-08-01 13:25:40 -07:00
bdf801b0e8 build: revert yarn.lock rxjs version to 6.0.0 (#25236)
PR Close #25236
2018-08-01 13:23:35 -07:00
fe5e8b7177 docs(aio): update Kendo UI description in resource.json (#24845)
PR Close #24845
2018-08-01 10:59:16 -07:00
11f0f98ad8 docs: fix typos and missing word in tutorial (#20764)
PR Close #20764
2018-08-01 10:56:31 -07:00
801b534421 docs(core): remove experimental tag (#24032)
PR Close #24032
2018-08-01 10:56:07 -07:00
0fc83215e2 docs(core): remove experimental tag (#24032)
Remove experimental note on APP_INITIALIZER.

PR Close #24032
2018-08-01 10:56:07 -07:00
3d3a1a4642 docs(aio): add Kevin Yang to GDE resources (#24791)
Add files via upload
PR Close #24791
2018-08-01 10:55:41 -07:00
32a40ba5de docs: refactor http module import for style guide app.module (#25001)
PR Close #25001
2018-08-01 10:55:17 -07:00
045271230d docs: refactor lazy loading modules example (#25071)
PR Close #25071
2018-08-01 10:54:00 -07:00
ec31f6bf9a docs(router): clarify scroll position wording (#25077)
PR Close #25077
2018-08-01 10:53:35 -07:00
4798d77088 docs(core): replace ReflectiveInjector example with Static Injector example (#25162)
PR Close #25162
2018-08-01 10:52:32 -07:00
08c6762039 docs: replace ReflectiveInjector samples with Injector samples (#25162)
PR Close #25162
2018-08-01 10:52:32 -07:00
26516045e7 refactor(animations): do not use short parameter names (#25198)
PR Close #25198
2018-08-01 10:51:58 -07:00
a83b9f7911 docs(changelog): remove reverted feature entry (#25206)
PR Close #25206
2018-08-01 10:51:28 -07:00
1b7c77e49f docs(changelog): remove duplicate entries (#25206)
PR Close #25206
2018-08-01 10:51:28 -07:00
3ab31a4be6 docs: update to account for CLI changes (#25223)
This should help clarify the use of providedIn and correct the documentation where it was showing the use of a now depreciated CLI command flag.

I am openly looking for feedback on this change to figure out the best wording.

PR Close #25223
2018-08-01 10:51:05 -07:00
43dcf77123 build(bazel): fix typo in protractor test target definition (#25235)
PR Close #25235
2018-08-01 10:50:44 -07:00
d4bf2da3bd refactor(core): remove withBody from public testing API (#25171)
PR Close #25171
2018-07-31 15:09:33 -07:00
fa3882845a docs(aio): add short description for entryComponents (#21360)
PR Close #21360
2018-07-31 13:18:36 -07:00
fa59748e00 build: make postinstall script compatible with Windows (#25232)
PR Close #25232
2018-07-31 13:17:55 -07:00
c38ecb3b5b docs(forms): fix incorrect variables naming in the comments (#25150)
PR Close #25150
2018-07-31 11:42:16 -07:00
875efa8492 docs(docs-infra): fix topnav layout for smaller screens (#25181)
PR Close #25181
2018-07-31 11:41:22 -07:00
74964bde99 docs: fix link to "Override component providers" (#24967)
Closes #24966

PR Close #24967
2018-07-30 21:53:21 -07:00
785fb5cc5a docs(aio): add StrongBrew to the trainer list (#24891)
PR Close #24891
2018-07-30 16:48:17 -07:00
26d9f0278b ci: correctly encode quoted params passed as params to curl
Previously the auth token could have been split into three separate args in bash which resulted
in two bogus requests being sent out for each curl call. These requests had to time out before
the real request was made, but without the token.

I couldn't find a better way to quickly fix this without adding some duplication.
2018-07-30 16:46:50 -07:00
22ebd53c17 docs: update bootstrapping and entry component guide to use httpclient (#25178)
PR Close #25178
2018-07-30 16:00:19 -07:00
a972c039c3 docs: fix typo in dependency injection guide (#24972)
PR Close #24972
2018-07-30 15:56:36 -07:00
f5e18029fa docs: refactor pipe example to use the HttpClient (#22741)
PR Close #22741
2018-07-30 14:40:25 -07:00
317c7087c5 build(compiler-cli): update tsickle dependency to support TypeScript 2.9 (#25152)
The original range (`^0.30.0`) does not match `0.32.1`, which enables support for TypeScript 2.9.

Close #25141

PR Close #25152
2018-07-27 11:25:28 -07:00
39abe7b7c1 test: fix typings for DoneFn (#25163)
This also fixes CI tests, which were accidentally broken in #24663.

PR Close #25163
2018-07-27 11:13:33 -07:00
36a7705a44 feat(docs-infra): allow notification bar to show arbitrary content (#25020)
This change generalises the notification bar rendering to allow
more complex content to be displayed.

Now you must provide the full HTML of the notification message
when using `<aio-notification>`.

Also you can control whether clicking the content triggers the
notification to close or not.

This will support the new notification specified in "Other Items : 3" of
[#24140](https://github.com/angular/angular/issues/24140#issuecomment-397480410)

PR Close #25020
2018-07-27 09:29:40 -07:00
50a21885cf style(docs-infra): remove unnecessary call to console.log() (#25020)
PR Close #25020
2018-07-27 09:29:40 -07:00
e86f3d9a49 docs: refactor feature modules example (#25069)
PR Close #25069
2018-07-27 09:28:13 -07:00
738f2961ba docs: Change unnecessary step in ToH-Tutorial (#25059)
PR Close #25059
2018-07-27 09:25:59 -07:00
f2bf8287ba build(bazel): add comment about angular bazel rules API re-export from /index.bzl (#24663)
PR Close #24663
2018-07-26 17:02:21 -07:00
9d5b34e1e7 build(bazel): add comment for patch-types work-around (#24663)
PR Close #24663
2018-07-26 17:02:21 -07:00
d237f4014a build(bazel): show bazel progress in CircleCI to prevent 10m timeout with no output (#24663)
PR Close #24663
2018-07-26 17:02:21 -07:00
8743a9bfd6 build(bazel): use bazel managed node_modules for downstream angular from source build support (#24663)
PR Close #24663
2018-07-26 17:02:21 -07:00
514d03f2d0 docs(router): Removed unneeded trailing text. (#24894)
PR Close #24894
2018-07-26 17:01:03 -07:00
48d7205873 release: cut the v6.1.0 release 2018-07-25 14:23:40 -07:00
e1c6fd5453 Revert "feat(core): add support for using async/await with Jasmine" (#25096)
This reverts commit f6829aba55e07609e312b4f67dbc9dbbf36e4e46.

PR Close #25096
2018-07-25 11:44:56 -07:00
968f153491 fix(router): Fix _lastPathIndex in deeply nested empty paths (#22394)
PR Close #22394
2018-07-25 11:27:28 -07:00
1e28495c89 fix(ivy): update compiler with latest runtime for view queries (#25061)
PR Close #25061
2018-07-25 10:39:30 -07:00
0bcf20c9fa docs(animations): typo fix in the comments (#22652)
PR Close #22652
2018-07-25 10:13:18 -07:00
cf81823b07 docs: refactor style guide example 03-06 (#24996)
docs: refactor style guide example 03-06


docs: refactor style guide example 03-06


docs: refactor style guide example 03-06


PR Close #24996
2018-07-25 08:04:12 -07:00
d4ac9698ba Revert "docs: refactor style guide example 03-06 (#24996)"
This reverts commit 65e18dc1bf.
2018-07-24 22:11:30 -07:00
c205516f0d docs: refactor ngmodules example (#25072)
PR Close #25072
2018-07-24 21:03:38 -07:00
777bd412b2 docs: replace angular/http with HttpClient (#25068)
PR Close #25068
2018-07-24 20:54:44 -07:00
1e79014fc4 docs: replace angular/http with HttpClient (#25066)
PR Close #25066
2018-07-24 20:51:50 -07:00
d0c066a223 docs: replaced old angular/http example (#25065)
PR Close #25065
2018-07-24 20:47:20 -07:00
65e18dc1bf docs: refactor style guide example 03-06 (#24996)
PR Close #24996
2018-07-24 20:46:07 -07:00
1ceddb6290 fix(ivy): support re-order embedded templates (#24805)
PR Close #24805
2018-07-24 16:41:05 -07:00
22731a7588 refactor(ivy): split i18nInterpolation into 8 functions (#24805)
PR Close #24805
2018-07-24 16:41:05 -07:00
72dd10f78f refactor(ivy): cleanup runtime i18n code (#24805)
Fixes #24785

PR Close #24805
2018-07-24 16:41:05 -07:00
c0e3852384 Revert "build: update to newer circleCI bazel remote cache proxy (#25054)" (#25076)
This reverts commit d6016f1d1d.

PR Close #25076
2018-07-24 16:05:58 -07:00
2cb0f68a7b test(bazel): allow no sandbox for protractor tests (#24906)
It specifies --no-sandbox flag when running the protractor tests as
root. This is needed for running the tests inside a docker container.

PR Close #24906
2018-07-24 08:28:03 -07:00
8450e0ab2f build(bazel): fix broken travis CI (#24788)
PR Close #24788
2018-07-24 08:26:16 -07:00
e38b2b502c build(bazel): //modules/benchmarks/src/largetable/render3:perf bazel protractor test (#24788)
PR Close #24788
2018-07-24 08:26:16 -07:00
445b9a5627 feat(ivy): support ViewContainerRef.createComponent() (#24997)
PR Close #24997
2018-07-24 08:23:23 -07:00
d523630ea2 docs(aio): cleanup aalert, callout, subsection use and author style (#24986)
PR Close #24986
2018-07-24 08:22:14 -07:00
d6016f1d1d build: update to newer circleCI bazel remote cache proxy (#25054)
it fixes the error we currently get on CI

PR Close #25054
2018-07-24 08:20:28 -07:00
be3cca4fd5 docs: tests for number/percent/currency pipe (#25028)
Will avoid errors in examples like the one fixed in #24661

Closes #25028
2018-07-23 13:18:23 -07:00
169e9dd2c8 feat(ivy): bridge compile instructions to include sanitization helpers (#24938)
PR Close #24938
2018-07-23 08:49:52 -07:00
13f3157823 fix(ivy): update content query compilation to latest runtime (#24957)
PR Close #24957
2018-07-23 08:45:50 -07:00
edef58f466 build(docs-infra): ensure all API headings are sentence cased (#24949)
Closes #24880

PR Close #24949
2018-07-23 08:43:07 -07:00
7c89af34a9 docs: square odds example in rxjs guide (#24947)
Added argument type to filter function of rxjs. Fixed the
return value of filtering of odd numbers

PR Close #24947
2018-07-23 08:41:58 -07:00
bd576bb83f docs: fix multicasting example in observable guide (#24911)
PR Close #24911
2018-07-23 08:40:45 -07:00
168c2a645b docs: add Truly-UI to resources (#24615)
PR Close #24615
2018-07-23 08:39:35 -07:00
7729bb2bdc docs: fix instructions for switching directories (#24439)
docs: fix instructions for switching directories


PR Close #24439
2018-07-23 08:38:10 -07:00
426324513d docs: update rxjs link to version 6 (#24269)
PR Close #24269
2018-07-23 08:36:51 -07:00
4d6f467fea docs: refactor style guide example 01-01 (#22738)
docs: refactor style guide example 01-01


PR Close #22738
2018-07-23 08:35:37 -07:00
6b859daea4 fix(core): stop reusing provider definitions across NgModuleRef instances (#25022)
Fixes #25018.

Instantiating a NgModuleRef from NgModuleFactory reuses the NgModuleDefinition if it is already present. However the NgModuleDefinition has a providers array which modified when tree shakable providers are instantiated. This corrupts the provider definitions the next time the same factory is used to create a new NgModuleRef - Two provider definitions can end up with the same index anf the injector could potentially return a completely wrong object for a provider token.

This scenario is more likely on the server where the same NgModuleFactory is reused across requests.

The fix clones the cached NgModuleDefinition so that any tree shakable providers added later do not affect the cached copy.

PR Close #25022
2018-07-23 08:13:29 -07:00
7960d1879d docs: technical review incorporated (#24744)
closes #24744
2018-07-20 12:40:00 -07:00
f1ab394218 docs: add api doc to commonly queried elements 2018-07-20 12:39:10 -07:00
86203736e9 fix(service-worker): don't include sourceMappingURL in ngsw-worker (#24877)
Fixes #23596

PR Close #24877
2018-07-20 11:49:46 -07:00
41ef75869c fix(ivy): types in .d.ts files should account for generics (#24862)
Ivy definition types have a generic type which specifies the return
type of the factory function. For example:

static ngDirectiveDef<NgForOf, '[ngFor][ngForOf]'>

However, in this case NgForOf itself has a type parameter <T>. Thus,
writing the above is incorrect.

This commit modifies ngtsc to understand the genericness of NgForOf and
to write the following:

static ngDirectiveDef<NgForOf<any>, '[ngFor][ngForOf]'>

PR Close #24862
2018-07-20 11:48:36 -07:00
2b8b647006 fix(ivy): export injectElementRef (#24862)
PR Close #24862
2018-07-20 11:48:36 -07:00
ed1db40322 fix(ivy): use 'typeof' and 'never' for type metadata (#24862)
Previously ngtsc would use a tuple of class types for listing metadata
in .d.ts files. For example, an @NgModule's declarations might be
represented with the type:

[NgIf, NgForOf, NgClass]

If the module had no declarations, an empty tuple [] would be produced.

This has two problems.

1. If the class type has generic type parameters, TypeScript will
complain that they're not provided.

2. The empty tuple type is not actually legal.

This commit addresses both problems.

1. Class types are now represented using the `typeof` operator, so the
above declarations would be represented as:

[typeof NgIf, typeof NgForOf, typeof NgClass].

Since typeof operates on a value, it doesn't require generic type
arguments.

2. Instead of an empty tuple, `never` is used to indicate no metadata.

PR Close #24862
2018-07-20 11:48:36 -07:00
d3594fc1c5 fix(ivy): correctly export all *Def symbols as private (#24862)
Previously, some of the *Def symbols were not exported or were exported
as public API. This commit ensures every definition type is in the
private export namespace.

PR Close #24862
2018-07-20 11:48:36 -07:00
9fd70c9715 refactor(ivy): run the compiler compliance tests against ngtsc (#24862)
This commit moves the compiler compliance tests into compiler-cli,
and uses ngtsc to run them instead of the custom compilation
pipeline used before. Testing against ngtsc allows for validation
of the real compiler output.

This commit also fixes a few small issues that prevented the tests
from passing.

PR Close #24862
2018-07-20 11:48:36 -07:00
b7bbc82e3e fix(ivy): wrap non-statement assignment expressions in parentheses (#24862)
Previously, when translating an assignment expression (e.g. x = 3), the
translator would always print the statement as X = Y. However, if the
expression is included in a larger expression (X = (Y = Z)), the
translator would print "X = Y = Z" without regard for the outer
expression context.

Now, the translator understands when it's printing an expression
statement (X = Y;) vs an expression in a larger context (X = (Y = Z);)
and encapsulates the latter in parentheses.

PR Close #24862
2018-07-20 11:48:36 -07:00
139f5b3672 fix(ivy): references track the identifier they were discovered under (#24862)
Previously, references had the concept of an identifier, but would not
properly detect whether the identifier should be used or not when
generating an expression. This change fixes that logic.

Additionally, now whenever an identifier resolves to a reference (even
one imported from another module) as part of resolving an expression,
the reference is updated to use that identifier. This ensures that for
a class Foo declared in foo.ts, but referenced in an expression in
bar.ts, the Reference returned includes the identifier from bar.ts,
meaning that writing an expression in bar.ts for the Reference will not
generate an import.

PR Close #24862
2018-07-20 11:48:36 -07:00
6f8ec256ef fix(ivy): detect ngOnChanges as a non-static method (#24862)
Previously ngtsc had a bug where it would only detect the presence of
ngOnChanges as a static method. This commit flips the condition and only
recognizes ngOnChanges as a non-static method.

PR Close #24862
2018-07-20 11:48:36 -07:00
5d7005eef5 feat(ivy): port the static resolver to use the ReflectionHost (#24862)
Previously, the static resolver did its own interpretation of statements
in the TypeScript AST, which only functioned on TypeScript code. ES5
code in particular would not work with the resolver as it had hard-coded
assumptions about AST structure.

This commit changes the resolver to use a ReflectionHost instead, which
abstracts away understanding of the structural side of the AST. It adds 3
new methods to the ReflectionHost in support of this functionality:

* getDeclarationOfIdentifier
* getExportsOfModule
* isClass

PR Close #24862
2018-07-20 11:48:36 -07:00
2e724ec68b feat(ivy): support host bindings in ngtsc (#24862)
This change adds support for host bindings to ngtsc, and parses them
both from decorators and from the metadata in the top-level annotation.

PR Close #24862
2018-07-20 11:48:36 -07:00
76f8f78920 feat(ivy): compile queries in ngtsc (#24862)
This commit adds support for @ContentChild[ren] and @ViewChild[ren] in
ngtsc. Previously queries were ignored.

PR Close #24862
2018-07-20 11:48:36 -07:00
6eb6ac7c12 fix(ivy): fix a couple issues with Input/Output compilation (#24862)
PR Close #24862
2018-07-20 11:48:36 -07:00
9644873023 fix(ivy): ignore imports without ngInjectorDef in r3_injector (#24862)
ngInjectorDef.imports is generated from @NgModule.imports plus
@NgModule.exports. A problem arises as a result, because @NgModule
exports contain not only other modules (which will have ngInjectorDef
fields), but components, directives, and pipes as well. Because of
locality, it's difficult for the compiler to filter these out at
build time.

It's not impossible, but for now filtering them out at runtime will
allow testing of the compiler against complex applications.

PR Close #24862
2018-07-20 11:48:36 -07:00
ae4563202c fix(ivy): export NgModuleFactory adapter (#24862)
PR Close #24862
2018-07-20 11:48:36 -07:00
42d4287153 fix(ivy): ngInjectorDef should copy full imports/exports nodes (#24862)
@NgModule()s get compiled to two fields: ngModuleDef and ngInjectorDef.
Both fields contain imports, as both selector scopes and injectors have
the concept of composed units of configuration. Previously these fields
were generated by static resolution of imports and exports in metadata.

Support for ModuleWithProviders requires they be generated differently.
ngModuleDef's imports/exports are generated as resolved lists of types,
whereas ngInjectorDef's imports should reflect the raw expressions that
the developer wrote in the metadata.

This change modifies the NgModule handler and properly copies raw nodes
for the imports and exports into the ngInjectorDef.

PR Close #24862
2018-07-20 11:48:36 -07:00
f9a6a175bf fix(ivy): properly inject all special token types (#24862)
Previously ngtsc had a few bugs handling special token types:

* Injector was not properly translated to INJECTOR
* ChangeDetectorRef was not injected via injectChangeDetectorRef()

This commit fixes these two bugs, and also adds a test to ensure
they continue to work correctly.

PR Close #24862
2018-07-20 11:48:36 -07:00
53a16006d6 fix(ivy): export InheritDefinitionFeature (#24862)
PR Close #24862
2018-07-20 11:48:35 -07:00
8a986d4642 feat(ivy): statically resolve template expressions (#24862)
This commit adds support for template substitution expressions for
ngtsc static resolution.

PR Close #24862
2018-07-20 11:48:35 -07:00
e346c3c2f2 refactor(ivy): fix an unnecessarily deep import (#24862)
PR Close #24862
2018-07-20 11:48:35 -07:00
60aeee7abf feat(ivy): selector side of ModuleWithProviders via type metadata (#24862)
Within an @NgModule it's common to include in the imports a call to
a ModuleWithProviders function, for example RouterModule.forRoot().
The old ngc compiler was able to handle this pattern because it had
global knowledge of metadata of not only the input compilation unit
but also all dependencies.

The ngtsc compiler for Ivy doesn't have this knowledge, so the
pattern of ModuleWithProviders functions is more difficult. ngtsc
must be able to determine which module is imported via the function
in order to expand the selector scope and properly tree-shake
directives and pipes.

This commit implements a solution to this problem, by adding a type
parameter to ModuleWithProviders through which the actual module
type can be passed between compilation units.

The provider side isn't a problem because the imports are always
copied directly to the ngInjectorDef.

PR Close #24862
2018-07-20 11:48:35 -07:00
1008bb6287 fix(ivy): unwrap parenthesized or cast expressions for metadata (#24862)
Metadata in Ivy must be literal. For example,

@NgModule({...})

is legal, whereas

const meta = {...};
@NgModule(meta)

is not.

However, some code contains additional superfluous parentheses:

@NgModule(({...}))

It is desirable that ngtsc accept this form of literal object.

PR Close #24862
2018-07-20 11:48:35 -07:00
8a5cd2200a fix(ivy): allow building router with ngtsc (#24862)
This commit adds the ivy-local tag to //packages/router. Since the
router depends on //packages/upgrade, it makes that package
compatible with ngtsc as well.

PR Close #24862
2018-07-20 11:48:35 -07:00
f58f3dc07a fix(ivy): handle ReadKeyExpr code generation (#24862)
This implements a missing expression type in ngtsc code generation:
that of bracket access to an object property.

PR Close #24862
2018-07-20 11:48:35 -07:00
bb58138579 docs: fix bad link (#24825)
PR Close #24825
2018-07-20 11:34:38 -07:00
b8f740b253 docs: remove closing parenthesis from provides guide (#24935)
PR Close #24935
2018-07-20 11:07:53 -07:00
23766b85e9 build: Fix windows tests (#24927)
closes #24927
2018-07-20 10:51:32 -07:00
3cd9645daa fix(docs-infra): fix table header layout in API pages (#24919)
PR Close #24919
2018-07-20 10:48:42 -07:00
2d38fa104b test(platform-webworker): avoid flakes due to existing PlatformRef (#24916)
PR Close #24916
2018-07-20 10:47:17 -07:00
56b3f1703e fix(ivy): invoke lifecycle hooks of directives placed on ng-template (#24899)
PR Close #24899
2018-07-20 10:45:51 -07:00
c438b5eeda build(bazel): turn on preserve-symlinks (#24881)
This change turns on preserve-symlinks in nodejs to verify hermeticity of the Angular build.

BREAKING CHANGE: Use of @angular/bazel rules now requires calling ng_setup_workspace() in your WORKSPACE file.

For example:

local_repository(
    name = "angular",
    path = "node_modules/@angular/bazel",
)

load("@angular//:index.bzl", "ng_setup_workspace")

ng_setup_workspace()

PR Close #24881
2018-07-20 10:37:30 -07:00
70b51a6255 docs: update i18n with requested changes (#24875)
use more general project name in code example

PR Close #24875
2018-07-20 10:36:13 -07:00
7ebd8e59a8 docs: update i18n doc regarding aot compilation (#24875)
Add missing lines to code example to allow using ng serve with custom i18n configurations.

PR Close #24875
2018-07-20 10:36:12 -07:00
1c533c913d build(docs-infra): add support for examples of type elements (#24840)
Examples using `@angular/elements` need to transpile to es2015 for
Custom Elements to work (on browsers that natively support them).

Alternatively, a polyfill would need to be loaded. For now, changing the
transpilation target to es2015 is the simplest solution.

PR Close #24840
2018-07-20 10:34:47 -07:00
ead3f926cb docs: add e2e tests for elements example (#24840)
PR Close #24840
2018-07-20 10:34:47 -07:00
9be222f448 docs: fix elements example (#24840)
PR Close #24840
2018-07-20 10:34:47 -07:00
b137f09345 docs: refactor elements example (#24840)
This makes the closing behavior more deterministic, which makes it
easier to be e2e-tested.

PR Close #24840
2018-07-20 10:34:47 -07:00
453693fd33 docs: clean up elements example (indentation, import order, etc) (#24840)
PR Close #24840
2018-07-20 10:34:47 -07:00
270176bbe4 docs: more info on currency digits (#24661)
Adds an example of using the `currency` pipe with a currency that has no cents like CLP,
which will format the amount with no digits if `digitsInfo` is not provided:

    <!-- outputs CA$14.00 -->
    {{ 14 | currency:'CAD' }}
    <!-- outputs CLP14 -->
    {{ 14 | currency:'CLP' }}

Amends the docs, adds an example and fix an error with a current example.

PR Close #24661
2018-07-20 10:33:06 -07:00
5840a86f98 docs: Add notes on manual sanitization to security guide (#24176)
Some users have remarked that we don't explain how to manually call
sanitization, so add a few lines on that.

PR Close #24176
2018-07-20 10:27:12 -07:00
2aab1c9dd6 ci: remove Tina from pullaprove (#25006)
She has been removed as a collaborator to the project and pullaprove rejects
this config file which still lists her name.

PR Close #25006
2018-07-20 10:25:52 -07:00
f9669e50ff release: cut the v6.1.0-rc.3 release
Note that RC1 and RC2 glitched out midway during the npm release.
Therefore there is only one commit
2018-07-19 15:45:06 -07:00
99a393e84f docs: add new Reactive Forms guide (#24578)
PR Close #24578
2018-07-19 13:46:30 -04:00
d76531d16e fix(animations): @internal must use JSDoc tags. (#24928)
This change fixes up several comments that accidentally used the JSDoc
tag @internal in regular block comments (`/*` instead of `/**`).

This prevents a problem with Closure Compiler that balks at `@` tags
occuring in regular block comments, because it assumes they were
intended to be tags for the compiler.

When occuring in `/**` JSDoc, tsickle escapes the tags, so they do not
cause problems.

PR Close #24928
2018-07-18 18:18:04 -04:00
395 changed files with 10934 additions and 8051 deletions

View File

@ -3,7 +3,10 @@
# See remote cache documentation in /docs/BAZEL.md
# Don't be spammy in the logs
build --noshow_progress
# TODO(gmagolan): Hide progress again once build performance improves
# Presently, CircleCI can timeout during bazel test ... with the following
# error: Too long with no output (exceeded 10m0s)
# build --noshow_progress
# Don't run manual tests
test --test_tag_filters=-manual

View File

@ -8,6 +8,7 @@
# alexeagle - Alex Eagle
# alxhub - Alex Rickabaugh
# andrewseguin - Andrew Seguin
# benlesh - Ben Lesh
# brandonroberts - Brandon Roberts
# brocco - Mike Brocchi
# filipesilva - Filipe Silva
@ -15,7 +16,7 @@
# hansl - Hans Larsen
# IgorMinar - Igor Minar
# jasonaden - Jason Aden
# kapunahelewong - Kapunahele Wong
# jenniferfell - Jennifer Fell
# kara - Kara Erickson
# kyliau - Keen Yee Liau
# matsko - Matias Niemelä
@ -23,7 +24,6 @@
# petebacondarwin - Pete Bacon Darwin
# pkozlowski-opensource - Pawel Kozlowski
# robwormald - Rob Wormald
# tinayuangao - Tina Gao
# vicb - Victor Berchet
# vikerman - Vikram Subramanian
@ -92,6 +92,7 @@ groups:
- "*.bzl"
- "packages/bazel/*"
- "tools/bazel.rc"
- "/docs/BAZEL.md"
users:
- alexeagle #primary
- kyliau
@ -131,42 +132,113 @@ groups:
conditions:
files:
- "packages/core/*"
- "aio/content/guide/bootstrapping.md"
- "aio/content/examples/bootstrapping/*"
- "aio/content/guide/attribute-directives.md"
- "aio/content/examples/attribute-directives/*"
- "aio/content/images/guide/attribute-directives/*"
- "aio/content/guide/structural-directives.md"
- "aio/content/examples/structural-directives/*"
- "aio/content/images/guide/structural-directives/*"
- "aio/content/guide/dynamic-component-loader.md"
- "aio/content/examples/dynamic-component-loader/*"
- "aio/content/images/guide/dynamic-component-loader/*"
- "aio/content/guide/template-syntax.md"
- "aio/content/examples/template-syntax/*"
- "aio/content/images/guide/template-syntax/*"
- "aio/content/guide/dependency-injection.md"
- "aio/content/examples/dependency-injection/*"
- "aio/content/images/guide/dependency-injection/*"
- "aio/content/guide/dependency-injection-in-action.md"
- "aio/content/examples/dependency-injection-in-action/*"
- "aio/content/images/guide/dependency-injection-in-action/*"
- "aio/content/guide/hierarchical-dependency-injection.md"
- "aio/content/examples/hierarchical-dependency-injection/*"
- "aio/content/guide/singleton-services.md"
- "aio/content/guide/dependency-injection-pattern.md"
- "aio/content/guide/providers.md"
- "aio/content/examples/providers/*"
- "aio/content/guide/component-interaction.md"
- "aio/content/examples/component-interaction/*"
- "aio/content/images/guide/component-interaction/*"
- "aio/content/guide/component-styles.md"
- "aio/content/examples/component-styles/*"
- "aio/content/guide/lifecycle-hooks.md"
- "aio/content/examples/lifecycle-hooks/*"
- "aio/content/images/guide/lifecycle-hooks/*"
- "aio/content/examples/ngcontainer/*"
- "aio/content/images/guide/ngcontainer/*"
- "aio/content/guide/pipes.md"
- "aio/content/examples/pipes/*"
- "aio/content/images/guide/pipes/*"
- "aio/content/guide/entry-components.md"
- "aio/content/guide/set-document-title.md"
- "aio/content/examples/set-document-title/*"
- "aio/content/images/guide/set-document-title/*"
- "aio/content/guide/ngmodules.md"
- "aio/content/examples/ngmodules/*"
- "aio/content/examples/ngmodule/*"
- "aio/content/images/guide/ngmodule/*"
- "aio/content/guide/ngmodule-faq.md"
- "aio/content/examples/ngmodule-faq/*"
- "aio/content/guide/module-types.md"
- "aio/content/guide/sharing-ngmodules.md"
- "aio/content/guide/frequent-ngmodules.md"
- "aio/content/images/guide/frequent-ngmodules/*"
- "aio/content/guide/ngmodule-api.md"
- "aio/content/guide/ngmodule-vs-jsmodule.md"
- "aio/content/guide/feature-modules.md"
- "aio/content/examples/feature-modules/*"
- "aio/content/images/guide/feature-modules/*"
- "aio/content/guide/lazy-loading-ngmodules.md"
- "aio/content/examples/lazy-loading-ngmodules/*"
- "aio/content/images/guide/lazy-loading-ngmodules"
users:
- mhevery #primary
- jasonaden
- kara
- vicb
- IgorMinar #fallback
- IgorMinar
- jenniferfell #docs only
animations:
conditions:
files:
- "packages/animations/*"
- "packages/platform-browser/animations/*"
- "aio/content/guide/animations.md"
- "aio/content/examples/animations/*"
- "aio/content/images/guide/animations/*"
users:
- matsko #primary
- mhevery #fallback
- IgorMinar #fallback
- jenniferfell #docs only
compiler/i18n:
conditions:
files:
- "packages/compiler/src/i18n/*"
- "aio/content/guide/i18n.md"
- "aio/content/examples/i18n/*"
users:
- vicb #primary
- alxhub
- IgorMinar #fallback
- mhevery #fallback
- jenniferfell #docs only
compiler:
conditions:
files:
- "packages/compiler/*"
- "aio/content/guide/aot-compiler.md"
users:
- alxhub #primary
- vicb
- mhevery
- IgorMinar #fallback
- jenniferfell #docs only
compiler-cli/ngtools:
conditions:
@ -175,7 +247,6 @@ groups:
users:
- hansl
- filipesilva #fallback
- brocco #fallback
- IgorMinar #fallback
compiler-cli:
@ -211,57 +282,97 @@ groups:
files:
- "packages/forms/*"
- "aio/content/guide/forms.md"
- "aio/content/guide/form-validation.md"
- "aio/content/guide/reactive-forms.md"
- "aio/content/examples/forms/*"
- "aio/content/images/guide/forms/*"
- "aio/content/guide/form-validation.md"
- "aio/content/examples/form-validation/*"
- "aio/content/images/guide/form-validation/*"
- "aio/content/guide/dynamic-form.md"
- "aio/content/examples/dynamic-form/*"
- "aio/content/images/guide/dynamic-form/*"
- "aio/content/guide/reactive-forms.md"
- "aio/content/examples/reactive-forms/*"
- "aio/content/images/guide/reactive-forms/*"
users:
- kara #primary
- tinayuangao #secondary
- IgorMinar #fallback
- mhevery #fallback
- jenniferfell #docs only
http:
conditions:
files:
- "packages/common/http/*"
- "packages/http/*"
- "aio/content/guide/http.md"
- "aio/content/examples/http/*"
- "aio/content/images/guide/http/*"
users:
- alxhub #primary
- IgorMinar
- mhevery #fallback
- jenniferfell #docs only
language-service:
conditions:
files:
- "packages/language-service/*"
- "aio/content/guide/language-service.md"
- "aio/content/images/guide/language-service/*"
users:
- kyliau #primary
# needs secondary
- vicb
- IgorMinar #fallback
- mhevery #fallback
- jenniferfell #docs only
router:
conditions:
files:
- "packages/router/*"
- "aio/content/guide/router.md"
- "aio/content/examples/router/*"
- "aio/content/images/guide/router/*"
users:
- jasonaden #primary
- vicb
- IgorMinar #fallback
- mhevery #fallback
- jenniferfell #docs only
testing:
conditions:
files:
- "*/testing/*"
- "aio/content/guide/testing.md"
- "aio/content/examples/testing/*"
- "aio/content/images/guide/testing/*"
users:
- vikerman
- IgorMinar #fallback
- mhevery #fallback
- jenniferfell #docs only
upgrade:
conditions:
files:
- "packages/upgrade/*"
- "aio/content/guide/upgrade.md"
- "aio/content/examples/upgrade-module/*"
- "aio/content/images/guide/upgrade/*"
- "aio/content/examples/upgrade-phonecat-1-typescript/*"
- "aio/content/examples/upgrade-phonecat-2-hybrid/*"
- "aio/content/examples/upgrade-phonecat-3-final/*"
- "aio/content/guide/upgrade-performance.md"
- "aio/content/guide/ajs-quick-reference.md"
- "aio/content/examples/ajs-quick-reference/*"
users:
- petebacondarwin #primary
- gkalpak
- IgorMinar #fallback
- mhevery #fallback
- jenniferfell #docs only
platform-browser:
conditions:
@ -277,12 +388,15 @@ groups:
conditions:
files:
- "packages/platform-server/*"
- "aio/content/guide/universal.md"
- "aio/content/examples/universal/*"
users:
- vikerman #primary
- alxhub #secondary
- vicb
- IgorMinar #fallback
- mhevery #fallback
- jenniferfell #docs only
platform-webworker:
conditions:
@ -298,22 +412,34 @@ groups:
conditions:
files:
- "packages/service-worker/*"
- "aio/content/guide/service-worker-getting-started.md"
- "aio/content/examples/service-worker-getting-started/*"
- "aio/content/guide/service-worker-communications.md"
- "aio/content/guide/service-worker-config.md"
- "aio/content/guide/service-worker-devops.md"
- "aio/content/guide/service-worker-intro.md"
- "aio/content/images/guide/service-worker/*"
users:
- alxhub #primary
- gkalpak
- IgorMinar #fallback
- gkalpak #primary
- alxhub
- IgorMinar
- mhevery #fallback
- jenniferfell #docs only
elements:
conditions:
files:
- "packages/elements/*"
- "aio/content/examples/elements/*"
- "aio/content/images/guide/elements/*"
- "aio/content/guide/elements.md"
users:
- andrewseguin #primary
- gkalpak
- robwormald
- IgorMinar #fallback
- mhevery #fallback
- jenniferfell #docs only
benchpress:
conditions:
@ -325,7 +451,7 @@ groups:
- IgorMinar #fallback
- mhevery #fallback
angular.io:
docs-infra:
conditions:
files:
include:
@ -338,7 +464,7 @@ groups:
- gkalpak
- mhevery #fallback
angular.io-guide-and-tutorial:
docs/guide-and-tutorial:
conditions:
files:
include:
@ -348,19 +474,20 @@ groups:
- "aio/content/navigation.json"
- "aio/content/license.md"
users:
- kapunahelewong
- stephenfluin
- jenniferfell
- brandonroberts
- petebacondarwin
- gkalpak
- IgorMinar
- brandonroberts
- mhevery #fallback
angular.io-marketing:
docs/marketing:
conditions:
files:
include:
- "aio/content/marketing/*"
- "aio/content/images/marketing/*"
- "aio/content/navigation.json"
- "aio/content/license.md"
users:
@ -370,3 +497,43 @@ groups:
- IgorMinar
- robwormald
- mhevery #fallback
docs/observables:
conditions:
files:
- "aio/content/examples/observables/*"
- "aio/content/images/guide/observables/*"
- "aio/content/guide/observables.md"
- "aio/content/guide/comparing-observables.md"
- "aio/content/examples/observables-in-angular/*"
- "aio/content/images/guide/observables-in-angular/*"
- "aio/content/guide/observables-in-angular.md"
- "aio/content/examples/practical-observable-usage/*"
- "aio/content/guide/practical-observable-usage.md"
- "aio/content/examples/rx-library/*"
- "aio/content/guide/rx-library.md"
users:
- jasonaden
- benlesh
- IgorMinar
- mhevery
- jenniferfell #docs only
docs/packaging:
conditions:
files:
- "aio/content/guide/npm-packages.md"
- "aio/content/guide/browser-support.md"
- "aio/content/guide/typescript-configuration.md"
- "aio/content/guide/setup-systemjs-anatomy.md"
- "aio/content/examples/setup/*"
- "aio/content/guide/setup.md"
- "aio/content/guide/deployment.md"
- "aio/content/guide/releases.md"
- "aio/content/guide/updating.md"
users:
- IgorMinar #primary
- alexeagle
- hansl
- mhevery #fallback
- jenniferfell #docs only

View File

@ -5,6 +5,7 @@ load("@build_bazel_rules_nodejs//:defs.bzl", "node_modules_filegroup")
exports_files([
"tsconfig.json",
"LICENSE",
"protractor-perf.conf.js",
])
# Developers should always run `bazel run :install`
@ -14,40 +15,19 @@ alias(
actual = "@nodejs//:yarn",
)
node_modules_filegroup(
alias(
name = "node_modules",
packages = [
"bytebuffer",
"hammerjs",
"jasmine",
"minimist",
"protobufjs",
"protractor",
"reflect-metadata",
"source-map-support",
"tsickle",
"tslib",
"tsutils",
"typescript",
"zone.js",
"@angular-devkit/core",
"@angular-devkit/schematics",
"@types",
"@webcomponents/custom-elements",
],
patterns = [
"node_modules/protractor/**",
],
actual = "@angular_deps//:node_modules",
)
filegroup(
name = "web_test_bootstrap_scripts",
# do not sort
srcs = [
"//:node_modules/reflect-metadata/Reflect.js",
"//:node_modules/zone.js/dist/zone.js",
"//:node_modules/zone.js/dist/zone-testing.js",
"//:node_modules/zone.js/dist/task-tracking.js",
"@angular_deps//:node_modules/reflect-metadata/Reflect.js",
"@angular_deps//:node_modules/zone.js/dist/zone.js",
"@angular_deps//:node_modules/zone.js/dist/zone-testing.js",
"@angular_deps//:node_modules/zone.js/dist/task-tracking.js",
"//:test-events.js",
],
)
@ -55,9 +35,11 @@ filegroup(
filegroup(
name = "angularjs_scripts",
srcs = [
"//:node_modules/angular-1.5/angular.js",
"//:node_modules/angular-mocks-1.5/angular-mocks.js",
"//:node_modules/angular-mocks/angular-mocks.js",
"//:node_modules/angular/angular.js",
"@angular_deps//:node_modules/angular-1.5/angular.js",
"@angular_deps//:node_modules/angular-1.6/angular.js",
"@angular_deps//:node_modules/angular-mocks-1.5/angular-mocks.js",
"@angular_deps//:node_modules/angular-mocks-1.6/angular-mocks.js",
"@angular_deps//:node_modules/angular-mocks/angular-mocks.js",
"@angular_deps//:node_modules/angular/angular.js",
],
)

View File

@ -1,3 +1,113 @@
<a name="6.1.1"></a>
## [6.1.1](https://github.com/angular/angular/compare/6.1.0...6.1.1) (2018-08-02)
### Bug Fixes
* **compiler-cli:** correct tsickle dependency version to fix typescript 2.9 compatibility ([fec29fa](https://github.com/angular/angular/commit/317c7087c56b72aa74cd6d6a8f719e6e7fec29fa))
<a name="6.1.0"></a>
# [6.1.0](https://github.com/angular/angular/compare/6.0.0-rc.5...6.1.0) (2018-07-25)
### Bug Fixes
* **animations:** always render end-state styles for orphaned DOM nodes ([#24236](https://github.com/angular/angular/issues/24236)) ([dc4a3d0](https://github.com/angular/angular/commit/dc4a3d0))
* **animations:** set animations styles properly on platform-server ([#24624](https://github.com/angular/angular/issues/24624)) ([0b356d4](https://github.com/angular/angular/commit/0b356d4))
* **animations:** do not throw errors when a destroyed component is animated ([#23836](https://github.com/angular/angular/issues/23836)) ([d2a8687](https://github.com/angular/angular/commit/d2a8687))
* **animations:** Fix browser detection logic ([#24188](https://github.com/angular/angular/issues/24188)) ([b492b9e](https://github.com/angular/angular/commit/b492b9e))
* **animations:** properly clean up queried element styles in safari/edge ([#23633](https://github.com/angular/angular/issues/23633)) ([da9ff25](https://github.com/angular/angular/commit/da9ff25))
* **animations:** retain state styling for nodes that are moved around ([#23534](https://github.com/angular/angular/issues/23534)) ([65211f4](https://github.com/angular/angular/commit/65211f4))
* **animations:** retain trigger-state for nodes that are moved around ([#24238](https://github.com/angular/angular/issues/24238)) ([8db928d](https://github.com/angular/angular/commit/8db928d))
* **bazel:** Allow ng_module to depend on targets w no deps ([#24446](https://github.com/angular/angular/issues/24446)) ([282d351](https://github.com/angular/angular/commit/282d351))
* **benchpress:** Fix promise chain in chrome_driver_extension. ([#23458](https://github.com/angular/angular/issues/23458)) ([d4b6c41](https://github.com/angular/angular/commit/d4b6c41))
* **common:** do not round factional seconds ([#24831](https://github.com/angular/angular/issues/24831)) ([a527c69](https://github.com/angular/angular/commit/a527c69)), closes [#24384](https://github.com/angular/angular/issues/24384)
* **common:** format fractional seconds ([#24844](https://github.com/angular/angular/issues/24844)) ([0b4d85e](https://github.com/angular/angular/commit/0b4d85e)), closes [#24831](https://github.com/angular/angular/issues/24831)
* **common:** properly update collection reference in NgForOf ([#24684](https://github.com/angular/angular/issues/24684)) ([ff84c5c](https://github.com/angular/angular/commit/ff84c5c)), closes [#24155](https://github.com/angular/angular/issues/24155)
* **common:** use correct currency format for locale de-AT ([#24658](https://github.com/angular/angular/issues/24658)) ([dcabb05](https://github.com/angular/angular/commit/dcabb05)), closes [#24609](https://github.com/angular/angular/issues/24609)
* **common:** use correct ICU plural for locale mk ([#24659](https://github.com/angular/angular/issues/24659)) ([64a8584](https://github.com/angular/angular/commit/64a8584))
* **compiler:** fix a few non-tree-shakeable code patterns ([#24677](https://github.com/angular/angular/issues/24677)) ([50d4a4f](https://github.com/angular/angular/commit/50d4a4f))
* **compiler:** i18n_extractor now outputs the correct source file name ([#24885](https://github.com/angular/angular/issues/24885)) ([c8ad965](https://github.com/angular/angular/commit/c8ad965)), closes [#24884](https://github.com/angular/angular/issues/24884)
* **compiler:** support `.` in import statements. ([#20634](https://github.com/angular/angular/issues/20634)) ([d8f7b29](https://github.com/angular/angular/commit/d8f7b29)), closes [#20363](https://github.com/angular/angular/issues/20363)
* **compiler:** avoid a crash in ngc-wrapped. ([#23468](https://github.com/angular/angular/issues/23468)) ([e1c4930](https://github.com/angular/angular/commit/e1c4930))
* **compiler:** generate constant array for i18n attributes ([#23837](https://github.com/angular/angular/issues/23837)) ([cfde36d](https://github.com/angular/angular/commit/cfde36d))
* **compiler:** generate core-compliant hostBindings property ([#24087](https://github.com/angular/angular/issues/24087)) ([01b5acd](https://github.com/angular/angular/commit/01b5acd)), closes [#24013](https://github.com/angular/angular/issues/24013)
* **compiler:** handle undefined annotation metadata ([#23349](https://github.com/angular/angular/issues/23349)) ([ca776c5](https://github.com/angular/angular/commit/ca776c5))
* **compiler-cli:** Use typescript to resolve modules for metadata ([#22856](https://github.com/angular/angular/issues/22856)) ([0d5f2d3](https://github.com/angular/angular/commit/0d5f2d3))
* **compiler-cli:** don't rely on incompatible TS method ([#23550](https://github.com/angular/angular/issues/23550)) ([b1f040f](https://github.com/angular/angular/commit/b1f040f))
* **core:** stop reusing provider definitions across NgModuleRef instances ([#25022](https://github.com/angular/angular/issues/25022)) ([6b859da](https://github.com/angular/angular/commit/6b859da)), closes [#25018](https://github.com/angular/angular/issues/25018)
* **core:** mark NgModule as not the root if APP_ROOT is set to false ([#24814](https://github.com/angular/angular/issues/24814)) ([1089261](https://github.com/angular/angular/commit/1089261))
* **core:** use addCustomEqualityTester instead of overriding toEqual ([#22983](https://github.com/angular/angular/issues/22983)) ([0922228](https://github.com/angular/angular/commit/0922228)), closes [#22939](https://github.com/angular/angular/issues/22939)
* **core:** Injector correctly honors the @Self flag ([#24520](https://github.com/angular/angular/issues/24520)) ([ccbda9d](https://github.com/angular/angular/commit/ccbda9d))
* **core:** avoid eager providers re-initialization ([#23559](https://github.com/angular/angular/issues/23559)) ([0c6dc45](https://github.com/angular/angular/commit/0c6dc45))
* **core:** call ngOnDestroy on all services that have it ([#23755](https://github.com/angular/angular/issues/23755)) ([fc03427](https://github.com/angular/angular/commit/fc03427)), closes [#22466](https://github.com/angular/angular/issues/22466) [#22240](https://github.com/angular/angular/issues/22240) [#14818](https://github.com/angular/angular/issues/14818)
* **docs-infra:** fix table header layout in API pages ([#24919](https://github.com/angular/angular/issues/24919)) ([3cd9645](https://github.com/angular/angular/commit/3cd9645))
* **elements:** always check to create strategy ([#23825](https://github.com/angular/angular/issues/23825)) ([b1cda36](https://github.com/angular/angular/commit/b1cda36))
* **elements:** prevent closure renaming of platform properties ([#23843](https://github.com/angular/angular/issues/23843)) ([d4b8b24](https://github.com/angular/angular/commit/d4b8b24))
* **forms:** properly handle special properties in FormGroup.get ([#22249](https://github.com/angular/angular/issues/22249)) ([9367e91](https://github.com/angular/angular/commit/9367e91)), closes [#17195](https://github.com/angular/angular/issues/17195)
* **language-service:** do not overwrite native `Reflect` ([#24299](https://github.com/angular/angular/issues/24299)) ([6881404](https://github.com/angular/angular/commit/6881404)), closes [#21420](https://github.com/angular/angular/issues/21420)
* **platform-browser:** add missing deps for HammerGesturesPlugin ([#24682](https://github.com/angular/angular/issues/24682)) ([13d60ea](https://github.com/angular/angular/commit/13d60ea))
* **platform-browser:** mark Meta and Title services as tree shakable providers ([#24815](https://github.com/angular/angular/issues/24815)) ([197387d](https://github.com/angular/angular/commit/197387d))
* **platform-browser:** workaround wrong import path generated by ngc for DOCUMENT ([#24830](https://github.com/angular/angular/issues/24830)) ([7d27ecc](https://github.com/angular/angular/commit/7d27ecc))
* **platform-server:** avoid clash between server and client style encapsulation attributes ([#24158](https://github.com/angular/angular/issues/24158)) ([b96a3c8](https://github.com/angular/angular/commit/b96a3c8))
* **platform-server:** avoid dependency cycle when using http interceptor ([#24229](https://github.com/angular/angular/issues/24229)) ([60aa943](https://github.com/angular/angular/commit/60aa943)), closes [#23023](https://github.com/angular/angular/issues/23023)
* **platform-server:** don't reflect innerHTML property to attribute ([#24213](https://github.com/angular/angular/issues/24213)) ([6a663a4](https://github.com/angular/angular/commit/6a663a4)), closes [#19278](https://github.com/angular/angular/issues/19278)
* **platform-server:** provide Domino DOM types globally ([#24116](https://github.com/angular/angular/issues/24116)) ([c73196e](https://github.com/angular/angular/commit/c73196e)), closes [#23280](https://github.com/angular/angular/issues/23280) [#23133](https://github.com/angular/angular/issues/23133)
* **router:** Fix _lastPathIndex in deeply nested empty paths ([#22394](https://github.com/angular/angular/issues/22394)) ([968f153](https://github.com/angular/angular/commit/968f153))
* **router:** add ability to recover from malformed url ([#23283](https://github.com/angular/angular/issues/23283)) ([86d254d](https://github.com/angular/angular/commit/86d254d)), closes [#21468](https://github.com/angular/angular/issues/21468)
* **router:** fix lazy loading of aux routes ([#23459](https://github.com/angular/angular/issues/23459)) ([5731d07](https://github.com/angular/angular/commit/5731d07)), closes [#10981](https://github.com/angular/angular/issues/10981)
* **router:** avoid freezing queryParams in-place ([#22663](https://github.com/angular/angular/issues/22663)) ([89f64e5](https://github.com/angular/angular/commit/89f64e5)), closes [#22617](https://github.com/angular/angular/issues/22617)
* **router:** cache route handle if found ([#22475](https://github.com/angular/angular/issues/22475)) ([4cfa571](https://github.com/angular/angular/commit/4cfa571)), closes [#22474](https://github.com/angular/angular/issues/22474)
* **router:** correct the segment parsing so it won't break on ampersand ([#23684](https://github.com/angular/angular/issues/23684)) ([553a680](https://github.com/angular/angular/commit/553a680))
* **service-worker:** don't include sourceMappingURL in ngsw-worker ([#24877](https://github.com/angular/angular/issues/24877)) ([8620373](https://github.com/angular/angular/commit/8620373)), closes [#23596](https://github.com/angular/angular/issues/23596)
* **service-worker:** avoid network requests when looking up hashed resources in cache ([#24127](https://github.com/angular/angular/issues/24127)) ([52d43a9](https://github.com/angular/angular/commit/52d43a9))
* **service-worker:** fix `SwPush.unsubscribe()` ([#24162](https://github.com/angular/angular/issues/24162)) ([3ed2d75](https://github.com/angular/angular/commit/3ed2d75)), closes [#24095](https://github.com/angular/angular/issues/24095)
* **service-worker:** add badge to NOTIFICATION_OPTION_NAMES ([#23241](https://github.com/angular/angular/issues/23241)) ([fb59b2d](https://github.com/angular/angular/commit/fb59b2d)), closes [#23196](https://github.com/angular/angular/issues/23196)
* **service-worker:** check platformBrowser before accessing navigator.serviceWorker ([#21231](https://github.com/angular/angular/issues/21231)) ([0bdd30e](https://github.com/angular/angular/commit/0bdd30e))
* **service-worker:** correctly handle requests with empty `clientId` ([#23625](https://github.com/angular/angular/issues/23625)) ([e0ed59e](https://github.com/angular/angular/commit/e0ed59e)), closes [#23526](https://github.com/angular/angular/issues/23526)
* **service-worker:** deprecate `versionedFiles` in asset-group resources ([#23584](https://github.com/angular/angular/issues/23584)) ([1d378e2](https://github.com/angular/angular/commit/1d378e2))
### Features
* **bazel:** Initial commit of protractor_web_test_suite ([#24787](https://github.com/angular/angular/issues/24787)) ([71e0df0](https://github.com/angular/angular/commit/71e0df0))
* **bazel:** protractor_web_test_suite for release ([#24787](https://github.com/angular/angular/issues/24787)) ([161ff5c](https://github.com/angular/angular/commit/161ff5c))
* **common:** introduce KeyValuePipe ([#24319](https://github.com/angular/angular/issues/24319)) ([2b49bf7](https://github.com/angular/angular/commit/2b49bf7))
* **compiler:** support `// ...` and `// TODO` in mock compiler expectations ([#23441](https://github.com/angular/angular/issues/23441)) ([c6b206e](https://github.com/angular/angular/commit/c6b206e))
* **compiler-cli:** update `tsickle` to `0.29.x` ([#24233](https://github.com/angular/angular/issues/24233)) ([f69ac67](https://github.com/angular/angular/commit/f69ac67))
* **core:** export defaultKeyValueDiffers to private api ([#24319](https://github.com/angular/angular/issues/24319)) ([92b278c](https://github.com/angular/angular/commit/92b278c))
* **core:** expose a Compiler API for accessing module ids from NgModule types ([#24258](https://github.com/angular/angular/issues/24258)) ([bd02b27](https://github.com/angular/angular/commit/bd02b27))
* **core:** KeyValueDiffer#diff allows null values ([#24319](https://github.com/angular/angular/issues/24319)) ([52ce9d5](https://github.com/angular/angular/commit/52ce9d5))
* **core:** add support for ShadowDOM v1 ([#24718](https://github.com/angular/angular/issues/24718)) ([3553977](https://github.com/angular/angular/commit/3553977))
(https://github.com/angular/angular/commit/328971f)), closes [#24616](https://github.com/angular/angular/issues/24616)
* **platform-browser:** add HammerJS lazy-loader symbols to public API ([#23943](https://github.com/angular/angular/issues/23943)) ([26fbf1d](https://github.com/angular/angular/commit/26fbf1d))
* **platform-browser:** allow lazy-loading HammerJS ([#23906](https://github.com/angular/angular/issues/23906)) ([313bdce](https://github.com/angular/angular/commit/313bdce))
* **platform-server:** use EventManagerPlugin on the server ([#24132](https://github.com/angular/angular/issues/24132)) ([d6595eb](https://github.com/angular/angular/commit/d6595eb))
* **router:** add urlUpdateStrategy allow updating the browser URL at the beginning of navigation ([#24820](https://github.com/angular/angular/issues/24820)) ([328971f]
* **router:** add navigation execution context info to activation hooks ([#24204](https://github.com/angular/angular/issues/24204)) ([20c463e](https://github.com/angular/angular/commit/20c463e)), closes [#24202](https://github.com/angular/angular/issues/24202)
* **router:** implement scrolling restoration service ([#20030](https://github.com/angular/angular/issues/20030)) ([49c5234](https://github.com/angular/angular/commit/49c5234)), closes [#13636](https://github.com/angular/angular/issues/13636) [#10929](https://github.com/angular/angular/issues/10929) [#7791](https://github.com/angular/angular/issues/7791) [#6595](https://github.com/angular/angular/issues/6595)
* **service-worker:** add support for `?` in SW config globbing ([#24105](https://github.com/angular/angular/issues/24105)) ([250527c](https://github.com/angular/angular/commit/250527c))
* typescript 2.9 support ([#24652](https://github.com/angular/angular/issues/24652)) ([e3064d5](https://github.com/angular/angular/commit/e3064d5))
### build
* **bazel:** turn on preserve-symlinks ([#24881](https://github.com/angular/angular/issues/24881)) ([c438b5e](https://github.com/angular/angular/commit/c438b5e))
### BREAKING CHANGES
* **bazel:** Use of @angular/bazel rules now requires calling ng_setup_workspace() in your WORKSPACE file.
For example:
local_repository(
name = "angular",
path = "node_modules/@angular/bazel",
)
load("@angular//:index.bzl", "ng_setup_workspace")
ng_setup_workspace()
<a name="6.0.9"></a>
## [6.0.9](https://github.com/angular/angular/compare/6.0.8...6.0.9) (2018-07-11)
@ -6,37 +116,6 @@
* **common:** format fractional seconds ([#24844](https://github.com/angular/angular/issues/24844)) ([3c93d07](https://github.com/angular/angular/commit/3c93d07)), closes [#24831](https://github.com/angular/angular/issues/24831)
<a name="6.1.0-rc.0"></a>
# [6.1.0-rc.0](https://github.com/angular/angular/compare/6.1.0-beta.3...6.1.0-rc.0) (2018-07-11)
### Bug Fixes
* **common:** do not round factional seconds ([#24831](https://github.com/angular/angular/issues/24831)) ([a527c69](https://github.com/angular/angular/commit/a527c69)), closes [#24384](https://github.com/angular/angular/issues/24384)
* **common:** properly update collection reference in NgForOf ([#24684](https://github.com/angular/angular/issues/24684)) ([ff84c5c](https://github.com/angular/angular/commit/ff84c5c)), closes [#24155](https://github.com/angular/angular/issues/24155)
* **common:** use correct currency format for locale de-AT ([#24658](https://github.com/angular/angular/issues/24658)) ([dcabb05](https://github.com/angular/angular/commit/dcabb05)), closes [#24609](https://github.com/angular/angular/issues/24609)
* **compiler:** fix a few non-tree-shakeable code patterns ([#24677](https://github.com/angular/angular/issues/24677)) ([50d4a4f](https://github.com/angular/angular/commit/50d4a4f))
* **compiler-cli:** Use typescript to resolve modules for metadata ([#22856](https://github.com/angular/angular/issues/22856)) ([0d5f2d3](https://github.com/angular/angular/commit/0d5f2d3))
* **core:** mark NgModule as not the root if APP_ROOT is set to false ([#24814](https://github.com/angular/angular/issues/24814)) ([1089261](https://github.com/angular/angular/commit/1089261))
* **core:** use addCustomEqualityTester instead of overriding toEqual ([#22983](https://github.com/angular/angular/issues/22983)) ([0922228](https://github.com/angular/angular/commit/0922228)), closes [#22939](https://github.com/angular/angular/issues/22939)
* **language-service:** do not overwrite native `Reflect` ([#24299](https://github.com/angular/angular/issues/24299)) ([6881404](https://github.com/angular/angular/commit/6881404)), closes [#21420](https://github.com/angular/angular/issues/21420)
* **platform-browser:** add missing deps for HammerGesturesPlugin ([#24682](https://github.com/angular/angular/issues/24682)) ([13d60ea](https://github.com/angular/angular/commit/13d60ea))
* **platform-browser:** mark Meta and Title services as tree shakable providers ([#24815](https://github.com/angular/angular/issues/24815)) ([197387d](https://github.com/angular/angular/commit/197387d))
* **platform-browser:** workaround wrong import path generated by ngc for DOCUMENT ([#24830](https://github.com/angular/angular/issues/24830)) ([7d27ecc](https://github.com/angular/angular/commit/7d27ecc))
* **router:** add ability to recover from malformed url ([#23283](https://github.com/angular/angular/issues/23283)) ([86d254d](https://github.com/angular/angular/commit/86d254d)), closes [#21468](https://github.com/angular/angular/issues/21468)
* **service-worker:** avoid network requests when looking up hashed resources in cache ([#24127](https://github.com/angular/angular/issues/24127)) ([52d43a9](https://github.com/angular/angular/commit/52d43a9))
### Features
* **core:** add support for ShadowDOM v1 ([#24718](https://github.com/angular/angular/issues/24718)) ([3553977](https://github.com/angular/angular/commit/3553977))
* **core:** add support for using async/await with Jasmine ([#24637](https://github.com/angular/angular/issues/24637)) ([71100e6](https://github.com/angular/angular/commit/71100e6))
* typescript 2.9 support ([#24652](https://github.com/angular/angular/issues/24652)) ([e3064d5](https://github.com/angular/angular/commit/e3064d5))
* **service-worker:** add support for `?` in SW config globbing ([#24105](https://github.com/angular/angular/issues/24105)) ([250527c](https://github.com/angular/angular/commit/250527c))
<a name="6.0.8"></a>
## [6.0.8](https://github.com/angular/angular/compare/6.0.7...6.0.8) (2018-07-11)
@ -57,15 +136,6 @@
* **core:** add support for ShadowDOM v1 ([#24718](https://github.com/angular/angular/issues/24718)) ([6c55a13](https://github.com/angular/angular/commit/6c55a13))
<a name="6.1.0-beta.3"></a>
# [6.1.0-beta.3](https://github.com/angular/angular/compare/6.1.0-beta.2...6.1.0-beta.3) (2018-06-28)
### Bug Fixes
* **animations:** set animations styles properly on platform-server ([#24624](https://github.com/angular/angular/issues/24624)) ([0b356d4](https://github.com/angular/angular/commit/0b356d4))
* **common:** use correct ICU plural for locale mk ([#24659](https://github.com/angular/angular/issues/24659)) ([64a8584](https://github.com/angular/angular/commit/64a8584))
<a name="6.0.7"></a>
## [6.0.7](https://github.com/angular/angular/compare/6.0.6...6.0.7) (2018-06-27)
@ -75,18 +145,6 @@
* **animations:** set animations styles properly on platform-server ([#24624](https://github.com/angular/angular/issues/24624)) ([0b356d4](https://github.com/angular/angular/commit/0b356d4))
* **common:** use correct ICU plural for locale mk ([#24659](https://github.com/angular/angular/issues/24659)) ([64a8584](https://github.com/angular/angular/commit/64a8584))
<a name="6.1.0-beta.2"></a>
# [6.1.0-beta.2](https://github.com/angular/angular/compare/6.1.0-beta.1...6.1.0-beta.2) (2018-06-20)
### Bug Fixes
* **compiler:** support `.` in import statements. ([#20634](https://github.com/angular/angular/issues/20634)) ([d8f7b29](https://github.com/angular/angular/commit/d8f7b29)), closes [#20363](https://github.com/angular/angular/issues/20363)
* **core:** Injector correctly honors the @Self flag ([#24520](https://github.com/angular/angular/issues/24520)) ([ccbda9d](https://github.com/angular/angular/commit/ccbda9d))
<a name="6.0.6"></a>
## [6.0.6](https://github.com/angular/angular/compare/6.0.5...6.0.6) (2018-06-20)
@ -96,39 +154,6 @@
* **compiler:** support `.` in import statements. ([#20634](https://github.com/angular/angular/issues/20634)) ([e543c73](https://github.com/angular/angular/commit/e543c73)), closes [#20363](https://github.com/angular/angular/issues/20363)
* **core:** Injector correctly honors the @Self flag ([#24520](https://github.com/angular/angular/issues/24520)) ([f5b3661](https://github.com/angular/angular/commit/f5b3661))
<a name="6.1.0-beta.1"></a>
# [6.1.0-beta.1](https://github.com/angular/angular/compare/6.1.0-beta.0...6.1.0-beta.1) (2018-06-13)
### Bug Fixes
* **animations:** always render end-state styles for orphaned DOM nodes ([#24236](https://github.com/angular/angular/issues/24236)) ([dc4a3d0](https://github.com/angular/angular/commit/dc4a3d0))
* **bazel:** Allow ng_module to depend on targets w no deps ([#24446](https://github.com/angular/angular/issues/24446)) ([282d351](https://github.com/angular/angular/commit/282d351))
* **docs-infra:** use script nomodule to load IE polyfills, skip other polyfills ([#24317](https://github.com/angular/angular/issues/24317)) ([8be6892](https://github.com/angular/angular/commit/8be6892)), closes [#23647](https://github.com/angular/angular/issues/23647)
* **ivy:** compute transitive scopes from NgModuleDef only ([#24334](https://github.com/angular/angular/issues/24334)) ([1135563](https://github.com/angular/angular/commit/1135563))
* **ivy:** correctly handle queries with embedded views ([#24418](https://github.com/angular/angular/issues/24418)) ([014949f](https://github.com/angular/angular/commit/014949f))
* **ivy:** remove debugger statement ([#24480](https://github.com/angular/angular/issues/24480)) ([70ef061](https://github.com/angular/angular/commit/70ef061))
* **ivy:** special case [style] and [class] bindings for future use ([#23232](https://github.com/angular/angular/issues/23232)) ([1b253e1](https://github.com/angular/angular/commit/1b253e1))
* **router:** fix lazy loading of aux routes ([#23459](https://github.com/angular/angular/issues/23459)) ([5731d07](https://github.com/angular/angular/commit/5731d07)), closes [#10981](https://github.com/angular/angular/issues/10981)
* **service-worker:** fix `SwPush.unsubscribe()` ([#24162](https://github.com/angular/angular/issues/24162)) ([3ed2d75](https://github.com/angular/angular/commit/3ed2d75)), closes [#24095](https://github.com/angular/angular/issues/24095)
### Features
* **common:** introduce KeyValuePipe ([#24319](https://github.com/angular/angular/issues/24319)) ([2b49bf7](https://github.com/angular/angular/commit/2b49bf7))
* **core:** export defaultKeyValueDiffers to private api ([#24319](https://github.com/angular/angular/issues/24319)) ([92b278c](https://github.com/angular/angular/commit/92b278c))
* **core:** expose a Compiler API for accessing module ids from NgModule types ([#24258](https://github.com/angular/angular/issues/24258)) ([bd02b27](https://github.com/angular/angular/commit/bd02b27))
* **core:** KeyValueDiffer#diff allows null values ([#24319](https://github.com/angular/angular/issues/24319)) ([52ce9d5](https://github.com/angular/angular/commit/52ce9d5))
* **ivy:** a generic visitor which allows prefixing nodes for ngtsc ([#24230](https://github.com/angular/angular/issues/24230)) ([ca79e11](https://github.com/angular/angular/commit/ca79e11))
* **ivy:** add support of ApplicationRef.bootstrapModuleFactory ([#23811](https://github.com/angular/angular/issues/23811)) ([e3759f7](https://github.com/angular/angular/commit/e3759f7))
* **ivy:** namespaced attributes added to output instructions ([#24386](https://github.com/angular/angular/issues/24386)) ([82c5313](https://github.com/angular/angular/commit/82c5313))
* **ivy:** now supports SVG and MathML elements ([#24377](https://github.com/angular/angular/issues/24377)) ([8c1ac28](https://github.com/angular/angular/commit/8c1ac28))
* **router:** implement scrolling restoration service ([#20030](https://github.com/angular/angular/issues/20030)) ([49c5234](https://github.com/angular/angular/commit/49c5234)), closes [#13636](https://github.com/angular/angular/issues/13636) [#10929](https://github.com/angular/angular/issues/10929) [#7791](https://github.com/angular/angular/issues/7791) [#6595](https://github.com/angular/angular/issues/6595)
<a name="6.0.5"></a>
## [6.0.5](https://github.com/angular/angular/compare/6.0.4...6.0.5) (2018-06-13)
@ -138,53 +163,6 @@
* **router:** fix lazy loading of aux routes ([#23459](https://github.com/angular/angular/issues/23459)) ([d20877b](https://github.com/angular/angular/commit/d20877b)), closes [#10981](https://github.com/angular/angular/issues/10981)
* **service-worker:** fix `SwPush.unsubscribe()` ([#24162](https://github.com/angular/angular/issues/24162)) ([ea2987c](https://github.com/angular/angular/commit/ea2987c)), closes [#24095](https://github.com/angular/angular/issues/24095)
<a name="6.1.0-beta.0"></a>
# [6.1.0-beta.0](https://github.com/angular/angular/compare/6.0.0-rc.5...6.1.0-beta.0) (2018-06-06)
### Bug Fixes
* **animations:** do not throw errors when a destroyed component is animated ([#23836](https://github.com/angular/angular/issues/23836)) ([d2a8687](https://github.com/angular/angular/commit/d2a8687))
* **animations:** Fix browser detection logic ([#24188](https://github.com/angular/angular/issues/24188)) ([b492b9e](https://github.com/angular/angular/commit/b492b9e))
* **animations:** properly clean up queried element styles in safari/edge ([#23633](https://github.com/angular/angular/issues/23633)) ([da9ff25](https://github.com/angular/angular/commit/da9ff25))
* **animations:** retain state styling for nodes that are moved around ([#23534](https://github.com/angular/angular/issues/23534)) ([65211f4](https://github.com/angular/angular/commit/65211f4))
* **animations:** retain trigger-state for nodes that are moved around ([#24238](https://github.com/angular/angular/issues/24238)) ([8db928d](https://github.com/angular/angular/commit/8db928d))
* **benchpress:** Fix promise chain in chrome_driver_extension. ([#23458](https://github.com/angular/angular/issues/23458)) ([d4b6c41](https://github.com/angular/angular/commit/d4b6c41))
* **compiler:** avoid a crash in ngc-wrapped. ([#23468](https://github.com/angular/angular/issues/23468)) ([e1c4930](https://github.com/angular/angular/commit/e1c4930))
* **compiler:** generate constant array for i18n attributes ([#23837](https://github.com/angular/angular/issues/23837)) ([cfde36d](https://github.com/angular/angular/commit/cfde36d))
* **compiler:** generate core-compliant hostBindings property ([#24087](https://github.com/angular/angular/issues/24087)) ([01b5acd](https://github.com/angular/angular/commit/01b5acd)), closes [#24013](https://github.com/angular/angular/issues/24013)
* **compiler:** handle undefined annotation metadata ([#23349](https://github.com/angular/angular/issues/23349)) ([ca776c5](https://github.com/angular/angular/commit/ca776c5))
* **compiler-cli:** don't rely on incompatible TS method ([#23550](https://github.com/angular/angular/issues/23550)) ([b1f040f](https://github.com/angular/angular/commit/b1f040f))
* **core:** avoid eager providers re-initialization ([#23559](https://github.com/angular/angular/issues/23559)) ([0c6dc45](https://github.com/angular/angular/commit/0c6dc45))
* **core:** call ngOnDestroy on all services that have it ([#23755](https://github.com/angular/angular/issues/23755)) ([fc03427](https://github.com/angular/angular/commit/fc03427)), closes [#22466](https://github.com/angular/angular/issues/22466) [#22240](https://github.com/angular/angular/issues/22240) [#14818](https://github.com/angular/angular/issues/14818)
* **elements:** always check to create strategy ([#23825](https://github.com/angular/angular/issues/23825)) ([b1cda36](https://github.com/angular/angular/commit/b1cda36))
* **elements:** prevent closure renaming of platform properties ([#23843](https://github.com/angular/angular/issues/23843)) ([d4b8b24](https://github.com/angular/angular/commit/d4b8b24))
* **forms:** properly handle special properties in FormGroup.get ([#22249](https://github.com/angular/angular/issues/22249)) ([9367e91](https://github.com/angular/angular/commit/9367e91)), closes [#17195](https://github.com/angular/angular/issues/17195)
* **platform-server:** avoid clash between server and client style encapsulation attributes ([#24158](https://github.com/angular/angular/issues/24158)) ([b96a3c8](https://github.com/angular/angular/commit/b96a3c8))
* **platform-server:** avoid dependency cycle when using http interceptor ([#24229](https://github.com/angular/angular/issues/24229)) ([60aa943](https://github.com/angular/angular/commit/60aa943)), closes [#23023](https://github.com/angular/angular/issues/23023)
* **platform-server:** don't reflect innerHTML property to attibute ([#24213](https://github.com/angular/angular/issues/24213)) ([6a663a4](https://github.com/angular/angular/commit/6a663a4)), closes [#19278](https://github.com/angular/angular/issues/19278)
* **platform-server:** provide Domino DOM types globally ([#24116](https://github.com/angular/angular/issues/24116)) ([c73196e](https://github.com/angular/angular/commit/c73196e)), closes [#23280](https://github.com/angular/angular/issues/23280) [#23133](https://github.com/angular/angular/issues/23133)
* **router:** avoid freezing queryParams in-place ([#22663](https://github.com/angular/angular/issues/22663)) ([89f64e5](https://github.com/angular/angular/commit/89f64e5)), closes [#22617](https://github.com/angular/angular/issues/22617)
* **router:** cache route handle if found ([#22475](https://github.com/angular/angular/issues/22475)) ([4cfa571](https://github.com/angular/angular/commit/4cfa571)), closes [#22474](https://github.com/angular/angular/issues/22474)
* **router:** correct the segment parsing so it won't break on ampersand ([#23684](https://github.com/angular/angular/issues/23684)) ([553a680](https://github.com/angular/angular/commit/553a680))
* **service-worker:** add badge to NOTIFICATION_OPTION_NAMES ([#23241](https://github.com/angular/angular/issues/23241)) ([fb59b2d](https://github.com/angular/angular/commit/fb59b2d)), closes [#23196](https://github.com/angular/angular/issues/23196)
* **service-worker:** check platformBrowser before accessing navigator.serviceWorker ([#21231](https://github.com/angular/angular/issues/21231)) ([0bdd30e](https://github.com/angular/angular/commit/0bdd30e))
* **service-worker:** correctly handle requests with empty `clientId` ([#23625](https://github.com/angular/angular/issues/23625)) ([e0ed59e](https://github.com/angular/angular/commit/e0ed59e)), closes [#23526](https://github.com/angular/angular/issues/23526)
* **service-worker:** deprecate `versionedFiles` in asset-group resources ([#23584](https://github.com/angular/angular/issues/23584)) ([1d378e2](https://github.com/angular/angular/commit/1d378e2))
### Features
* **compiler:** support `// ...` and `// TODO` in mock compiler expectations ([#23441](https://github.com/angular/angular/issues/23441)) ([c6b206e](https://github.com/angular/angular/commit/c6b206e))
* **compiler-cli:** update `tsickle` to `0.29.x` ([#24233](https://github.com/angular/angular/issues/24233)) ([f69ac67](https://github.com/angular/angular/commit/f69ac67))
* **platform-browser:** add HammerJS lazy-loader symbols to public API ([#23943](https://github.com/angular/angular/issues/23943)) ([26fbf1d](https://github.com/angular/angular/commit/26fbf1d))
* **platform-browser:** allow lazy-loading HammerJS ([#23906](https://github.com/angular/angular/issues/23906)) ([313bdce](https://github.com/angular/angular/commit/313bdce))
* **platform-server:** use EventManagerPlugin on the server ([#24132](https://github.com/angular/angular/issues/24132)) ([d6595eb](https://github.com/angular/angular/commit/d6595eb))
* **router:** add navigation execution context info to activation hooks ([#24204](https://github.com/angular/angular/issues/24204)) ([20c463e](https://github.com/angular/angular/commit/20c463e)), closes [#24202](https://github.com/angular/angular/issues/24202)
<a name="6.0.4"></a>
## [6.0.4](https://github.com/angular/angular/compare/6.0.3...6.0.4) (2018-06-06)
@ -263,7 +241,6 @@ To learn about the release highlights and our new CLI-powered update workflow fo
* **animations:** only use the WA-polyfill alongside AnimationBuilder ([#22143](https://github.com/angular/angular/issues/22143)) ([b2f366b](https://github.com/angular/angular/commit/b2f366b)), closes [#17496](https://github.com/angular/angular/issues/17496)
* **animations:** expose `element` and `params` within transition matchers ([#22693](https://github.com/angular/angular/issues/22693)) ([58b94e6](https://github.com/angular/angular/commit/58b94e6))
* **common:** better error message when non-template element used in NgIf ([#22274](https://github.com/angular/angular/issues/22274)) ([67cf11d](https://github.com/angular/angular/commit/67cf11d)), closes [#16410](https://github.com/angular/angular/issues/16410)
* **common:** better error message when non-template element used in NgIf ([#22274](https://github.com/angular/angular/issues/22274)) ([67cf11d](https://github.com/angular/angular/commit/67cf11d)), closes [#16410](https://github.com/angular/angular/issues/16410)
* **common:** export functions to format numbers, percents, currencies & dates ([#22423](https://github.com/angular/angular/issues/22423)) ([4180912](https://github.com/angular/angular/commit/4180912)), closes [#20536](https://github.com/angular/angular/issues/20536)
* **compiler:** lower @NgModule ids if needed ([#23031](https://github.com/angular/angular/issues/23031)) ([bd024c0](https://github.com/angular/angular/commit/bd024c0))
* **compiler:** implement "enableIvy" compiler option ([#21427](https://github.com/angular/angular/issues/21427)) ([64d16de](https://github.com/angular/angular/commit/64d16de))
@ -303,7 +280,6 @@ To learn about the release highlights and our new CLI-powered update workflow fo
* **animations:** report correct totalTime value even during noOp animations ([#22225](https://github.com/angular/angular/issues/22225)) ([e1bf067](https://github.com/angular/angular/commit/e1bf067))
* **animations:** avoid animation insertions during router back/refresh ([#21977](https://github.com/angular/angular/issues/21977)) ([f88fba0](https://github.com/angular/angular/commit/f88fba0)), closes [#19712](https://github.com/angular/angular/issues/19712)
* **animations:** treat numeric state name values as strings ([#22923](https://github.com/angular/angular/issues/22923)) ([e5e1b0d](https://github.com/angular/angular/commit/e5e1b0d))
* **animations:** report correct totalTime value even during noOp animations ([#22225](https://github.com/angular/angular/issues/22225)) ([e1bf067](https://github.com/angular/angular/commit/e1bf067))
* **animations:** fix increment/decrement aliases example ([#18323](https://github.com/angular/angular/issues/18323)) ([d2aa8ac](https://github.com/angular/angular/commit/d2aa8ac))
* **common:** NgClass should properly take className changes into account ([#21937](https://github.com/angular/angular/issues/21937)) ([4a42669](https://github.com/angular/angular/commit/4a42669)), closes [#21932](https://github.com/angular/angular/issues/21932)
* **common:** fix the titlecase pipe ([#22600](https://github.com/angular/angular/issues/22600)) ([7966744](https://github.com/angular/angular/commit/7966744))

View File

@ -6,9 +6,9 @@ workspace(name = "angular")
http_archive(
name = "build_bazel_rules_nodejs",
url = "https://github.com/bazelbuild/rules_nodejs/archive/0.10.1.zip",
strip_prefix = "rules_nodejs-0.10.1",
sha256 = "634206524d90dc03c52392fa3f19a16637d2bcf154910436fe1d669a0d9d7b9c",
url = "https://github.com/bazelbuild/rules_nodejs/archive/20ff5892612f8359aec8aaf26dd3902a24976ada.zip",
strip_prefix = "rules_nodejs-20ff5892612f8359aec8aaf26dd3902a24976ada",
sha256 = "07da9d4c3e688a02745d0f50709a87744706d4f5d1959b799b0ac38e97acd622",
)
http_archive(
@ -20,9 +20,9 @@ http_archive(
http_archive(
name = "build_bazel_rules_typescript",
url = "https://github.com/bazelbuild/rules_typescript/archive/0.15.1.zip",
strip_prefix = "rules_typescript-0.15.1",
sha256 = "3792cc20ef13bb1d1d8b1760894c3320f02a87843e3a04fed7e8e454a75328b6",
url = "https://github.com/bazelbuild/rules_typescript/archive/0.15.3.zip",
strip_prefix = "rules_typescript-0.15.3",
sha256 = "a2b26ac3fc13036011196063db1bf7f1eae81334449201dc28087ebfa3708c99",
)
http_archive(
@ -71,6 +71,22 @@ http_archive(
sha256 = "8a517806d2b7c8505ba5c53934e7d7c70d341b68ffd268e9044d35b564a48828",
)
#
# Point Bazel to WORKSPACEs that live in subdirectories
#
local_repository(
name = "rxjs",
path = "node_modules/rxjs/src",
)
# Point to the integration test workspace just so that Bazel doesn't descend into it
# when expanding the //... pattern
local_repository(
name = "bazel_integration_test",
path = "integration/bazel",
)
#
# Load and install our dependencies downloaded above.
#
@ -78,7 +94,10 @@ http_archive(
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories", "yarn_install")
check_bazel_version("0.15.0")
node_repositories(package_json = ["//:package.json"])
node_repositories(
package_json = ["//:package.json"],
preserve_symlinks = True,
)
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
@ -97,21 +116,9 @@ load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
ts_setup_workspace()
#
# Point Bazel to WORKSPACEs that live in subdirectories
#
load("@angular//:index.bzl", "ng_setup_workspace")
local_repository(
name = "rxjs",
path = "node_modules/rxjs/src",
)
# Point to the integration test workspace just so that Bazel doesn't descend into it
# when expanding the //... pattern
local_repository(
name = "bazel_integration_test",
path = "integration/bazel",
)
ng_setup_workspace()
#
# Ask Bazel to manage these toolchain dependencies for us.

View File

@ -43,6 +43,17 @@ Here are the most important tasks you might need to use:
* `yarn build-ie-polyfills` - generates a js file of polyfills that can be loaded in Internet Explorer.
## Developing on Windows
The `packages/` directory may contain Linux-specific symlinks, which are not recognized by Windows.
These unresolved links cause the docs generation process to fail because it cannot locate certain files.
> Hint: The following steps require administration rights or [Windows Developer Mode](https://docs.microsoft.com/en-us/windows/uwp/get-started/enable-your-device-for-development) enabled!
To fix this problem, run `scripts/windows/create-symlinks.sh`. This command creates temporary files where the symlinks used to be. Make sure not to commit those files with your documentation changes.
When you are done making and testing your documentation changes, you can restore the original symlinks and delete the temporary files by running `scripts/windows/remove-symlinks.sh`.
It's necessary to remove the temporary files, because otherwise they're displayed as local changes in your git working copy and certain operations are blocked.
## Using ServiceWorker locally
Since abb36e3cb, running `yarn start --prod` will no longer set up the ServiceWorker, which

View File

@ -5,7 +5,7 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
// #docregion directive-import
@ -24,7 +24,7 @@ import { ItemDirective } from './item.directive';
imports: [
BrowserModule,
FormsModule,
HttpModule
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]

View File

@ -1,7 +1,7 @@
// #docregion
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { HttpClientModule } from '@angular/common/http';
// import { AppRoutingModule } from './app-routing.module';
import { LocationStrategy,
@ -54,7 +54,7 @@ const c_components = [
imports: [
BrowserModule,
FormsModule,
HttpModule,
HttpClientModule,
InMemoryWebApiModule.forRoot(HeroData)
// AppRoutingModule TODO: add routes
],

View File

@ -1,26 +1,38 @@
import { ReflectiveInjector } from '@angular/core';
import { Injector } from '@angular/core';
import { Car, Engine, Tires } from './car';
import { Logger } from '../logger.service';
// #docregion injector
export function useInjector() {
let injector: ReflectiveInjector;
let injector: Injector;
// #enddocregion injector
/*
// #docregion injector-no-new
// Cannot instantiate an ReflectiveInjector like this!
let injector = new ReflectiveInjector([Car, Engine, Tires]);
// Cannot instantiate an Injector like this!
let injector = new Injector([
{ provide: Car, deps: [Engine, Tires] },
{ provide: Engine, deps: [] },
{ provide: Tires, deps: [] }
]);
// #enddocregion injector-no-new
*/
// #docregion injector, injector-create-and-call
injector = ReflectiveInjector.resolveAndCreate([Car, Engine, Tires]);
injector = Injector.create({
providers: [
{ provide: Car, deps: [Engine, Tires] },
{ provide: Engine, deps: [] },
{ provide: Tires, deps: [] }
]
});
// #docregion injector-call
let car = injector.get(Car);
// #enddocregion injector-call, injector-create-and-call
car.description = 'Injector';
injector = ReflectiveInjector.resolveAndCreate([Logger]);
injector = Injector.create({
providers: [{ provide: Logger, deps: [] }]
});
let logger = injector.get(Logger);
logger.log('Injector car.drive() said: ' + car.drive());
return car;

View File

@ -0,0 +1,69 @@
'use strict'; // necessary for es6 output in node
import { browser, by, element } from 'protractor';
/* tslint:disable:quotemark */
describe('Elements', () => {
const messageInput = element(by.css('input'));
const popupButtons = element.all(by.css('button'));
beforeEach(() => browser.get(''));
describe('popup component', () => {
const popupComponentButton = popupButtons.get(0);
const popupComponent = element(by.css('popup-component'));
const closeButton = popupComponent.element(by.css('button'));
it('should be displayed on button click', () => {
expect(popupComponent.isPresent()).toBe(false);
popupComponentButton.click();
expect(popupComponent.isPresent()).toBe(true);
});
it('should display the specified message', () => {
messageInput.clear();
messageInput.sendKeys('Angular rocks!');
popupComponentButton.click();
expect(popupComponent.getText()).toContain('Popup: Angular rocks!');
});
it('should be closed on "close" button click', () => {
popupComponentButton.click();
expect(popupComponent.isPresent()).toBe(true);
closeButton.click();
expect(popupComponent.isPresent()).toBe(false);
});
});
describe('popup element', () => {
const popupElementButton = popupButtons.get(1);
const popupElement = element(by.css('popup-element'));
const closeButton = popupElement.element(by.css('button'));
it('should be displayed on button click', () => {
expect(popupElement.isPresent()).toBe(false);
popupElementButton.click();
expect(popupElement.isPresent()).toBe(true);
});
it('should display the specified message', () => {
messageInput.clear();
messageInput.sendKeys('Angular rocks!');
popupElementButton.click();
expect(popupElement.getText()).toContain('Popup: Angular rocks!');
});
it('should be closed on "close" button click', () => {
popupElementButton.click();
expect(popupElement.isPresent()).toBe(true);
closeButton.click();
expect(popupElement.isPresent()).toBe(false);
});
});
});

View File

@ -0,0 +1,3 @@
{
"projectType": "elements"
}

View File

@ -1,6 +1,5 @@
// #docregion
import { Component, Injector } from '@angular/core';
import { createNgElementConstructor } from '../elements-dist';
import { createCustomElement } from '@angular/elements';
import { PopupService } from './popup.service';
import { PopupComponent } from './popup.component';
@ -8,19 +7,15 @@ import { PopupComponent } from './popup.component';
selector: 'app-root',
template: `
<input #input value="Message">
<button (click)="popup.showAsComponent(input.value)">
Show as component </button>
<button (click)="popup.showAsElement(input.value)">
Show as element </button>
`
<button (click)="popup.showAsComponent(input.value)">Show as component</button>
<button (click)="popup.showAsElement(input.value)">Show as element</button>
`,
})
export class AppComponent {
constructor(private injector: Injector, public popup: PopupService) {
// on init, convert PopupComponent to a custom element
const PopupElement =
createNgElementConstructor(PopupComponent, {injector: this.injector});
// register the custom element with the browser.
customElements.define('popup-element', PopupElement);
constructor(injector: Injector, public popup: PopupService) {
// Convert `PopupComponent` to a custom element.
const PopupElement = createCustomElement(PopupComponent, {injector});
// Register the custom element with the browser.
customElements.define('popup-element', PopupElement);
}
}

View File

@ -1,22 +1,21 @@
// #docregion
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { PopupService } from './popup.service';
import { PopupComponent } from './popup.component';
import { PopupService } from './popup.service';
// include the PopupService provider,
// but exclude PopupComponent from compilation,
// because it will be added dynamically
// Include the `PopupService` provider,
// but exclude `PopupComponent` from compilation,
// because it will be added dynamically.
@NgModule({
declarations: [AppComponent, PopupComponent],
imports: [BrowserModule, BrowserAnimationsModule],
providers: [PopupService],
declarations: [AppComponent, PopupComponent],
bootstrap: [AppComponent],
entryComponents: [PopupComponent],
})
export class AppModule {}
export class AppModule {
}

View File

@ -1,14 +1,14 @@
// #docregion
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { AnimationEvent } from '@angular/animations';
import { animate, state, style, transition, trigger } from '@angular/animations';
@Component({
selector: 'my-popup',
template: 'Popup: {{message}}',
template: `
<span>Popup: {{message}}</span>
<button (click)="closed.next()">&#x2716;</button>
`,
host: {
'[@state]': 'state',
'(@state.done)': 'onAnimationDone($event)',
},
animations: [
trigger('state', [
@ -27,13 +27,17 @@ import { animate, state, style, transition, trigger } from '@angular/animations'
height: 48px;
padding: 16px;
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px solid black;
font-size: 24px;
}
button {
border-radius: 50%;
}
`]
})
export class PopupComponent {
private state: 'opened' | 'closed' = 'closed';
@ -41,18 +45,10 @@ export class PopupComponent {
set message(message: string) {
this._message = message;
this.state = 'opened';
setTimeout(() => this.state = 'closed', 2000);
}
get message(): string { return this._message; }
_message: string;
@Output()
closed = new EventEmitter();
onAnimationDone(e: AnimationEvent) {
if (e.toState === 'closed') {
this.closed.next();
}
}
}

View File

@ -1,9 +1,8 @@
// #docregion
import { ApplicationRef, ComponentFactoryResolver, Injectable, Injector } from '@angular/core';
import { NgElement, WithProperties } from '@angular/elements';
import { PopupComponent } from './popup.component';
import { NgElementConstructor } from '../elements-dist';
@Injectable()
export class PopupService {
@ -40,7 +39,7 @@ export class PopupService {
// This uses the new custom-element method to add the popup to the DOM.
showAsElement(message: string) {
// Create element
const popupEl = document.createElement('popup-element');
const popupEl: NgElement & WithProperties<PopupComponent> = document.createElement('popup-element') as any;
// Listen to the close event
popupEl.addEventListener('closed', () => document.body.removeChild(popupEl));

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<base href="/">
<title>Elements</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<app-root></app-root>
</body>
</html>

View File

@ -1,4 +1,3 @@
// tslint:disable:no-unused-variable
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
@ -10,4 +9,3 @@ if (environment.production) {
}
platformBrowserDynamic().bootstrapModule(AppModule);

View File

@ -0,0 +1,9 @@
{
"description": "Angular Elements",
"files":[
"!**/*.d.ts",
"!**/*.js",
"!**/*.[1].*"
],
"tags":["cookbook"]
}

View File

@ -1,15 +1,14 @@
// #docplaster
// #docregion app-module
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
// import the feature module here so you can add it to the imports array below
import { CustomerDashboardModule } from './customer-dashboard/customer-dashboard.module';
@NgModule({
declarations: [
AppComponent
@ -17,7 +16,7 @@ import { CustomerDashboardModule } from './customer-dashboard/customer-dashboard
imports: [
BrowserModule,
FormsModule,
HttpModule,
HttpClientModule,
CustomerDashboardModule // add the feature module here
],
providers: [],

View File

@ -1,9 +1,9 @@
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppRoutingModule } from './app-routing.module';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
@ -13,7 +13,7 @@ import { AppComponent } from './app.component';
imports: [
BrowserModule,
FormsModule,
HttpModule,
HttpClientModule,
AppRoutingModule
],
providers: [],

View File

@ -1,7 +1,5 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
/* App Root */
import { AppComponent } from './app.component';

View File

@ -15,7 +15,7 @@ function sequenceSubscriber(observer) {
if (idx === arr.length - 1) {
observer.complete();
} else {
doSequence(arr, idx++);
doSequence(arr, ++idx);
}
}, 1000);
}
@ -95,7 +95,7 @@ function multicastSequenceSubscriber() {
},
complete() {
// Notify all complete callbacks
observers.forEach(obs => obs.complete());
observers.slice(0).forEach(obs => obs.complete());
}
}, seq, 0);
}
@ -121,13 +121,13 @@ function doSequence(observer, arr, idx) {
if (idx === arr.length - 1) {
observer.complete();
} else {
doSequence(observer, arr, idx++);
doSequence(observer, arr, ++idx);
}
}, 1000);
}
// Create a new Observable that will deliver the above sequence
const multicastSequence = new Observable(multicastSequenceSubscriber);
const multicastSequence = new Observable(multicastSequenceSubscriber());
// Subscribe starts the clock, and begins to emit after 1 second
multicastSequence.subscribe({

View File

@ -1,26 +1,21 @@
// #docregion
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import {
FlyingHeroesComponent,
FlyingHeroesImpureComponent
} from './flying-heroes.component';
import { ExponentialStrengthPipe } from './exponential-strength.pipe';
import { FetchJsonPipe } from './fetch-json.pipe';
import { FlyingHeroesComponent, FlyingHeroesImpureComponent } from './flying-heroes.component';
import { FlyingHeroesImpurePipe, FlyingHeroesPipe } from './flying-heroes.pipe';
import { HeroAsyncMessageComponent } from './hero-async-message.component';
import { HeroBirthdayComponent } from './hero-birthday1.component';
import { HeroBirthday2Component } from './hero-birthday2.component';
import { HeroListComponent } from './hero-list.component';
import { PowerBoosterComponent } from './power-booster.component';
import { PowerBoostCalculatorComponent } from './power-boost-calculator.component';
import {
FlyingHeroesPipe,
FlyingHeroesImpurePipe
} from './flying-heroes.pipe';
import { FetchJsonPipe } from './fetch-json.pipe';
import { ExponentialStrengthPipe } from './exponential-strength.pipe';
import { PowerBoosterComponent } from './power-booster.component';
@NgModule({
imports: [
@ -43,6 +38,6 @@ import { ExponentialStrengthPipe } from './exponential-strength.pipe';
FetchJsonPipe,
ExponentialStrengthPipe
],
bootstrap: [ AppComponent ]
bootstrap: [AppComponent]
})
export class AppModule { }

View File

@ -1,13 +1,14 @@
// #docregion
import { Pipe, PipeTransform } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Pipe, PipeTransform } from '@angular/core';
// #docregion pipe-metadata
@Pipe({
name: 'fetch',
pure: false
})
// #enddocregion pipe-metadata
export class FetchJsonPipe implements PipeTransform {
export class FetchJsonPipe implements PipeTransform {
private cachedData: any = null;
private cachedUrl = '';
@ -17,7 +18,7 @@ export class FetchJsonPipe implements PipeTransform {
if (url !== this.cachedUrl) {
this.cachedData = null;
this.cachedUrl = url;
this.http.get(url).subscribe( result => this.cachedData = result );
this.http.get(url).subscribe(result => this.cachedData = result);
}
return this.cachedData;

View File

@ -1,3 +0,0 @@
[1030/162525.401:ERROR:process_reader_win.cc(123)] NtOpenThread: {Acceso denegado} Un proceso ha solicitado acceso a un objeto, pero no se le han concedido esos derechos de acceso. (0xc0000022)
[1030/162525.402:ERROR:exception_snapshot_win.cc(87)] thread ID 26896 not found in process
[1030/162525.402:WARNING:crash_report_exception_handler.cc(62)] ProcessSnapshotWin::Initialize failed

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +0,0 @@
{
"description": "Angular Reactive Forms (final)",
"files":[
"src/styles.css",
"src/app/app.component.ts",
"src/app/app.component.html",
"src/app/app.component.css",
"src/app/app.module.ts",
"src/app/data-model.ts",
"src/app/hero.service.ts",
"src/app/hero-detail/hero-detail.component.html",
"src/app/hero-detail/hero-detail.component.ts",
"src/app/hero-detail/hero-detail.component.css",
"src/app/hero-list/hero-list.component.html",
"src/app/hero-list/hero-list.component.ts",
"src/app/hero-list/hero-list.component.css",
"src/main-final.ts",
"src/index-final.html"
],
"main": "src/index-final.html",
"tags": ["reactive", "forms"]
}

View File

@ -1,4 +1,10 @@
<div class="container">
<h1>Reactive Forms</h1>
<app-hero-detail></app-hero-detail>
</div>
<!-- #docplaster -->
<h1>Reactive Forms</h1>
<!-- #docregion app-name-editor-->
<app-name-editor></app-name-editor>
<!-- #enddocregion app-name-editor-->
<!-- #docregion app-profile-editor -->
<app-profile-editor></app-profile-editor>
<!-- #enddocregion app-profile-editor -->

View File

@ -1,4 +1,17 @@
<div class="container">
<h1>Reactive Forms</h1>
<app-hero-list></app-hero-list>
</div>
<!-- #docplaster -->
<!-- #docregion app-name-editor -->
<h1>Reactive Forms</h1>
<!-- #enddocregion app-name-editor -->
<nav>
<a (click)="toggleEditor('name')">Name Editor</a>
<a (click)="toggleEditor('profile')">Profile Editor</a>
</nav>
<!-- #docregion app-name-editor -->
<app-name-editor *ngIf="showNameEditor"></app-name-editor>
<!-- #enddocregion app-name-editor -->
<!-- #docregion app-profile-editor -->
<app-profile-editor *ngIf="showProfileEditor"></app-profile-editor>
<!-- #enddocregion app-profile-editor -->

View File

@ -0,0 +1,27 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to reactive-forms!');
}));
});

View File

@ -1,9 +1,24 @@
// #docregion
import { Component } from '@angular/core';
export type EditorType = 'name' | 'profile';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent { }
export class AppComponent {
editor: EditorType = 'name';
get showNameEditor() {
return this.editor === 'name';
}
get showProfileEditor() {
return this.editor === 'profile';
}
toggleEditor(type: EditorType) {
this.editor = type;
}
}

View File

@ -1,45 +1,34 @@
// #docplaster
// #docregion
// #docregion v1
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms'; // <-- #1 import module
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
// #docregion imports
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
// #enddocregion v1
// #docregion hero-service-list
// add JavaScript imports
import { HeroListComponent } from './hero-list/hero-list.component';
import { HeroService } from './hero.service';
// #docregion v1
// #enddocregion imports
import { AppComponent } from './app.component';
import { NameEditorComponent } from './name-editor/name-editor.component';
import { ProfileEditorComponent } from './profile-editor/profile-editor.component';
// #docregion imports
@NgModule({
// #enddocregion imports
declarations: [
AppComponent,
HeroDetailComponent,
// #enddocregion v1
HeroListComponent // <--declare HeroListComponent
// #docregion v1
NameEditorComponent,
ProfileEditorComponent
],
// #enddocregion hero-service-list
// #docregion imports
imports: [
// #enddocregion imports
BrowserModule,
ReactiveFormsModule // <-- #2 add to @NgModule imports
// #docregion imports
// other imports ...
ReactiveFormsModule
],
// #enddocregion v1
// export for the DemoModule
// #docregion hero-service-list
// ...
exports: [
AppComponent,
HeroDetailComponent,
HeroListComponent // <-- export HeroListComponent
],
providers: [ HeroService ], // <-- provide HeroService
// #enddocregion hero-service-list
// #docregion v1
bootstrap: [ AppComponent ]
// #enddocregion imports
providers: [],
bootstrap: [AppComponent]
// #docregion imports
})
export class AppModule { }
// #enddocregion v1
// #enddocregion imports

View File

@ -1,40 +0,0 @@
// #docregion
// #docregion model-classes
export class Hero {
id = 0;
name = '';
addresses: Address[];
}
export class Address {
street = '';
city = '';
state = '';
zip = '';
}
// #enddocregion model-classes
export const heroes: Hero[] = [
{
id: 1,
name: 'Whirlwind',
addresses: [
{street: '123 Main', city: 'Anywhere', state: 'CA', zip: '94801'},
{street: '456 Maple', city: 'Somewhere', state: 'VA', zip: '23226'},
]
},
{
id: 2,
name: 'Bombastic',
addresses: [
{street: '789 Elm', city: 'Smallville', state: 'OH', zip: '04501'},
]
},
{
id: 3,
name: 'Magneta',
addresses: [ ]
},
];
export const states = ['CA', 'MD', 'OH', 'VA'];

View File

@ -1,40 +0,0 @@
<div class="container">
<h1>Reactive Forms</h1>
<h4><i>Pick a demo:</i>
<select [selectedIndex]="demo - 1" (change)="selectDemo($event.target.selectedIndex)">
<option *ngFor="let demo of demos">{{demo}}</option>
</select>
</h4>
<hr>
<div class="demo">
<app-hero-list *ngIf="demo===final"></app-hero-list>
<app-hero-detail-1 *ngIf="demo===1"></app-hero-detail-1>
<app-hero-detail-2 *ngIf="demo===2"></app-hero-detail-2>
<app-hero-detail-3 *ngIf="demo===3"></app-hero-detail-3>
<app-hero-detail-4 *ngIf="demo===4"></app-hero-detail-4>
<app-hero-detail-5 *ngIf="demo===5"></app-hero-detail-5>
<div *ngIf="demo >= 6 && demo !== final" >
<h3 *ngIf="isLoading"><i>Loading heroes ... </i></h3>
<h3 *ngIf="!isLoading">Select a hero:</h3>
<nav>
<button (click)="getHeroes()" class="btn btn-primary">Refresh</button>
<a *ngFor="let hero of heroes | async" (click)="select(hero)">{{hero.name}}</a>
</nav>
<div *ngIf="selectedHero">
<hr>
<h2>Hero Detail</h2>
<h3>Editing: {{selectedHero.name}}</h3>
<app-hero-detail-6 [hero]=selectedHero *ngIf="demo===6"></app-hero-detail-6>
<app-hero-detail-7 [hero]=selectedHero *ngIf="demo===7"></app-hero-detail-7>
<app-hero-detail-8 [hero]=selectedHero *ngIf="demo===8"></app-hero-detail-8>
</div>
</div>
</div>
</div>

View File

@ -1,49 +0,0 @@
/* tslint:disable:member-ordering */
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { finalize } from 'rxjs/operators';
import { Hero } from './data-model';
import { HeroService } from './hero.service';
@Component({
selector: 'app-root',
templateUrl: './demo.component.html'
})
export class DemoComponent {
demos: string[] = [
'Just a FormControl',
'FormControl in a FormGroup',
'Simple FormBuilder group',
'Group with multiple controls',
'Nested FormBuilder group',
'PatchValue',
'SetValue',
'FormArray',
'Final'].map(n => n + ' Demo');
final = this.demos.length;
demo = this.final; // current demo
heroes: Observable<Hero[]>;
isLoading = false;
selectedHero: Hero;
constructor(private heroService: HeroService) { }
getHeroes() {
this.isLoading = true;
this.heroes = this.heroService.getHeroes().pipe(
finalize(() => this.isLoading = false)
);
this.selectedHero = undefined;
}
select(hero: Hero) { this.selectedHero = hero; }
selectDemo(demo: number) {
this.demo = demo + 1;
this.getHeroes();
}
}

View File

@ -1,33 +0,0 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { AppModule } from './app.module';
import { DemoComponent } from './demo.component';
import { HeroDetailComponent1 } from './hero-detail/hero-detail-1.component';
import { HeroDetailComponent2 } from './hero-detail/hero-detail-2.component';
import { HeroDetailComponent3 } from './hero-detail/hero-detail-3.component';
import { HeroDetailComponent4 } from './hero-detail/hero-detail-4.component';
import { HeroDetailComponent5 } from './hero-detail/hero-detail-5.component';
import { HeroDetailComponent6 } from './hero-detail/hero-detail-6.component';
import { HeroDetailComponent7 } from './hero-detail/hero-detail-7.component';
import { HeroDetailComponent8 } from './hero-detail/hero-detail-8.component';
@NgModule({
imports: [
BrowserModule,
ReactiveFormsModule,
AppModule,
],
declarations: [ DemoComponent,
HeroDetailComponent1,
HeroDetailComponent2,
HeroDetailComponent3,
HeroDetailComponent4,
HeroDetailComponent5,
HeroDetailComponent6,
HeroDetailComponent7,
HeroDetailComponent8],
bootstrap: [ DemoComponent ]
})
export class DemoModule { }

View File

@ -1,8 +0,0 @@
<!-- #docregion simple-control-->
<h2>Hero Detail</h2>
<h3><i>Just a FormControl</i></h3>
<label class="center-block">Name:
<input class="form-control" [formControl]="name">
</label>
<!-- #enddocregion simple-control-->

View File

@ -1,15 +0,0 @@
/* tslint:disable:component-class-suffix */
import { Component } from '@angular/core';
// #docregion import
import { FormControl } from '@angular/forms';
// #enddocregion import
@Component({
selector: 'app-hero-detail-1',
templateUrl: './hero-detail-1.component.html'
})
// #docregion v1
export class HeroDetailComponent1 {
name = new FormControl();
}

View File

@ -1,18 +0,0 @@
<!-- #docregion basic-form-->
<h2>Hero Detail</h2>
<h3><i>FormControl in a FormGroup</i></h3>
<form [formGroup]="heroForm">
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">
</label>
</div>
</form>
<!-- #enddocregion basic-form-->
<!-- #docregion form-value-json -->
<p>Form value: {{ heroForm.value | json }}</p>
<!-- #enddocregion form-value-json -->

View File

@ -1,17 +0,0 @@
/* tslint:disable:component-class-suffix */
// #docregion imports
import { Component } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
// #enddocregion imports
@Component({
selector: 'app-hero-detail-2',
templateUrl: './hero-detail-2.component.html'
})
// #docregion v2
export class HeroDetailComponent2 {
heroForm = new FormGroup ({
name: new FormControl()
});
}
// #enddocregion v2

View File

@ -1,16 +0,0 @@
<!-- #docregion basic-form-->
<h2>Hero Detail</h2>
<h3><i>A FormGroup with a single FormControl using FormBuilder</i></h3>
<form [formGroup]="heroForm">
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">
</label>
</div>
</form>
<!-- #enddocregion basic-form-->
<!-- #docregion form-value-json -->
<p>Form value: {{ heroForm.value | json }}</p>
<p>Form status: {{ heroForm.status | json }}</p>
<!-- #enddocregion form-value-json -->

View File

@ -1,27 +0,0 @@
/* tslint:disable:component-class-suffix */
// #docregion imports
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
// #enddocregion imports
@Component({
selector: 'app-hero-detail-3',
templateUrl: './hero-detail-3.component.html'
})
// #docregion v3
export class HeroDetailComponent3 {
heroForm: FormGroup; // <--- heroForm is of type FormGroup
constructor(private fb: FormBuilder) { // <--- inject FormBuilder
this.createForm();
}
createForm() {
// #docregion required
this.heroForm = this.fb.group({
name: ['', Validators.required ],
});
// #enddocregion required
}
}
// #enddocregion v3

View File

@ -1,25 +0,0 @@
/* tslint:disable:component-class-suffix */
// #docregion imports
import { Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
// #enddocregion imports
@Component({
selector: 'app-hero-detail-3',
templateUrl: './hero-detail-3.component.html'
})
// #docregion v3a
export class HeroDetailComponent3 {
heroForm: FormGroup; // <--- heroForm is of type FormGroup
constructor(private fb: FormBuilder) { // <--- inject FormBuilder
this.createForm();
}
createForm() {
this.heroForm = this.fb.group({
name: '', // <--- the FormControl called "name"
});
}
}
// #enddocregion v3a

View File

@ -1,46 +0,0 @@
<!-- #docregion -->
<h2>Hero Detail</h2>
<h3><i>A FormGroup with multiple FormControls</i></h3>
<form [formGroup]="heroForm">
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">
</label>
</div>
<div class="form-group">
<label class="center-block">Street:
<input class="form-control" formControlName="street">
</label>
</div>
<div class="form-group">
<label class="center-block">City:
<input class="form-control" formControlName="city">
</label>
</div>
<div class="form-group">
<label class="center-block">State:
<select class="form-control" formControlName="state">
<option *ngFor="let state of states" [value]="state">{{state}}</option>
</select>
</label>
</div>
<div class="form-group">
<label class="center-block">Zip Code:
<input class="form-control" formControlName="zip">
</label>
</div>
<div class="form-group radio">
<h4>Super power:</h4>
<label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
<label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
<label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
</div>
<div class="checkbox">
<label class="center-block">
<input type="checkbox" formControlName="sidekick">I have a sidekick.
</label>
</div>
</form>
<p>Form value: {{ heroForm.value | json }}</p>

View File

@ -1,34 +0,0 @@
/* tslint:disable:component-class-suffix */
// #docregion imports
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { states } from '../data-model';
// #enddocregion imports
@Component({
selector: 'app-hero-detail-4',
templateUrl: './hero-detail-4.component.html'
})
// #docregion v4
export class HeroDetailComponent4 {
heroForm: FormGroup;
states = states;
constructor(private fb: FormBuilder) {
this.createForm();
}
createForm() {
this.heroForm = this.fb.group({
name: ['', Validators.required ],
street: '',
city: '',
state: '',
zip: '',
power: '',
sidekick: ''
});
}
}
// #enddocregion v4

View File

@ -1,56 +0,0 @@
<form [formGroup]="heroForm">
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">
</label>
</div>
<!-- #docregion add-group-->
<div formGroupName="address" class="well well-lg">
<h4>Secret Lair</h4>
<div class="form-group">
<label class="center-block">Street:
<input class="form-control" formControlName="street">
</label>
</div>
<div class="form-group">
<label class="center-block">City:
<input class="form-control" formControlName="city">
</label>
</div>
<div class="form-group">
<label class="center-block">State:
<select class="form-control" formControlName="state">
<option *ngFor="let state of states" [value]="state">{{state}}</option>
</select>
</label>
</div>
<div class="form-group">
<label class="center-block">Zip Code:
<input class="form-control" formControlName="zip">
</label>
</div>
</div>
<!-- #enddocregion add-group-->
<div class="form-group radio">
<h4>Super power:</h4>
<label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
<label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
<label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
</div>
<div class="checkbox">
<label class="center-block">
<input type="checkbox" formControlName="sidekick">I have a sidekick.
</label>
</div>
</form>
<p>heroForm value: {{ heroForm.value | json}}</p>
<h4>Extra info for the curious:</h4>
<!-- #docregion inspect-value -->
<p>Name value: {{ heroForm.get('name').value }}</p>
<!-- #enddocregion inspect-value -->
<!-- #docregion inspect-child-control -->
<p>Street value: {{ heroForm.get('address.street').value}}</p>
<!-- #enddocregion inspect-child-control -->

View File

@ -1,35 +0,0 @@
/* tslint:disable:component-class-suffix */
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { states } from '../data-model';
@Component({
selector: 'app-hero-detail-5',
templateUrl: './hero-detail-5.component.html'
})
// #docregion v5
export class HeroDetailComponent5 {
heroForm: FormGroup;
states = states;
constructor(private fb: FormBuilder) {
this.createForm();
}
createForm() {
this.heroForm = this.fb.group({ // <-- the parent FormGroup
name: ['', Validators.required ],
address: this.fb.group({ // <-- the child FormGroup
street: '',
city: '',
state: '',
zip: ''
}),
power: '',
sidekick: ''
});
}
}
// #enddocregion v5

View File

@ -1,46 +0,0 @@
<!-- #docregion -->
<h2>Hero Detail</h2>
<h3><i>PatchValue to initialize a value</i></h3>
<form [formGroup]="heroForm">
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">
</label>
</div>
<div class="form-group">
<label class="center-block">Street:
<input class="form-control" formControlName="street">
</label>
</div>
<div class="form-group">
<label class="center-block">City:
<input class="form-control" formControlName="city">
</label>
</div>
<div class="form-group">
<label class="center-block">State:
<select class="form-control" formControlName="state">
<option *ngFor="let state of states" [value]="state">{{state}}</option>
</select>
</label>
</div>
<div class="form-group">
<label class="center-block">Zip Code:
<input class="form-control" formControlName="zip">
</label>
</div>
<div class="form-group radio">
<h4>Super power:</h4>
<label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
<label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
<label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
</div>
<div class="checkbox">
<label class="center-block">
<input type="checkbox" formControlName="sidekick">I have a sidekick.
</label>
</div>
</form>
<p>Form value: {{ heroForm.value | json }}</p>

View File

@ -1,66 +0,0 @@
/* tslint:disable:component-class-suffix */
// #docregion import-input
import { Component, Input, OnChanges } from '@angular/core';
// #enddocregion import-input
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
// #docregion import-hero
import { Hero, states } from '../data-model';
// #enddocregion import-hero
////////// 6 ////////////////////
@Component({
selector: 'app-hero-detail-6',
templateUrl: './hero-detail-5.component.html'
})
// #docregion v6
export class HeroDetailComponent6 implements OnChanges {
// #docregion hero
@Input() hero: Hero;
// #enddocregion hero
heroForm: FormGroup;
states = states;
constructor(private fb: FormBuilder) {
this.createForm();
}
createForm() {
// #docregion hero-form-model
this.heroForm = this.fb.group({
name: ['', Validators.required ],
address: this.fb.group({
street: '',
city: '',
state: '',
zip: ''
}),
power: '',
sidekick: ''
});
// #enddocregion hero-form-model
}
// #docregion patch-value-on-changes
ngOnChanges() { // <-- call rebuildForm in ngOnChanges
this.rebuildForm();
}
// #enddocregion patch-value-on-changes
// #docregion patch-value-rebuildform
rebuildForm() { // <-- wrap patchValue in rebuildForm
this.heroForm.reset();
// #docregion patch-value
this.heroForm.patchValue({
name: this.hero.name
});
// #enddocregion patch-value
}
// #enddocregion patch-value-rebuildform
}
// #enddocregion v6

View File

@ -1,46 +0,0 @@
<!-- #docregion -->
<h2>Hero Detail</h2>
<h3><i>A FormGroup with multiple FormControls</i></h3>
<form [formGroup]="heroForm">
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">
</label>
</div>
<div class="form-group">
<label class="center-block">Street:
<input class="form-control" formControlName="street">
</label>
</div>
<div class="form-group">
<label class="center-block">City:
<input class="form-control" formControlName="city">
</label>
</div>
<div class="form-group">
<label class="center-block">State:
<select class="form-control" formControlName="state">
<option *ngFor="let state of states" [value]="state">{{state}}</option>
</select>
</label>
</div>
<div class="form-group">
<label class="center-block">Zip Code:
<input class="form-control" formControlName="zip">
</label>
</div>
<div class="form-group radio">
<h4>Super power:</h4>
<label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
<label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
<label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
</div>
<div class="checkbox">
<label class="center-block">
<input type="checkbox" formControlName="sidekick">I have a sidekick.
</label>
</div>
</form>
<p>Form value: {{ heroForm.value | json }}</p>

View File

@ -1,68 +0,0 @@
/* tslint:disable:component-class-suffix */
// #docplaster
// #docregion imports
import { Component, Input, OnChanges } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
// #docregion import-address
import { Address, Hero, states } from '../data-model';
// #enddocregion import-address
// #enddocregion imports
@Component({
selector: 'app-hero-detail-7',
templateUrl: './hero-detail-5.component.html'
})
// #docregion v7
export class HeroDetailComponent7 implements OnChanges {
@Input() hero: Hero;
heroForm: FormGroup;
states = states;
constructor(private fb: FormBuilder) {
this.createForm();
}
createForm() {
// #docregion address-form-group
this.heroForm = this.fb.group({
name: ['', Validators.required ],
address: this.fb.group(new Address()), // <-- a FormGroup with a new address
power: '',
sidekick: ''
});
// #enddocregion address-form-group
}
// #docregion ngOnChanges
ngOnChanges() {
this.rebuildForm();
}
// #enddocregion ngOnChanges
// #docregion rebuildForm
rebuildForm() {
this.heroForm.reset({
name: this.hero.name,
// #docregion set-value-address
address: this.hero.addresses[0] || new Address()
// #enddocregion set-value-address
});
}
// #enddocregion rebuildForm
/* First version of rebuildForm */
rebuildForm1() {
// #docregion reset
this.heroForm.reset();
// #enddocregion reset
// #docregion set-value
this.heroForm.setValue({
name: this.hero.name,
address: this.hero.addresses[0] || new Address()
});
// #enddocregion set-value
}
}

View File

@ -1,72 +0,0 @@
<!-- #docplaster-->
<h3><i>Using FormArray to add groups</i></h3>
<form [formGroup]="heroForm">
<p>Form Changed: {{ heroForm.dirty }}</p>
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">
</label>
</div>
<!-- #docregion form-array-->
<!-- #docregion form-array-skeleton -->
<!-- #docregion form-array-name -->
<div formArrayName="secretLairs" class="well well-lg">
<!-- #enddocregion form-array-name -->
<div *ngFor="let address of secretLairs.controls; let i=index" [formGroupName]="i" >
<!-- The repeated address template -->
<!-- #enddocregion form-array-skeleton -->
<h4>Address #{{i + 1}}</h4>
<div style="margin-left: 1em;">
<div class="form-group">
<label class="center-block">Street:
<input class="form-control" formControlName="street">
</label>
</div>
<div class="form-group">
<label class="center-block">City:
<input class="form-control" formControlName="city">
</label>
</div>
<div class="form-group">
<label class="center-block">State:
<select class="form-control" formControlName="state">
<option *ngFor="let state of states" [value]="state">{{state}}</option>
</select>
</label>
</div>
<div class="form-group">
<label class="center-block">Zip Code:
<input class="form-control" formControlName="zip">
</label>
</div>
</div>
<br>
<!-- End of the repeated address template -->
<!-- #docregion form-array-skeleton -->
</div>
<!-- #enddocregion form-array-skeleton -->
<!-- #enddocregion form-array-->
<!-- #docregion add-lair -->
<button (click)="addLair()" type="button">Add a Secret Lair</button>
<!-- #enddocregion add-lair -->
<!-- #docregion form-array-->
<!-- #docregion form-array-skeleton -->
</div>
<!-- #enddocregion form-array-skeleton -->
<!-- #enddocregion form-array-->
<div class="form-group radio">
<h4>Super power:</h4>
<label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
<label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
<label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
</div>
<div class="checkbox">
<label class="center-block">
<input type="checkbox" formControlName="sidekick">I have a sidekick.
</label>
</div>
</form>
<p>heroForm value: {{ heroForm.value | json}}</p>

View File

@ -1,74 +0,0 @@
/* tslint:disable:component-class-suffix */
// #docregion imports
import { Component, Input, OnChanges } from '@angular/core';
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Address, Hero, states } from '../data-model';
// #enddocregion imports
@Component({
selector: 'app-hero-detail-8',
templateUrl: './hero-detail-8.component.html'
})
// #docregion v8
export class HeroDetailComponent8 implements OnChanges {
@Input() hero: Hero;
heroForm: FormGroup;
states = states;
// #docregion ctor
constructor(private fb: FormBuilder) {
this.createForm();
this.logNameChange();
}
// #enddocregion ctor
createForm() {
// #docregion secretLairs-form-array
this.heroForm = this.fb.group({
name: ['', Validators.required ],
secretLairs: this.fb.array([]), // <-- secretLairs as an empty FormArray
power: '',
sidekick: ''
});
// #enddocregion secretLairs-form-array
}
logNameChange() {/* Coming soon */}
// #docregion onchanges
ngOnChanges() {
this.rebuildForm();
}
// #enddocregion onchanges
// #docregion rebuildform
rebuildForm() {
this.heroForm.reset({
name: this.hero.name
});
this.setAddresses(this.hero.addresses);
}
// #enddocregion rebuildform
// #docregion get-secret-lairs
get secretLairs(): FormArray {
return this.heroForm.get('secretLairs') as FormArray;
};
// #enddocregion get-secret-lairs
// #docregion set-addresses
setAddresses(addresses: Address[]) {
const addressFGs = addresses.map(address => this.fb.group(address));
const addressFormArray = this.fb.array(addressFGs);
this.heroForm.setControl('secretLairs', addressFormArray);
}
// #enddocregion set-addresses
// #docregion add-lair
addLair() {
this.secretLairs.push(this.fb.group(new Address()));
}
// #enddocregion add-lair
}

View File

@ -1,73 +0,0 @@
<!-- #docplaster -->
<!-- #docregion -->
<!-- #docregion buttons -->
<form [formGroup]="heroForm" (ngSubmit)="onSubmit()">
<div style="margin-bottom: 1em">
<button type="submit"
[disabled]="heroForm.pristine" class="btn btn-success">Save</button> &nbsp;
<button type="button" (click)="revert()"
[disabled]="heroForm.pristine" class="btn btn-danger">Revert</button>
</div>
<!-- Hero Detail Controls -->
<!-- #enddocregion buttons -->
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">
</label>
</div>
<div formArrayName="secretLairs" class="well well-lg">
<div *ngFor="let address of secretLairs.controls; let i=index" [formGroupName]="i" >
<!-- The repeated address template -->
<h4>Address #{{i + 1}}</h4>
<div style="margin-left: 1em;">
<div class="form-group">
<label class="center-block">Street:
<input class="form-control" formControlName="street">
</label>
</div>
<div class="form-group">
<label class="center-block">City:
<input class="form-control" formControlName="city">
</label>
</div>
<div class="form-group">
<label class="center-block">State:
<select class="form-control" formControlName="state">
<option *ngFor="let state of states" [value]="state">{{state}}</option>
</select>
</label>
</div>
<div class="form-group">
<label class="center-block">Zip Code:
<input class="form-control" formControlName="zip">
</label>
</div>
</div>
<br>
<!-- End of the repeated address template -->
</div>
<button (click)="addLair()" type="button">Add a Secret Lair</button>
</div>
<!-- #docregion buttons -->
<div class="form-group radio">
<h4>Super power:</h4>
<label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
<label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
<label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
</div>
<div class="checkbox">
<label class="center-block">
<input type="checkbox" formControlName="sidekick">I have a sidekick.
</label>
</div>
</form>
<!-- #enddocregion buttons -->
<p>heroForm value: {{ heroForm.value | json}}</p>
<!-- #docregion name-change-log -->
<h4>Name change log</h4>
<div *ngFor="let name of nameChangeLog">{{name}}</div>
<!-- #enddocregion name-change-log -->

View File

@ -1,113 +0,0 @@
// #docplaster
// #docregion
import { Component, Input, OnChanges } from '@angular/core';
import { FormArray, FormBuilder, FormGroup } from '@angular/forms';
import { Address, Hero, states } from '../data-model';
// #docregion import-service
import { HeroService } from '../hero.service';
// #enddocregion import-service
@Component({
selector: 'app-hero-detail',
templateUrl: './hero-detail.component.html',
styleUrls: ['./hero-detail.component.css']
})
// #docregion onchanges-implementation
export class HeroDetailComponent implements OnChanges {
// #enddocregion onchanges-implementation
@Input() hero: Hero;
heroForm: FormGroup;
// #docregion log-name-change
nameChangeLog: string[] = [];
// #enddocregion log-name-change
states = states;
// #docregion ctor
constructor(
private fb: FormBuilder,
private heroService: HeroService) {
this.createForm();
this.logNameChange();
}
// #enddocregion ctor
createForm() {
this.heroForm = this.fb.group({
name: '',
secretLairs: this.fb.array([]),
power: '',
sidekick: ''
});
}
ngOnChanges() {
this.rebuildForm();
}
rebuildForm() {
this.heroForm.reset({
name: this.hero.name
});
this.setAddresses(this.hero.addresses);
}
get secretLairs(): FormArray {
return this.heroForm.get('secretLairs') as FormArray;
};
setAddresses(addresses: Address[]) {
const addressFGs = addresses.map(address => this.fb.group(address));
const addressFormArray = this.fb.array(addressFGs);
this.heroForm.setControl('secretLairs', addressFormArray);
}
addLair() {
this.secretLairs.push(this.fb.group(new Address()));
}
// #docregion on-submit
onSubmit() {
this.hero = this.prepareSaveHero();
this.heroService.updateHero(this.hero).subscribe(/* error handling */);
this.rebuildForm();
}
// #enddocregion on-submit
// #docregion prepare-save-hero
prepareSaveHero(): Hero {
const formModel = this.heroForm.value;
// deep copy of form model lairs
const secretLairsDeepCopy: Address[] = formModel.secretLairs.map(
(address: Address) => Object.assign({}, address)
);
// return new `Hero` object containing a combination of original hero value(s)
// and deep copies of changed form model values
const saveHero: Hero = {
id: this.hero.id,
name: formModel.name as string,
// addresses: formModel.secretLairs // <-- bad!
addresses: secretLairsDeepCopy
};
return saveHero;
}
// #enddocregion prepare-save-hero
// #docregion revert
revert() { this.rebuildForm(); }
// #enddocregion revert
// #docregion log-name-change
logNameChange() {
const nameControl = this.heroForm.get('name');
nameControl.valueChanges.forEach(
(value: string) => this.nameChangeLog.push(value)
);
}
// #enddocregion log-name-change
}

View File

@ -1,8 +0,0 @@
<!-- #docregion -->
<nav>
<a *ngFor="let hero of heroes | async" (click)="select(hero)">{{hero.name}}</a>
</nav>
<div *ngIf="selectedHero">
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
</div>

View File

@ -1,17 +0,0 @@
<!-- #docregion -->
<h3 *ngIf="isLoading"><i>Loading heroes ... </i></h3>
<h3 *ngIf="!isLoading">Select a hero:</h3>
<nav>
<button (click)="getHeroes()" class="btn btn-primary">Refresh</button>
<a *ngFor="let hero of heroes | async" (click)="select(hero)">{{hero.name}}</a>
</nav>
<div *ngIf="selectedHero">
<hr>
<h2>Hero Detail</h2>
<h3>Editing: {{selectedHero.name}}</h3>
<!-- #docregion hero-binding -->
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
<!-- #enddocregion hero-binding -->
</div>

View File

@ -1,32 +0,0 @@
// #docregion
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { finalize } from 'rxjs/operators';
import { Hero } from '../data-model';
import { HeroService } from '../hero.service';
@Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html',
styleUrls: ['./hero-list.component.css']
})
export class HeroListComponent implements OnInit {
heroes: Observable<Hero[]>;
isLoading = false;
selectedHero: Hero;
constructor(private heroService: HeroService) { }
ngOnInit() { this.getHeroes(); }
getHeroes() {
this.isLoading = true;
this.heroes = this.heroService.getHeroes()
// TODO: error handling
.pipe(finalize(() => this.isLoading = false));
this.selectedHero = undefined;
}
select(hero: Hero) { this.selectedHero = hero; }
}

View File

@ -1,25 +0,0 @@
// #docregion
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { delay } from 'rxjs/operators';
import { Hero, heroes } from './data-model';
@Injectable()
export class HeroService {
delayMs = 500;
// Fake server get; assume nothing can go wrong
getHeroes(): Observable<Hero[]> {
return of(heroes).pipe(delay(this.delayMs)); // simulate latency with delay
}
// Fake server update; assume nothing can go wrong
updateHero(hero: Hero): Observable<Hero> {
const oldHero = heroes.find(h => h.id === hero.id);
const newHero = Object.assign(oldHero, hero); // Demo: mutate cached hero
return of(newHero).pipe(delay(this.delayMs)); // simulate latency with delay
}
}

View File

@ -0,0 +1,19 @@
:host {
display: flex;
flex-direction: column;
padding-top: 24px;
}
label {
display: block;
width: 6em;
margin: .5em 0;
color: #607D8B;
font-weight: bold;
}
input {
height: 2em;
font-size: 1em;
padding-left: .4em;
}

View File

@ -0,0 +1,21 @@
<!-- #docregion control-binding -->
<label>
Name:
<input type="text" [formControl]="name">
</label>
<!-- #enddocregion control-binding -->
<!-- #docregion display-value -->
<p>
Value: {{ name.value }}
</p>
<!-- #enddocregion display-value -->
<!-- #docregion update-value -->
<p>
<button (click)="updateName()">Update Name</button>
</p>
<!-- #enddocregion update-value -->

View File

@ -0,0 +1,22 @@
// #docplaster
// #docregion create-control
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
@Component({
selector: 'app-name-editor',
templateUrl: './name-editor.component.html',
styleUrls: ['./name-editor.component.css']
})
export class NameEditorComponent {
name = new FormControl('');
// #enddocregion create-control
// #docregion update-value
updateName() {
this.name.setValue('Nancy');
}
// #enddocregion update-value
// #docregion create-control
}
// #enddocregion create-control

View File

@ -0,0 +1,67 @@
<!-- #docplaster -->
<!-- #docregion formgroup -->
<form [formGroup]="profileForm">
<label>
First Name:
<input type="text" formControlName="firstName">
</label>
<label>
Last Name:
<input type="text" formControlName="lastName">
</label>
<!-- #enddocregion formgroup -->
<!-- #docregion formgroupname -->
<div formGroupName="address">
<h3>Address</h3>
<label>
Street:
<input type="text" formControlName="street">
</label>
<label>
City:
<input type="text" formControlName="city">
</label>
<label>
State:
<input type="text" formControlName="state">
</label>
<label>
Zip Code:
<input type="text" formControlName="zip">
</label>
</div>
<!-- #enddocregion formgroupname -->
<!-- #docregion formarrayname -->
<div formArrayName="aliases">
<h3>Aliases</h3> <button (click)="addAlias()">Add Alias</button>
<div *ngFor="let address of aliases.controls; let i=index">
<!-- The repeated alias template -->
<label>
Alias:
<input type="text" [formControlName]="i">
</label>
</div>
</div>
<!-- #enddocregion formarrayname -->
<!-- #docregion formgroup -->
</form>
<!-- #enddocregion formgroup -->
<p>
Form Value: {{ profileForm.value | json }}
</p>
<!-- #docregion patch-value -->
<p>
<button (click)="updateProfile()">Update Profile</button>
</p>
<!-- #enddocregion patch-value -->

View File

@ -0,0 +1,40 @@
// #docplaster
// #docregion formgroup, nested-formgroup
import { Component } from '@angular/core';
// #docregion imports
import { FormGroup, FormControl } from '@angular/forms';
// #enddocregion imports
@Component({
selector: 'app-profile-editor',
templateUrl: './profile-editor.component.html',
styleUrls: ['./profile-editor.component.css']
})
export class ProfileEditorComponent {
// #docregion formgroup-compare
profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
// #enddocregion formgroup
address: new FormGroup({
street: new FormControl(''),
city: new FormControl(''),
state: new FormControl(''),
zip: new FormControl('')
})
// #docregion formgroup
});
// #enddocregion formgroup, nested-formgroup, formgroup-compare
// #docregion patch-value
updateProfile() {
this.profileForm.patchValue({
firstName: 'Nancy',
address: {
street: '123 Drew Street'
}
});
}
// #enddocregion patch-value
// #docregion formgroup, nested-formgroup
}
// #enddocregion formgroup

View File

@ -0,0 +1,58 @@
// #docplaster
// #docregion form-builder
import { Component } from '@angular/core';
// #docregion form-builder-imports
import { FormBuilder } from '@angular/forms';
// #enddocregion form-builder-imports, form-builder
// #docregion form-array-imports
import { FormArray } from '@angular/forms';
// #docregion form-builder-imports, form-builder
// #enddocregion form-builder-imports, form-array-imports
@Component({
selector: 'app-profile-editor',
templateUrl: './profile-editor.component.html',
styleUrls: ['./profile-editor.component.css']
})
export class ProfileEditorComponent {
// #docregion formgroup-compare
profileForm = this.fb.group({
firstName: [''],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: ['']
}),
// #enddocregion form-builder, formgroup-compare
aliases: this.fb.array([
this.fb.control('')
])
// #docregion form-builder, formgroup-compare
});
// #enddocregion form-builder, formgroup-compare
get aliases() {
return this.profileForm.get('aliases') as FormArray;
}
// #docregion inject-form-builder, form-builder
constructor(private fb: FormBuilder) { }
// #enddocregion inject-form-builder, form-builder
updateProfile() {
this.profileForm.patchValue({
firstName: 'Nancy',
address: {
street: '123 Drew Street'
}
});
}
addAlias() {
this.aliases.push(this.fb.control(''));
}
// #docregion form-builder
}
// #enddocregion form-builder

View File

@ -0,0 +1,39 @@
/* ProfileEditorComponent's private CSS styles */
:host {
display: flex;
flex-direction: column;
padding-top: 24px;
}
label {
display: block;
width: 6em;
margin: .5em 0;
color: #607D8B;
font-weight: bold;
}
input {
height: 2em;
font-size: 1em;
padding-left: .4em;
}
button {
font-family: Arial;
background-color: #eee;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #cfd8dc;
}
button:disabled {
background-color: #eee;
color: #ccc;
cursor: auto;
}

View File

@ -0,0 +1,80 @@
<!-- #docplaster -->
<!-- #docregion ng-submit -->
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
<!-- #enddocregion ng-submit -->
<label>
First Name:
<!-- #docregion required-attribute -->
<input type="text" formControlName="firstName" required>
<!-- #enddocregion required-attribute -->
</label>
<label>
Last Name:
<input type="text" formControlName="lastName">
</label>
<div formGroupName="address">
<h3>Address</h3>
<label>
Street:
<input type="text" formControlName="street">
</label>
<label>
City:
<input type="text" formControlName="city">
</label>
<label>
State:
<input type="text" formControlName="state">
</label>
<label>
Zip Code:
<input type="text" formControlName="zip">
</label>
</div>
<!-- #docregion formarrayname -->
<div formArrayName="aliases">
<h3>Aliases</h3> <button (click)="addAlias()">Add Alias</button>
<div *ngFor="let address of aliases.controls; let i=index">
<!-- The repeated alias template -->
<label>
Alias:
<input type="text" [formControlName]="i">
</label>
</div>
</div>
<!-- #enddocregion formarrayname -->
<!-- #docregion submit-button -->
<button type="submit" [disabled]="!profileForm.valid">Submit</button>
<!-- #enddocregion submit-button -->
</form>
<hr>
<!-- #docregion display-value -->
<p>
Form Value: {{ profileForm.value | json }}
</p>
<!-- #enddocregion display-value -->
<!-- #docregion display-status -->
<p>
Form Status: {{ profileForm.status }}
</p>
<!-- #enddocregion display-status -->
<!-- #docregion patch-value -->
<p>
<button (click)="updateProfile()">Update Profile</button>
</p>
<!-- #enddocregion patch-value -->

View File

@ -0,0 +1,73 @@
// #docplaster
// #docregion form-builder
import { Component } from '@angular/core';
// #docregion form-builder-imports
import { FormBuilder } from '@angular/forms';
// #enddocregion form-builder-imports
// #docregion validator-imports
import { Validators } from '@angular/forms';
// #enddocregion validator-imports
// #docregion form-array-imports
import { FormArray } from '@angular/forms';
// #enddocregion form-array-imports
@Component({
selector: 'app-profile-editor',
templateUrl: './profile-editor.component.html',
styleUrls: ['./profile-editor.component.css']
})
export class ProfileEditorComponent {
// #docregion required-validator, aliases
profileForm = this.fb.group({
firstName: ['', Validators.required],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: ['']
}),
// #enddocregion form-builder, required-validator
aliases: this.fb.array([
this.fb.control('')
])
// #docregion form-builder, required-validator
});
// #enddocregion form-builder, required-validator, aliases
// #docregion aliases-getter
get aliases() {
return this.profileForm.get('aliases') as FormArray;
}
// #enddocregion aliases-getter
// #docregion inject-form-builder, form-builder
constructor(private fb: FormBuilder) { }
// #enddocregion inject-form-builder
updateProfile() {
this.profileForm.patchValue({
firstName: 'Nancy',
address: {
street: '123 Drew Street'
}
});
}
// #enddocregion form-builder
// #docregion add-alias
addAlias() {
this.aliases.push(this.fb.control(''));
}
// #enddocregion add-alias
// #docregion on-submit
onSubmit() {
// TODO: Use EventEmitter with form value
console.warn(this.profileForm.value);
}
// #enddocregion on-submit
// #docregion form-builder
}
// #enddocregion form-builder

View File

@ -1,17 +0,0 @@
<!DOCTYPE html>
<!-- #docregion -->
<html lang="en">
<head>
<title>Hero Form</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- #docregion bootstrap -->
<link rel="stylesheet" href="https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css">
</head>
<body>
<app-root></app-root>
</body>
</html>

View File

@ -2,10 +2,9 @@
<!-- #docregion -->
<html lang="en">
<head>
<title>Hero Form</title>
<title>Angular Reactive Forms</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css">
</head>
<body>

View File

@ -2,12 +2,11 @@
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module'; // just the final version
import { DemoModule } from './app/demo.module'; // demo picker
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(DemoModule);
platformBrowserDynamic().bootstrapModule(AppModule);

View File

@ -1 +0,0 @@
@import url('https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css');

View File

@ -3,6 +3,7 @@
"files":[
"!**/*.d.ts",
"!**/*.js",
"!**/*.[0-9].*",
"!src/app/app.component.1.ts",
"!src/app/hero-list.component.1.html",

View File

@ -8,7 +8,7 @@ const nums = of(1, 2, 3, 4, 5);
// Create a function that accepts an Observable.
const squareOddVals = pipe(
filter(n => n % 2),
filter((n: number) => n % 2 !== 0),
map(n => n * n)
);

View File

@ -9,6 +9,6 @@ import { HeroService } from './heroes';
<toh-heroes></toh-heroes>
`,
styleUrls: ['./app.component.css'],
providers: [ HeroService ]
providers: [HeroService]
})
export class AppComponent { }
export class AppComponent {}

View File

@ -1,9 +1,8 @@
// #docregion
/* avoid */
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { Component, NgModule, OnInit } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Component, OnInit } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
class Hero {
id: number;
@ -24,24 +23,24 @@ class AppComponent implements OnInit {
heroes: Hero[] = [];
ngOnInit() {
getHeroes().then(heroes => this.heroes = heroes);
getHeroes().then(heroes => (this.heroes = heroes));
}
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
exports: [ AppComponent ],
bootstrap: [ AppComponent ]
imports: [BrowserModule],
declarations: [AppComponent],
exports: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
export class AppModule {}
platformBrowserDynamic().bootstrapModule(AppModule);
const HEROES: Hero[] = [
{id: 1, name: 'Bombasto'},
{id: 2, name: 'Tornado'},
{id: 3, name: 'Magneta'},
{ id: 1, name: 'Bombasto' },
{ id: 2, name: 'Tornado' },
{ id: 3, name: 'Magneta' }
];
function getHeroes(): Promise<Hero[]> {

View File

@ -2,7 +2,7 @@
import { Hero } from './hero.model';
export const HEROES: Hero[] = [
{id: 1, name: 'Bombasto'},
{id: 2, name: 'Tornado'},
{id: 3, name: 'Magneta'},
{ id: 1, name: 'Bombasto' },
{ id: 2, name: 'Tornado' },
{ id: 3, name: 'Magneta' }
];

View File

@ -1,6 +1,6 @@
// #docregion
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule);

View File

@ -3,9 +3,8 @@
/* avoid */
import { ExceptionService, SpinnerService, ToastService } from '../../core';
import { Http } from '@angular/http';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { map } from 'rxjs/operators';
import { Hero } from './hero.model';
// #enddocregion example
@ -16,18 +15,15 @@ export class HeroService {
private exceptionService: ExceptionService,
private spinnerService: SpinnerService,
private toastService: ToastService,
private http: Http
private http: HttpClient
) { }
getHero(id: number) {
return this.http.get(`api/heroes/${id}`).pipe(
map(response => response.json().data as Hero));
return this.http.get<Hero>(`api/heroes/${id}`);
}
getHeroes() {
return this.http.get(`api/heroes`).pipe(
map(response => response.json().data as Hero[]));
return this.http.get<Hero[]>(`api/heroes`);
}
}

View File

@ -1,11 +1,11 @@
// #docregion
// #docregion example
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { map } from 'rxjs/operators';
import { Hero } from './hero.model';
import { ExceptionService, SpinnerService, ToastService } from '../../core';
import { Hero } from './hero.model';
// #enddocregion example
@Injectable()
@ -16,18 +16,15 @@ export class HeroService {
private exceptionService: ExceptionService,
private spinnerService: SpinnerService,
private toastService: ToastService,
private http: Http
private http: HttpClient
) { }
getHero(id: number) {
return this.http.get(`api/heroes/${id}`).pipe(
map(response => response.json() as Hero));
return this.http.get<Hero>(`api/heroes/${id}`);
}
getHeroes() {
return this.http.get(`api/heroes`).pipe(
map(response => response.json() as Hero[]));
return this.http.get<Hero[]>(`api/heroes`);
}
}

View File

@ -22,7 +22,7 @@ code uses [AnimationBuilder](/api/animations/AnimationBuilder). If your code doe
uncomment the `web-animations-js` polyfill from the `polyfills.ts` file generated by Angular CLI.
</div>
<div class="l-sub-section">
<div class="alert is-helpful">
The examples in this page are available as a <live-example></live-example>.
@ -183,7 +183,7 @@ transition definitions, and not in a separate `state(void)` definition. Thus, th
are different on enter and leave: the element enters from the left
and leaves to the right.
<div class="l-sub-section">
<div class="alert is-helpful">
These two common animations have their own aliases:

View File

@ -4,7 +4,7 @@ The Angular Ahead-of-Time (AOT) compiler converts your Angular HTML and TypeScri
This guide explains how to build with the AOT compiler using different compiler options and how to write Angular metadata that AOT can compile.
<div class="l-sub-section">
<div class="alert is-helpful>
<a href="https://www.youtube.com/watch?v=kW9cJsvcsGo">Watch compiler author Tobias Bosch explain the Angular Compiler</a> at AngularConnect 2016.
@ -39,7 +39,7 @@ For AOT compilation, append the `--aot` flags to the _build-only_ or the _build-
ng serve --aot
</code-example>
<div class="l-sub-section">
<div class="alert is-helpful">
The `--prod` meta-flag compiles with AOT by default.
@ -297,7 +297,7 @@ At the same time, the AOT **_collector_** analyzes the metadata recorded in the
You can think of `.metadata.json` as a diagram of the overall structure of a decorator's metadata, represented as an [abstract syntax tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree).
<div class="l-sub-section">
<div class="alert is-helpful">
Angular's [schema.ts](https://github.com/angular/angular/blob/master/packages/compiler-cli/src/metadata/schema.ts)
describes the JSON format as a collection of TypeScript interfaces.
@ -333,7 +333,7 @@ Parentheses | `(a + b)`
If an expression uses unsupported syntax, the _collector_ writes an error node to the `.metadata.json` file. The compiler later reports the error if it needs that
piece of metadata to generate the application code.
<div class="l-sub-section">
<div class="alert is-helpful">
If you want `ngc` to report syntax errors immediately rather than produce a `.metadata.json` file with errors, set the `strictMetadataEmit` option in `tsconfig`.

View File

@ -11,7 +11,7 @@ A _component_ controls a patch of screen called a *view*. For example, individua
You define a component's application logic&mdash;what it does to support the view&mdash;inside a class.
The class interacts with the view through an API of properties and methods.
For example, the `HeroListComponent` has a `heroes` property that holds an array of heroes. It also has a `selectHero()` method that sets a `selectedHero` property when the user clicks to choose a hero from that list. The component acquires the heroes from a service, which is a TypeScript [parameter property[(http://www.typescriptlang.org/docs/handbook/classes.html#parameter-properties) on the constructor. The service is provided to the component through the dependency injection system.
For example, the `HeroListComponent` has a `heroes` property that holds an array of heroes. It also has a `selectHero()` method that sets a `selectedHero` property when the user clicks to choose a hero from that list. The component acquires the heroes from a service, which is a TypeScript [parameter property](http://www.typescriptlang.org/docs/handbook/classes.html#parameter-properties) on the constructor. The service is provided to the component through the dependency injection system.
<code-example path="architecture/src/app/hero-list.component.ts" linenums="false" title="src/app/hero-list.component.ts (class)" region="class"></code-example>

View File

@ -26,7 +26,7 @@ Here's a simple root NgModule definition:
<code-example path="architecture/src/app/mini-app.ts" region="module" title="src/app/app.module.ts" linenums="false"></code-example>
<div class="l-sub-section">
<div class="alert is-helpful">
The `export` of `AppComponent` is just to show how to export; it isn't actually necessary in this example. A root NgModule has no reason to _export_ anything because other modules don't need to _import_ the root NgModule.
@ -56,7 +56,7 @@ A component and its template together define a _view_. A component can contain a
When you create a component, it is associated directly with a single view, called the _host view_. The host view can be the root of a view hierarchy, which can contain _embedded views_, which are in turn the host views of other components. Those components can be in the same NgModule, or can be imported from other NgModules. Views in the tree can be nested to any depth.
<div class="l-sub-section">
<div class="alert is-helpful">
The hierarchical structure of views is a key factor in the way Angular detects and responds to changes in the DOM and app data.
</div>
@ -72,7 +72,7 @@ Other JavaScript modules use *import statements* to access public objects from o
<code-example path="architecture/src/app/app.module.ts" region="export" linenums="false"></code-example>
<div class="l-sub-section">
<div class="alert is-helpful">
<a href="http://exploringjs.com/es6/ch_modules.html">Learn more about the JavaScript module system on the web.</a>
</div>
@ -99,7 +99,7 @@ In the example of the simple root module above, the application module needs mat
In this way you're using both the Angular and JavaScript module systems _together_. Although it's easy to confuse the two systems, which share the common vocabulary of "imports" and "exports", you will become familiar with the different contexts in which they are used.
<div class="l-sub-section">
<div class="alert is-helpful">
Learn more from the [NgModules](guide/ngmodules) page.

View File

@ -27,7 +27,7 @@ Like JavaScript modules, NgModules can import functionality from other NgModules
Organizing your code into distinct functional modules helps in managing development of complex applications, and in designing for reusability. In addition, this technique lets you take advantage of _lazy-loading_&mdash;that is, loading modules on demand&mdash;in order to minimize the amount of code that needs to be loaded at startup.
<div class="l-sub-section">
<div class="alert is-helpful">
For a more detailed discussion, see [Introduction to modules](guide/architecture-modules).
@ -39,7 +39,7 @@ Every Angular application has at least one component, the *root component* that
The `@Component` decorator identifies the class immediately below it as a component, and provides the template and related component-specific metadata.
<div class="l-sub-section">
<div class="alert is-helpful">
Decorators are functions that modify JavaScript classes. Angular defines a number of such decorators that attach specific kinds of metadata to classes, so that it knows what those classes mean and how they should work.
@ -59,7 +59,7 @@ Before a view is displayed, Angular evaluates the directives and resolves the bi
Your templates can also use *pipes* to improve the user experience by transforming values for display. Use pipes to display, for example, dates and currency values in a way appropriate to the user's locale. Angular provides predefined pipes for common transformations, and you can also define your own.
<div class="l-sub-section">
<div class="alert is-helpful">
For a more detailed discussion of these concepts, see [Introduction to components](guide/architecture-components).
@ -74,7 +74,7 @@ For data or logic that is not associated with a specific view, and that you want
*Dependency injection* (or DI) lets you keep your component classes lean and efficient. They don't fetch data from the server, validate user input, or log directly to the console; they delegate such tasks to services.
<div class="l-sub-section">
<div class="alert is-helpful">
For a more detailed discusssion, see [Introduction to services and DI](guide/architecture-services).
@ -96,7 +96,7 @@ The router interprets a link URL according to your app's view navigation rules a
To define navigation rules, you associate *navigation paths* with your components. A path uses a URL-like syntax that integrates your program data, in much the same way that template syntax integrates your views with your program data. You can then apply program logic to choose which views to show or to hide, in response to user input and your own access rules.
<div class="l-sub-section">
<div class="alert is-helpful">
For a more detailed discussion, see [Routing and navigation](guide/router).
@ -128,7 +128,7 @@ Each of these subjects is introduced in more detail in the following pages.
* [Pipes](guide/architecture-components#pipes)
* [Services and dependency injection](guide/architecture-services)
<div class="l-sub-section">
<div class="alert is-helpful">
Note that the code referenced on these pages is available as a <live-example></live-example>.
</div>

View File

@ -51,7 +51,7 @@ ng generate directive highlight
The CLI creates `src/app/highlight.directive.ts`, a corresponding test file (`.../spec.ts`, and _declares_ the directive class in the root `AppModule`.
<div class="l-sub-section">
<div class="alert is-helpful">
_Directives_ must be declared in [Angular Modules](guide/ngmodules) in the same manner as _components_.
@ -71,7 +71,7 @@ Angular locates each element in the template that has an attribute named `appHig
The _attribute selector_ pattern explains the name of this kind of directive.
<div class="l-sub-section">
<div class="alert is-helpful">
#### Why not "highlight"?
@ -146,7 +146,7 @@ each adorned by the `HostListener` decorator.
The `@HostListener` decorator lets you subscribe to events of the DOM
element that hosts an attribute directive, the `<p>` in this case.
<div class="l-sub-section">
<div class="alert is-helpful">
Of course you could reach into the DOM with standard JavaScript and attach event listeners manually.
There are at least three problems with _that_ approach:

View File

@ -19,7 +19,7 @@ If you use the CLI to generate an app, the default `AppModule` is as follows:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
@ -31,7 +31,7 @@ import { AppComponent } from './app.component';
imports: [
BrowserModule,
FormsModule,
HttpModule
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
@ -138,7 +138,7 @@ It tells Angular about other NgModules that this particular module needs to func
This list of modules are those that export components, directives, or pipes
that the component templates in this module reference. In this case, the component is
`AppComponent`, which references components, directives, or pipes in `BrowserModule`,
`FormsModule`, or `HttpModule`.
`FormsModule`, or `HttpClientModule`.
A component template can reference another component, directive,
or pipe when the referenced class is declared in this module or
the class was imported from another module.

View File

@ -95,7 +95,7 @@ Angular supports most recent browsers. This includes the following specific vers
</table>
<div class="l-sub-section">
<div class="alert is-helpful">
Angular's continuous integration process runs unit tests of the framework on all of these browsers for every pull request,
using <a href="https://saucelabs.com/">SauceLabs</a> and
@ -154,7 +154,7 @@ add it yourself, following the same pattern:
1. install the npm package
1. `import` the file in `polyfills.ts`
<div class="l-sub-section">
<div class="alert is-helpful">
Non-CLI users should follow the instructions [below](#non-cli).
</div>

View File

@ -44,6 +44,9 @@ is available to <code>declarations</code> of this module.</p>
<td><p>List of dependency injection providers visible both to the contents of this module and to importers of this module.</p>
</td>
</tr><tr>
<td><code><b>entryComponents:</b> [SomeComponent, OtherComponent]</code></td>
<td><p>List of components not referenced in any reachable template, for example dynamically created from code.</p></td>
</tr><tr>
<td><code><b>bootstrap:</b> [MyAppComponent]</code></td>
<td><p>List of components to bootstrap when this module is bootstrapped.</p>
</td>

View File

@ -119,7 +119,7 @@ E2E tests of input property setter with empty and non-empty names:
Detect and act upon changes to input property values with the `ngOnChanges()` method of the `OnChanges` lifecycle hook interface.
<div class="l-sub-section">
<div class="alert is-helpful">
@ -311,7 +311,7 @@ The following example illustrates this technique with the same
Neither its appearance nor its behavior will change.
The child [CountdownTimerComponent](guide/component-interaction#countdown-timer-example) is the same as well.
<div class="l-sub-section">
<div class="alert is-helpful">
@ -400,7 +400,7 @@ Each `AstronautComponent` is a child of the `MissionControlComponent` and theref
<div class="l-sub-section">
<div class="alert is-helpful">

View File

@ -187,7 +187,7 @@ They are _not inherited_ by any components nested within the template nor by any
</div>
<div class="l-sub-section">
<div class="alert is-helpful">
You can specify more than one styles file or even a combination of `styles` and `styleUrls`.

View File

@ -25,7 +25,7 @@ application and don't need to be listed in any module.
Service classes can act as their own providers which is why defining them in the `@Injectable` decorator
is all the registration you need.
<div class="l-sub-section">
<div class="alert is-helpful">
@ -167,7 +167,7 @@ that is visible only to the component and its children, if any.
You could also provide the `HeroService` to a *different* component elsewhere in the application.
That would result in a *different* instance of the service, living in a *different* injector.
<div class="l-sub-section">
<div class="alert is-helpful">
@ -433,7 +433,7 @@ It may already have that value in its internal container.
If it doesn't, it may be able to make one with the help of a ***provider***.
A *provider* is a recipe for delivering a service associated with a *token*.
<div class="l-sub-section">
<div class="alert is-helpful">
@ -577,7 +577,7 @@ The second provider substitutes the `DateLoggerService` for the `LoggerService`.
The `LoggerService` is already registered at the `AppComponent` level.
When _this component_ requests the `LoggerService`, it receives the `DateLoggerService` instead.
<div class="l-sub-section">
<div class="alert is-helpful">
@ -645,7 +645,7 @@ The `HeroOfTheMonthComponent` constructor's `logger` parameter is typed as `Mini
Behind the scenes, Angular actually sets the `logger` parameter to the full service registered under the `LoggingService` token which happens to be the `DateLoggerService` that was [provided above](guide/dependency-injection-in-action#useclass).
<div class="l-sub-section">
<div class="alert is-helpful">
@ -707,7 +707,7 @@ After some undisclosed work, the function returns the string of names
and Angular injects it into the `runnersUp` parameter of the `HeroOfTheMonthComponent`.
<div class="l-sub-section">
<div class="alert is-helpful">
@ -769,7 +769,7 @@ A ***class-interface*** should define *only* the members that its consumers are
Such a narrowing interface helps decouple the concrete class from its consumers.
<div class="l-sub-section">
<div class="alert is-helpful">
@ -866,7 +866,7 @@ and displays them in the order they arrive from the database.
<div class="l-sub-section">
<div class="alert is-helpful">
@ -982,7 +982,7 @@ If you're lucky, they all implement the same base class
whose API your `NewsComponent` understands.
<div class="l-sub-section">
<div class="alert is-helpful">
@ -1165,7 +1165,7 @@ its class signature doesn't mention `Parent`:
<div class="l-sub-section">
<div class="alert is-helpful">

View File

@ -81,7 +81,7 @@ now in the constructor.
The `Car` class no longer creates an `engine` or `tires`.
It just consumes them.
<div class="l-sub-section">
<div class="alert is-helpful">
This example leverages TypeScript's constructor syntax for declaring
parameters and properties simultaneously.
@ -101,7 +101,7 @@ conform to the general API requirements of an `engine` or `tires`.
Now, if someone extends the `Engine` class, that is not `Car`'s problem.
<div class="l-sub-section">
<div class="alert is-helpful">
The _consumer_ of `Car` has the problem. The consumer must update the car creation code to
something like this:

View File

@ -98,7 +98,7 @@ Without a provider, the injector would not know
that it is responsible for injecting the service
nor be able to create the service.
<div class="l-sub-section">
<div class="alert is-helpful">
You'll learn much more about _providers_ [below](#providers).
For now, it is sufficient to know that they configure where and how services are created.
@ -141,7 +141,7 @@ The second registers a value (`HERO_DI_CONFIG`) under the `APP_CONFIG` _injectio
With the above registrations, Angular can inject the `UserService` or the `HERO_DI_CONFIG` value
into any class that it creates.
<div class="l-sub-section">
<div class="alert is-helpful">
You'll learn about _injection tokens_ and _provider_ syntax [below](#providers).
</div>
@ -174,7 +174,7 @@ You're likely to inject the `UserService` in many places throughout the app
and will want to inject the same service instance every time.
Providing the `UserService` with an Angular module is a good choice if an `@Injectable` provider is not an option..
<div class="l-sub-section">
<div class="alert is-helpful">
To be precise, Angular module providers are registered with the root injector
_unless the module is_ [lazy loaded](guide/lazy-loading-ngmodules).
@ -199,7 +199,7 @@ and is never destroyed so the `HeroService` created for the `HeroComponent` also
If you want to restrict `HeroService` access to the `HeroComponent` and its nested `HeroListComponent`,
providing the `HeroService` in the `HeroComponent` may be a good choice.
<div class="l-sub-section">
<div class="alert is-helpful">
The scope and lifetime of component-provided services is a consequence of [the way Angular creates component instances](#component-child-injectors).
@ -375,7 +375,7 @@ and let the injector pass them along to the factory function:
<code-example path="dependency-injection/src/app/heroes/hero.service.provider.ts" region="provider" title="src/app/heroes/hero.service.provider.ts (excerpt)" linenums="false">
</code-example>
<div class="l-sub-section">
<div class="alert is-helpful">
The `useFactory` field tells Angular that the provider is a factory function
whose implementation is the `heroServiceFactory`.
@ -440,7 +440,7 @@ The service can be instantiated by configuring a factory function as shown below
<code-example path="dependency-injection/src/app/tree-shaking/service.0.ts" title="src/app/tree-shaking/service.0.ts" linenums="false"> </code-example>
<div class="l-sub-section">
<div class="alert is-helpful">
To override tree-shakable providers, register the provider using the `providers: []` array syntax of any Angular decorator that supports it.
@ -532,7 +532,7 @@ under test:
<code-example path="dependency-injection/src/app/test.component.ts" region="spec" title="src/app/test.component.ts" linenums="false">
</code-example>
<div class="l-sub-section">
<div class="alert is-helpful">
Learn more in the [Testing](guide/testing) guide.
@ -636,7 +636,7 @@ But what should you use as the token?
You don't have a class to serve as a token.
There is no `AppConfig` class.
<div class="l-sub-section">
<div class="alert is-helpful">
### TypeScript interfaces aren't valid tokens
@ -692,7 +692,7 @@ If the factory function needs access to other DI tokens, it can use the inject f
const TOKEN =
new InjectionToken('tree-shakeable token',
{ providedIn: 'root', factory: () =>
new AppConfig(inject(Parameter1), inject(Paremeter2)), });
new AppConfig(inject(Parameter1), inject(Parameter2)), });
</code-example>
{@a optional}
@ -742,7 +742,7 @@ You can call `get()` with a second parameter, which is the value to return if th
is not found. Angular can't find the service if it's not registered with this or any ancestor injector.
<div class="l-sub-section">
<div class="alert is-helpful">
@ -776,7 +776,7 @@ If you define the component before the service,
you'll get a runtime null reference error.
<div class="l-sub-section">
<div class="alert is-helpful">
You actually can define the component first with the help of the `forwardRef()` method as explained
in this [blog post](http://blog.thoughtram.io/angular/2015/09/03/forward-references-in-angular-2.html).

View File

@ -187,7 +187,7 @@ For example, given the `<base href="/my/app/">`, the browser resolves a URL such
into a server request for `my/app/some/place/foo.jpg`.
During navigation, the Angular router uses the _base href_ as the base path to component, template, and module files.
<div class="l-sub-section">
<div class="alert is-helpful">
See also the [*APP_BASE_HREF*](api/common/APP_BASE_HREF "API: APP_BASE_HREF") alternative.
@ -215,7 +215,7 @@ The `ng build` command writes generated build artifacts to the output folder.
The `ng serve` command does not.
It serves build artifacts from memory instead for a faster development experience.
<div class="l-sub-section">
<div class="alert is-helpful">
The output folder is `dist/` by default.
To output to a different folder, change the `outputPath` in `angular.json`.

View File

@ -13,7 +13,7 @@ The final UI looks like this:
<img src="generated/images/guide/displaying-data/final.png" alt="Final UI">
</figure>
<div class="l-sub-section">
<div class="alert is-helpful">
@ -60,7 +60,7 @@ interpolation:
<div class="l-sub-section">
<div class="alert is-helpful">
@ -79,7 +79,7 @@ inserts those values into the browser. Angular updates the display
when these properties change.
<div class="l-sub-section">
<div class="alert is-helpful">
@ -213,7 +213,7 @@ to the item (the hero) in the current iteration. Angular uses that variable as t
context for the interpolation in the double curly braces.
<div class="l-sub-section">
<div class="alert is-helpful">

View File

@ -47,7 +47,7 @@ The reader requests a page by its Page URL. The doc viewer fetches the correspon
Page URLs mirror the `content` file structure. The URL for the page of a guide is in the form `guide/{page-name}`. The page for _this_ "Authors Style Guide" is located at `content/guide/docs-style-guide.md` and its URL is `guide/docs-style-guide`.
<div class="l-sub-section">
<div class="alert is-helpful">
_Tutorial_ pages are exactly like guide pages. The only difference is that they reside in `content/tutorial` instead of `content/guide` and have URLs like `tutorial/{page-name}`.
@ -84,7 +84,7 @@ Standard markdown processors don't allow you to put markdown _within_ HTML tags.
</div>
```
<div class="l-sub-section">
<div class="alert is-helpful">
It is customary but not required to _precede_ the _closing HTML_ tag with a blank line as well.
@ -162,34 +162,6 @@ Try to minimize the heading depth, preferably only two. But more headings, such
Try to minimize ...
```
## Subsections
Subsections typically present extra detail and references to other pages.
Use subsections for commentary that _enriches_ the reader's understanding of the text that precedes it.
A subsection _must not_ contain anything _essential_ to that understanding. Don't put a critical instruction or a tutorial step in a subsection.
A subsection is content within a `<div>` that has the `l-sub-section` CSS class. You should write the subsection content in markdown.
Here is an example of a subsection `<div>` surrounding the subsection content written in markdown.
<div class="l-sub-section">
You'll learn about styles for live examples in the [section below](guide/docs-style-guide#live-examples "Live examples").
</div>
```html
<div class="l-sub-section">
You'll learn about styles for live examples in the [section below](guide/docs-style-guide#live-examples "Live examples").
</div>
```
Note that at least one blank line must follow the opening `<div>`. A blank line before the closing `</div>` is customary but not required.
## Table of contents
Most pages display a table of contents (TOC). The TOC appears in the right panel when the viewport is wide. When narrow, the TOC appears in an expandable/collapsible region near the top of the page.
@ -322,7 +294,7 @@ The author must also write end-to-end tests for the sample.
Code samples are located in sub-folders of the `content/examples` directory of the `angular/angular` repository. An example folder name should be the same as the guide page it supports.
<div class="l-sub-section">
<div class="alert is-helpful">
A guide page might not have its own sample code. It might refer instead to a sample belonging to another page.
@ -355,7 +327,7 @@ In this example, that path is `docs-style-guide/src/app/app.module.ts`.
You added a header to tell the reader where to find the file by setting the `title` attribute.
Following convention, you set the `title` attribute to the file's location within the sample's root folder.
<div class="l-sub-section">
<div class="alert is-helpful">
Unless otherwise noted, all code snippets in this page are derived from sample source code
located in the `content/examples/docs-style-guide` directory.
@ -523,7 +495,7 @@ The `linenums` attribute in the second pane restores line numbering for _itself
You must add special code snippet markup to sample source code files before they can be displayed by `<code-example>` and `<code-tabs>` components.
<div class="l-sub-section">
<div class="alert is-helpful">
The sample source code for this page, located in `context/examples/docs-style-guide`, contains examples of every code snippet markup described in this section.
@ -570,7 +542,7 @@ The `<code-example>` and `<code-tabs>` components won't display a source code fi
The _#docregion_ comment begins a code snippet region.
Every line of code _after_ that comment belongs in the region _until_ the code fragment processor encounters the end of the file or a closing _#enddocregion_.
<div class="l-sub-section">
<div class="alert is-helpful">
The `src/main.ts` is a simple example of a file with a single _#docregion_ at the top of the file.
@ -613,7 +585,7 @@ You can nest _#docregions_ within _#docregions_
... yet more code ...
/// #enddocregion
```
<div class="l-sub-section">
<div class="alert is-helpful">
The `src/app/app.module.ts` file has a good example of a nested region.
@ -726,7 +698,7 @@ By adding `<live-example>` to the page you generate links that run sample code i
Live examples (AKA "stackblitz") are defined by one or more `stackblitz.json` files in the root of a code sample folder. Each sample folder usually has a single unnamed definition file, the default `stackblitz.json`.
<div class="l-sub-section">
<div class="alert is-helpful">
You can create additional, named definition files in the form `name.stackblitz.json`. See `content/examples/testing` for examples.
@ -826,14 +798,14 @@ Here's an embedded live example for this guide.
Every section header tag is also an anchor point. Another guide page could add a link to this section by writing:
<div class="l-sub-section">
<div class="alert is-helpful">
See the ["Anchors"](guide/docs-style-guide#anchors "Style Guide - Anchors") section for details.
</div>
```html
<div class="l-sub-section">
<div class="alert is-helpful">
See the ["Anchors"](guide/docs-style-guide#anchors "Style Guide - Anchors") section for details.
@ -875,7 +847,7 @@ Now [link to that custom anchor name](#ugly-anchors) as you did before.
Now [link to that custom anchor name](#ugly-anchors) as you did before.
```
<div class="l-sub-section">
<div class="alert is-helpful">
Alternatively, you can use the HTML `<a>` tag.
@ -889,44 +861,81 @@ If you do, be sure to set the `id` attribute - not the `name` attribute! The doc
</div>
## Alerts
## Alerts and Calllouts
Alerts draw attention to important points. Alerts should not be used for multi-line content (use callouts insteads) or stacked on top of each other. Note that the content of an alert is indented to the right by two spaces.
Alerts and callouts present warnings, extra detail or references to other pages. They can also be used to provide commentary that _enriches_ the reader's understanding of the content being presented.
An alert or callout _must not_ contain anything _essential_ to that understanding. Don't put a critical instruction or a tutorial step in a subsection.
### Alerts
Alerts draw attention to short important points. Alerts should not be used for multi-line content (use [callouts](#callouts "callouts") instead).
<div class="alert is-helpful">
You'll learn about styles for live examples in the [section below](guide/docs-style-guide#live-examples "Live examples").
</div>
Note that at least one blank line must follow both the opening and closing `<div>` tags. A blank line before the closing `</div>` is customary but not required.
```html
<div class="alert is-helpful">
You'll learn about styles for live examples in the [section below](guide/docs-style-guide#live-examples "Live examples").
</div>
```
There are three different _urgency levels_ used to style the alerts based on the severity or importance of the content.
<div class="alert is-critical">
A critical alert.
</div>
<div class="alert is-important">
An important alert.
</div>
<div class="alert is-helpful">
A helpful, informational alert.
</div>
Here is the markup for these alerts.
```html
<div class="alert is-critical">
A critical alert.
</div>
<div class="alert is-important">
An important alert.
</div>
<div class="alert is-helpful">
A helpful, informational alert.
</div>
```
Alerts are meant to grab the user's attention and should be used sparingly.
They are not for casual asides or commentary. Use [subsections](#subsections "subsections") for commentary.
### Callouts
## Callouts
Callouts, like alerts, are meant to draw attention to important points. Use a callout when you want a riveting header and multi-line content.
Callouts (like alerts) are meant to draw attention to important points. Use a callout when you want a riveting header and multi-line content.
If you have more than two paragraphs, consider creating a new page or making it part of the main content.
Callouts use the same _urgency levels_ that alerts do.
<div class="callout is-critical">
<header>A critical point</header>
@ -943,7 +952,7 @@ Callouts (like alerts) are meant to draw attention to important points. Use a ca
</div>
<div class="callout is-helpful">
<header>A helpful point</header>
<header>A helpful or informational point</header>
**Pitchfork hoodie semiotics**, roof party pop-up _paleo_ messenger bag cred Carles tousled Truffaut yr. Semiotics viral freegan VHS, Shoreditch disrupt McSweeney's. Intelligentsia kale chips Vice four dollar toast, Schlitz crucifix
@ -959,10 +968,10 @@ Here is the markup for the first of these callouts.
</div>
```
Notice that
* the callout header text is forced to all upper case.
* the callout body can be written in markdown.
* a blank line separates the `</header>` tag from the markdown content.
Notice that:
* the callout header text is forced to all upper case
* the callout body can be written in markdown
* a blank line separates the `</header>` tag from the markdown content
Callouts are meant to grab the user's attention. They are not for casual asides. Please use them sparingly.
@ -1254,7 +1263,7 @@ Note that you generally don't wrap a floating image in a `<figure>` element.
If you have a floating image inside an alert, callout, or a subsection, it is a good idea to apply the `clear-fix` class to the `div` to ensure that the image doesn't overflow its container. For example:
<div class="l-sub-section clear-fix">
<div class="alert is-helpful clear-fix">
<img src="generated/images/guide/docs-style-guide/flying-hero.png"
alt="flying Angular hero"
@ -1266,7 +1275,7 @@ If you have a floating image inside an alert, callout, or a subsection, it is a
</div>
```html
<div class="l-sub-section clear-fix">
<div class="alert is-helpful clear-fix">
<img src="generated/images/guide/docs-style-guide/flying-hero.png"
alt="flying Angular hero"

View File

@ -101,7 +101,7 @@ The `loadComponent()` method is doing a lot of the heavy lifting here.
Take it step by step. First, it picks an ad.
<div class="l-sub-section">
<div class="alert is-helpful">

Some files were not shown because too many files have changed in this diff Show More