Compare commits

...

116 Commits

Author SHA1 Message Date
f50affaf9c chore(release): cut 2.0.0-beta.0 - sonambulent-inauguration 2015-12-15 10:54:10 -08:00
463754bf16 docs(changelog): release notes for 2.0.0-beta.0 sonambulent-inauguration 2015-12-15 10:54:10 -08:00
a45b27e7f9 chore(release): cut 2.0.0-alpha.54 2015-12-15 09:57:05 -08:00
af3ea16acb docs(changelog): add release notes for alpha.55 2015-12-15 09:57:05 -08:00
fc75220d63 fix(router): export ROUTER_LINK_DSL_PROVIDER and hide MockPopStateEvent 2015-12-15 09:45:00 -08:00
00822c3415 chore(publish): add Rx bundles to code.angularjs.org publish step
Closes #5904
Closes #5909
2015-12-15 17:12:42 +00:00
3dca9d522a feat(core): enable dev mode by default
BREAKING CHANGE

Before

Previously Angular would run in dev prod mode by default, and you could enable the dev mode by calling enableDevMode.

After

Now, Angular runs in the dev mode by default, and you can enable the prod mode by calling enableProdMode.
2015-12-15 08:34:44 -08:00
de996ec50b build(publish.sh): uncomment prepare steps for existing tmp repo
I tested these steps manually and they seem to work well.
2015-12-15 03:31:47 -08:00
059e09c3be chore(release): cut alpha.54 - rxjs bundle separation 2015-12-15 03:04:28 -08:00
d5e4686e7e docs(changelog): add alpha.54 release notes 2015-12-15 03:04:28 -08:00
d55655f5a3 fix(bundles): rename the testing.js bundle
BREAKING CHANGE:

System.register testing bundle was renamed:
`testing.js` -> `testing.dev.js`

Closes #5899
Closes #5776
2015-12-15 02:52:25 -08:00
61b9468596 fix(bundles): rename UMD bundles
BREAKING CHANGE:

UMD bundles were renamed:
* `angular2.umd.js` -> `angular2-all.umd.js`
* `angular2-testing.umd.js` -> `angular2-all-testing.umd.js`

Closes #5898
2015-12-15 10:24:32 +00:00
c6f52e3282 docs(cheatsheet): fix the ES5 snippets for services 2015-12-15 01:27:19 -08:00
42ccff859c build(gulp): remove obsolete insertRXLicense bundle transform 2015-12-15 01:11:10 -08:00
29600c0c87 docs(bundles): update RxJS info in bundles/overview.md post-#5893 2015-12-15 01:07:16 -08:00
5b63b6764f fix(docs,benchmarks): remove invalid </input> closing tags
Closing #5752
2015-12-15 00:45:31 -08:00
2835265916 docs(cheatsheet) adding JS specific syntax to cheatsheet
Closes #5861
2015-12-14 23:19:12 -08:00
e950dd6a2a refactor(bundles): make rxjs an external dependency in umd bundle
Closes #5886
Closes #5893
2015-12-14 22:08:22 -08:00
321ed7d099 chore(package): update rxjs to beta.0 2015-12-14 22:08:16 -08:00
42b74f524a chore(bundles): use RxJS bundles 2015-12-14 22:08:16 -08:00
77b7caeceb fix(bundles): don't include RxJS in System.register bundles
BREAKING CHANGE:

RxJS used to be bundled with Angular 2 code and this is not the case
any more. RxJS needs to be loaded explicitly.
2015-12-14 22:08:16 -08:00
b803ecf7e7 refactor(testing): reenable injectAsync checking for return value
Before #5375, injectAsync would check the return value and fail
if it was not a promise, to help users remember that they need to
return a promise from an async test. #5375 removed that with the
introduction of the testing zone.

This un-deprecates `injectAsync` until we can resolve
https://github.com/angular/angular/issues/5515.

To be clear, this means that `inject` and `injectAsync` are now
identical except that `injectAsync` will fail if the test
does not return a promise, and `inject` will fail if the test
returns any value.

Closes #5721
2015-12-15 05:51:54 +00:00
d3a79db48d build(publish.sh): do not error when tmp/code.angularjs.org already exists
I'm not sure what's the best way to update the shallow repo and I'm in a state where there is nothing to be
updated so I'll revisit the proper fix the next time I'm doing a release unless someone beats me to it.

Closes #5872
2015-12-15 05:45:10 +00:00
e891baeea4 chore: remove unused decorator
Closes #5880
2015-12-15 05:20:35 +00:00
2aaef81b1b Revert "refactor(testing): move common testing logic into test_injector"
This reverts commit b88a6d983f.
2015-12-14 20:27:31 -08:00
3191fd1440 cleanup(linker): Remove vestigial ComponentUrlMapper.
Closes #5849
2015-12-15 03:04:49 +00:00
80a5e47e61 docs(*): Document a lot more symbols that are missing comments in our generated docs. 2015-12-15 03:04:48 +00:00
5a04ffec3e refactor(Directive): drop moduleId
moduleId is only used by components to resolve urls.
Directives have no templates and do not need moduleId.
Closes #5873
2015-12-15 01:20:56 +00:00
1c779d8b9e docs(bundles): document existing bundles and their usage
Closes #5777

Closes #5878
2015-12-15 01:18:44 +00:00
a79fe057f9 fix(changelog): fix rxjs operator import paths
Closes #5864
2015-12-15 01:15:57 +00:00
b88a6d983f refactor(testing): move common testing logic into test_injector
Before, all test framework wrappers (internal for dart and js/ts,
angular2_test for dart and testing for js/ts) had similar logic to
keep track of current global test injector and test provider list.
This change wraps that logic into one class managed by the test
injector.

Closes #5819
2015-12-15 01:14:48 +00:00
19396d14cc docs(contributing.md): improve submit issue instructions
Closes #5889
2015-12-15 00:45:29 +00:00
2983558e5e fix(bundles): remove polyfills from angular2.js bundle
BREAKING CHANGE:

Previously `angular2.js`, `angular2.min.js` and `angular2.dev.js` bundles
would have zone.js and reflect-metadata pre-appended. New bundles don't
contain zone.js nor reflect-metadata - those external dependencies can
be easily loaded into a browser using `angular2-polyfills.js`

Closes #5881
2015-12-14 21:34:56 +00:00
0f8e40bb42 chore(zone.js) : update to 0.5.10
Closes #5845
2015-12-14 21:23:18 +00:00
006a96dd20 refactor(WebWorker): Make WebWorker bootstrap synchronous
BREAKING CHANGE

From the app thread, in both TypeScript and Dart, you bootstrap the app
using `application` instead of `asyncApplication`.
Before:
```TypeScript
platform([WORKER_APP_PLATFORM])
.asyncApplication(setupWebWorker, optionalProviders?)
.then((ref) => ref.bootstrap(RootComponent));
```
Now:
```TypeScript
platform([WORKER_APP_PLATFORM])
.application([WORKER_APP_APPLICATION])
.bootstrap(RootComponent);
```

closes #5857

Closes #5862
2015-12-14 21:04:46 +00:00
4deaf0bdd3 chore(bundles): align content of System.register and UMD bundles
Closes #5856
2015-12-14 20:48:29 +00:00
9917d7f8af chore(bundles): properly clean the dist/build folder
The `dist/build` folder is created as part of the bundling
process but it was never cleaned up in the `clean` task.

Closes #5832
2015-12-14 20:48:19 +00:00
1607ef8782 refactor(HtmlLexer): process carriage returns in one pass
Closes #5867
2015-12-14 20:17:06 +00:00
539c5633bf chore(bundles): add http and router mocks to angular2-testing
Closes #5830
2015-12-14 19:04:03 +00:00
f83f4ace2d chore(changelog): fix formatting for alpha.53
Closes #5866
2015-12-14 18:34:51 +00:00
283962f810 fix(bundles): remove ngUpgrade from the angular2.js bundle
Closes #5739

BREAKING CHANGE:

`ngUpgrade` related symbols are no longer part of the `angular2.js`
bundle. `ngUpgrade` has a dedicated `upgrade.js` bundle now.

Closes #5854
2015-12-14 17:55:05 +00:00
892f9e19bc chore(release): cut alpha.53 - no more angular2/angular2 2015-12-12 17:59:35 -08:00
cacfb214b6 docs(changelog): changelog for alpha.53 2015-12-12 17:59:35 -08:00
4e5cd1e558 chore: update ts2dart to 0.7.18
Closes #5853
2015-12-12 19:28:13 +00:00
43f42d9c6e feat(facade): do not reexport Observable from angular2/core
BREAKING CHANGE

Before import {Observable} from 'angular2/core'

After import {Observable} from 'rxjs/Observable';
2015-12-12 19:28:13 +00:00
a885f37dfa fix(web_workers): remove unnecessary setup module and AppRootUrl
Since AppRootUrl is removed, the logic for extending and emitting
the root url as part of the setup seems unnecessary.

BREAKING CHANGES:

The setupWebWorker function exported from 
angular2/platform/worker_app  no longer returns a promise of providers, 
but instead synchronously returns providers.

Related to #5815
Closes #5820
2015-12-12 00:58:56 +00:00
ed2c25eb2f fix(compiler): remove AppRootUrl
Related to #5815

This should not break anything because AppRootUrl wasn't actually
being used by the compiler anymore.
2015-12-12 00:58:56 +00:00
b1b0593ddf docs(core): replace angular2/angular2 with the right barrel import.
Related to #5710
Closes #5847
2015-12-11 15:30:25 -08:00
200dc00dbb fix(angular2): remove angular2.ts module
Closes #5815
Closes #5844

BREAKING CHANGE:

`angular2/angular2` was removed. Use the correct import from one of the barrels. E.g. `angular2/core`, `angular2/platform/browser`,  `angular2/common`, …

Note: This only applies to JavaScript, Dart is not changed.
2015-12-11 14:21:33 -08:00
20c6eebb29 fix(angular2): don't export compiler bits as public API
Closes #5815
Closes #5797

BREAKING CHANGE:

The following symbols are not exported from angular2/angular2 any more:
`UrlResolver`, `AppRootUrl`, `getUrlScheme`, `DEFAULT_PACKAGE_URL_PROVIDER`.
Use imports from `angular2/compiler` instead.
2015-12-11 14:04:01 -08:00
8c69497d8e fix(bundles): don't use angular2/angular2 in config of System.register bundles
Related #5710
2015-12-11 14:04:01 -08:00
44c648fc04 Revert "fix(animate): ensure transition properties are removed once the animation is over"
This reverts commit b8e69a21a9.
2015-12-11 13:13:11 -08:00
979162d324 fix(public_spec): check exports of barrels instead of angular2/angular2
This changes the public api spec to check each public barrel individually
to make sure its API has not changed. The previous API spec has been
preserved but split into respective barrels.

The compiler barrel has been added to the spec, along with all of its
public exports. Previously, angular2/angular2 was only exporting a
handful of symbols from compiler, so there are now many more symbols
being tested in the spec for compiler than previously.

Part of #5710
Closes #5841
Supercedes #5821
2015-12-11 13:05:52 -08:00
2934b82113 chore(tools): remove unused performance import
Closes #5840
2015-12-11 20:32:17 +00:00
92ddc62bed fix(styles): Escape \r characters in compiled text
Closes #5772

Closes #5835
2015-12-11 19:48:43 +00:00
0cb32c2fef feat(Headers): implement toJSON 2015-12-11 19:40:56 +00:00
2ca5e38a78 fix(upgrade): allow directives with empty template 2015-12-11 11:39:45 -08:00
b8e69a21a9 fix(animate): ensure transition properties are removed once the animation is over 2015-12-11 11:38:24 -08:00
3fd898e91f docs(cheatsheet): copyedit
Fixed a few little things. I'll probably have more changes to make later, once I understand everything better.

Also added a missing syntax line.

Closes #5806
2015-12-11 18:41:57 +00:00
a66cc50168 refactor(testing): limit imports of barrel-private APIs
Closes #5603
2015-12-11 18:39:56 +00:00
eb296756fb refactor(benchmarks): remove imports from 'angular2/angular2'
Closes #5799
2015-12-11 18:33:03 +00:00
f1a9a537cb test(core): remove imports from 'angular2/angular2'
Closes #5829
2015-12-11 18:02:23 +00:00
080469f8e6 fix(HtmlParser): allow ng-content elements regardless the namespace
relates to #5547
Closes #5745
2015-12-11 01:36:48 +00:00
7c13372721 fix(TemplateParser): match element and attributes regardless the namespace 2015-12-11 01:36:48 +00:00
778677ba75 docs(core): Myriad of documentation changes including lots of new example code. 2015-12-10 15:23:57 -08:00
f0d876a873 chore(tests): disable flaky firefox test
Tracking issue is #5611
Closes #5817
2015-12-10 22:54:26 +00:00
e9e2a4152e docs: fix variable name, change to camelCase
closes #5801
2015-12-10 14:35:28 -08:00
398f024b24 fix(async): support BehaviorSubjects in async pipe 2015-12-10 21:49:40 +00:00
4a17e6906c fix(async): improve Rx support in ObservableWrapper 2015-12-10 21:49:40 +00:00
8d3e5596dc refactor(playground): remove imports from 'angular2/angular2'
Part of #5710

Closes #5798
2015-12-10 21:46:51 +00:00
df6d2d1e23 refactor(examples): remove imports from 'angular2/angular2'
Closes #5803
2015-12-10 21:45:58 +00:00
d26c338aa0 refactor(material): remove imports from 'angular2/angular2'
Closes #5800
2015-12-10 21:19:38 +00:00
edcb34dc9f fix(dom_renderer): moveNodeAfterSiblings should not detach the reference node
Fixes #5077
Closes #5759
2015-12-10 20:14:27 +00:00
693d9dce5d fix(parse5): support comment nodes with getText and setText
In the browser, calling element.textContent causes child comment
nodes to be ignored, while getting textContent directly on a
comment node will return the comment. This change makes
parse5Adapter consistent with this behavior by adding a 2nd
argument to getText telling if it's being called recursively.

Closes #5805
2015-12-10 19:18:14 +00:00
194dc7da78 feat(renderer): use a comment instead of an element when stamping out template>` elements
Originally authored by @tbosch, this reverts the revert commit
e274ff8a69.

Closes #4805
2015-12-10 19:18:14 +00:00
79399e1c51 feat(dom_renderer): add setBindingDebugInfo method
This is used for setting property binding values as attributes
on elements when running in dev mode. This implementation will
also serialize binding information to template placeholder
comment nodes.

Closes #5227
2015-12-10 19:18:14 +00:00
fe1dd77d94 feat(benchpress): add receivedData + requestCount to PerflogMetric
Closes #5750
2015-12-10 18:51:47 +00:00
24dcd267b8 refactor(gulpfile.js): cleanup obsolete file reference
Closes #5738
2015-12-10 18:16:50 +00:00
cf3ce171a5 docs(kebab-case.md): more fixes and CSS migration instructions
Closes #5773
2015-12-10 04:18:17 -08:00
06d076a6f2 docs(kebab-case): fix typo on property
Closes #5783
2015-12-10 03:42:43 -08:00
3190c5941a fix(changelog): fix ngFor on template
Closes #5785
2015-12-10 03:41:00 -08:00
30e25acb9f fix(core): workaround for typescript@1.7.3 breakage #5784
I don't understand why I need to declare the type-here, but it resolves the issue.

Looks like a bug in tsc.

Fixes #5784
2015-12-10 03:30:16 -08:00
4975cb92ae docs(changelog): add link back to A2 package.json
Closes #5779
2015-12-10 02:28:41 -08:00
c8d6ad2718 chore(release): cut alpha.52 - the new beginning 2015-12-10 00:48:32 -08:00
cde6726e25 docs(changelog): add changelog for alpha.52 2015-12-10 00:48:32 -08:00
b3d10af89a docs(kebab-case.md): fix indentation, add links and other small changes 2015-12-10 00:48:32 -08:00
4724cc664e docs(kebab-case.md): add link to the design doc 2015-12-10 00:18:08 -08:00
4e16feaf72 docs(changelog): add breaking change note about peerDependencies
Closes #5747
2015-12-09 22:10:12 -08:00
9e44dd85ad feat(camelCase Angular): legacy template transformer 2015-12-09 19:59:40 -08:00
da9b46a071 feat: camelCase Angular (kebab-case removal)
BREAKING CHANGE:

Angular is now fully camel case.

Before:

    <p *ng-if="cond">
    <my-cmp [my-prop]="exp">
    <my-cmp (my-event)="action()">
    <my-cmp [(my-prop)]="prop">
    <input #my-input>
    <template ng-for #my-item [ng-for-of]=items #my-index="index">

After

    <p *ngIf="cond">
    <my-cmp [myProp]="exp">
    <my-cmp (myEvent)="action()">
    <my-cmp [(myProp)]="prop">
    <input #myInput>`,
    <template ngFor="#my-item" [ngForOf]=items #myIndex="index">

The full details are found in [angular2/docs/migration/kebab-case.md](https://github.com/angular/angular/blob/master/modules/angular2/docs/migration/kebab-case.md)
2015-12-09 19:59:40 -08:00
b386d1134a doc(camelCase Angular): migration guide 2015-12-09 19:59:40 -08:00
1e740581ee build(npm_publish.sh): run gulp via node --max-old-space-size=1900 to workaround #5229 2015-12-09 19:51:10 -08:00
f1741b10f2 docs(changelog): release notes for 2.0.0-alpha.51 2015-12-09 19:28:52 -08:00
7bce1477ef chore(release): cut alpha.52 - the last release of Angular as we know it 2015-12-09 19:20:20 -08:00
01ba94ba56 build(npm): update to ts2dart@0.7.17
resolves regression in 0.7.16

Closes #5758
2015-12-10 01:32:45 +00:00
51cb7586e0 build(npm): update to typescript@1.7.3 + fix broccoli-typescript + fix src 2015-12-10 01:32:44 +00:00
796eee1e6f build(npm): update to gulp-typescript@2.10.0 2015-12-10 01:32:44 +00:00
c39828f0f2 build(npm): bump ts2dart to 0.7.16 2015-12-10 01:32:44 +00:00
28860d35b2 feat(core): provide support for relative assets for components
Assets defined for `templateUrl` and `styleUrls` can now be loaded
in relative to where the component file is placed so long as the
`moduleId` is set within the component annotation.

Closes #5634
2015-12-09 16:28:49 -08:00
5f0ce30ee6 revert: feat(core): provide support for relative assets for components 2015-12-09 16:26:42 -08:00
f4d937ad8d docs(cheatsheet): add Dart-specific syntax & headings
Closes #5756
2015-12-09 23:05:23 +00:00
db096a5e22 feat(core): provide support for relative assets for components
Assets defined for `templateUrl` and `styleUrls` can now be loaded
in relative to where the component file is placed so long as the
`moduleId` is set within the component annotation.

Closes #5634

Closes #5634
2015-12-09 22:04:00 +00:00
bf484b19b3 chore(changelog): fix formatting for alpha.49
Closes #5732
2015-12-09 21:30:30 +00:00
56a254e6a5 chore: enforce import checks for the 'upgrade' barrel
Closes #5741
2015-12-09 21:04:41 +00:00
793098bcce refactor(upgrade): remove imports from angular2/angular2
Related #5739
2015-12-09 21:04:41 +00:00
d6d759d722 feat(bundles): add angular-testing UMD bundle
Closes #5581

Closes #5734
2015-12-09 19:36:18 +00:00
61e8b60506 docs(Observable): add documentation for Observable and operators
Closes #5642
Closes #5684
2015-12-09 19:32:30 +00:00
2f0744b089 docs(cheatsheet): update to new syntax
See https://github.com/angular/angular.io/pull/459

Closes #5733
2015-12-09 19:04:08 +00:00
ca73852746 docs(AngularEntrypoint): add missing backticks 2015-12-09 19:04:08 +00:00
72444c40a7 typo fix: registerPrimaryOutlet description
Closes #5648
2015-12-08 19:55:35 -08:00
214148d58a chore(release): update package.json and changelog to alpha.50 2015-12-08 19:07:43 -08:00
cc8f1f9552 feat(testing): package angular2_testing to prepare it for publishing
Closes #5682
2015-12-09 03:01:21 +00:00
cbf788869d fix(http): use any for res.json() return
fixes #5636

Closes #5646
2015-12-09 03:00:22 +00:00
c1ae49d91e fix(testing): remove Symbol dummy shim
Closes #5067

Closes #5719
2015-12-09 02:57:19 +00:00
4432cf5438 chore(package): update rxjs dependency to alpha.14
Closes #5722

Closes #5723
2015-12-08 18:54:43 -08:00
869a392357 fix(package) add missing comma in ngHttp package.json
Closes #5727
2015-12-08 18:51:19 -08:00
366 changed files with 6030 additions and 2743 deletions

View File

@ -1,3 +1,193 @@
<a name="2.0.0-beta.0"></a>
# 2.0.0-beta.0 sonambulent-inauguration (2015-12-15)
**Enjoy!**
<a name="2.0.0-alpha.55"></a>
# 2.0.0-alpha.55 (2015-12-15)
### Bug Fixes
* **router:** export ROUTER_LINK_DSL_PROVIDER and hide MockPopStateEvent ([fc75220](https://github.com/angular/angular/commit/fc75220))
### Features
* **core:** enable dev mode by default ([3dca9d5](https://github.com/angular/angular/commit/3dca9d5))
### BREAKING CHANGES
* Before
Previously Angular would run in dev prod mode by default, and you could enable the dev mode by calling enableDevMode.
After
Now, Angular runs in the dev mode by default, and you can enable the prod mode by calling enableProdMode.
<a name="2.0.0-alpha.54"></a>
# 2.0.0-alpha.54 (2015-12-15)
### Bug Fixes
* **bundles:** don't include RxJS in System.register bundles ([77b7cae](https://github.com/angular/angular/commit/77b7cae))
* **bundles:** remove ngUpgrade from the angular2.js bundle ([283962f](https://github.com/angular/angular/commit/283962f)), closes [#5739](https://github.com/angular/angular/issues/5739) [#5854](https://github.com/angular/angular/issues/5854)
* **bundles:** remove polyfills from angular2.js bundle ([2983558](https://github.com/angular/angular/commit/2983558)), closes [#5881](https://github.com/angular/angular/issues/5881)
* **bundles:** rename the testing.js bundle to testing.dev.js ([d55655f](https://github.com/angular/angular/commit/d55655f)), closes [#5899](https://github.com/angular/angular/issues/5899) [#5776](https://github.com/angular/angular/issues/5776)
* **bundles:** rename UMD bundles ([61b9468](https://github.com/angular/angular/commit/61b9468)), closes [#5898](https://github.com/angular/angular/issues/5898)
### BREAKING CHANGES
* System.register testing bundle was renamed:
`testing.js` -> `testing.dev.js`
* UMD bundles were renamed:
* `angular2.umd.js` -> `angular2-all.umd.js`
* `angular2-testing.umd.js` -> `angular2-all-testing.umd.js`
* RxJS used to be bundled with Angular 2 code and this is not the case
any more. RxJS needs to be loaded explicitly.
* Previously `angular2.js`, `angular2.min.js` and `angular2.dev.js` bundles
would have zone.js and reflect-metadata pre-appended. New bundles don't
contain zone.js nor reflect-metadata - those external dependencies can
be easily loaded into a browser using `angular2-polyfills.js`
* `ngUpgrade` related symbols are no longer part of the `angular2.js`
bundle. `ngUpgrade` has a dedicated `upgrade.js` bundle now.
<a name="2.0.0-alpha.53"></a>
# 2.0.0-alpha.53 (2015-12-13)
### Bug Fixes
* **angular2:** don't export compiler bits as public API ([20c6eeb](https://github.com/angular/angular/commit/20c6eeb)), closes [#5815](https://github.com/angular/angular/issues/5815) [#5797](https://github.com/angular/angular/issues/5797)
* **angular2:** remove `angular2.ts` module ([200dc00](https://github.com/angular/angular/commit/200dc00)), closes [#5815](https://github.com/angular/angular/issues/5815) [#5844](https://github.com/angular/angular/issues/5844)
* **animate:** ensure transition properties are removed once the animation is over ([b8e69a2](https://github.com/angular/angular/commit/b8e69a2))
* **async:** improve Rx support in ObservableWrapper ([4a17e69](https://github.com/angular/angular/commit/4a17e69))
* **async:** support BehaviorSubjects in async pipe ([398f024](https://github.com/angular/angular/commit/398f024))
* **bundles:** don't use angular2/angular2 in config of System.register bundles ([8c69497](https://github.com/angular/angular/commit/8c69497))
* **changelog:** fix ngFor on template ([3190c59](https://github.com/angular/angular/commit/3190c59)), closes [#5785](https://github.com/angular/angular/issues/5785)
* **compiler:** remove AppRootUrl ([ed2c25e](https://github.com/angular/angular/commit/ed2c25e))
* **core:** workaround for typescript@1.7.3 breakage #5784 ([30e25ac](https://github.com/angular/angular/commit/30e25ac)), closes [#5784](https://github.com/angular/angular/issues/5784)
* **dom_renderer:** moveNodeAfterSiblings should not detach the reference node ([edcb34d](https://github.com/angular/angular/commit/edcb34d)), closes [#5077](https://github.com/angular/angular/issues/5077) [#5759](https://github.com/angular/angular/issues/5759)
* **HtmlParser:** allow ng-content elements regardless the namespace ([080469f](https://github.com/angular/angular/commit/080469f)), closes [#5745](https://github.com/angular/angular/issues/5745)
* **parse5:** support comment nodes with getText and setText ([693d9dc](https://github.com/angular/angular/commit/693d9dc)), closes [#5805](https://github.com/angular/angular/issues/5805)
* **public_spec:** check exports of barrels instead of angular2/angular2 ([979162d](https://github.com/angular/angular/commit/979162d)), closes [#5841](https://github.com/angular/angular/issues/5841)
* **styles:** Escape \r characters in compiled text ([92ddc62](https://github.com/angular/angular/commit/92ddc62)), closes [#5772](https://github.com/angular/angular/issues/5772) [#5835](https://github.com/angular/angular/issues/5835)
* **TemplateParser:** match element and attributes regardless the namespace ([7c13372](https://github.com/angular/angular/commit/7c13372))
* **upgrade:** allow directives with empty template ([2ca5e38](https://github.com/angular/angular/commit/2ca5e38))
* **web_workers:** remove unnecessary setup module and AppRootUrl ([a885f37](https://github.com/angular/angular/commit/a885f37)), closes [#5820](https://github.com/angular/angular/issues/5820)
### Features
* **benchpress:** add receivedData + requestCount to PerflogMetric ([fe1dd77](https://github.com/angular/angular/commit/fe1dd77)), closes [#5750](https://github.com/angular/angular/issues/5750)
* **dom_renderer:** add setBindingDebugInfo method ([79399e1](https://github.com/angular/angular/commit/79399e1)), closes [#5227](https://github.com/angular/angular/issues/5227)
* **facade:** do not reexport Observable from angular2/core ([43f42d9](https://github.com/angular/angular/commit/43f42d9))
* **Headers:** implement `toJSON` ([0cb32c2](https://github.com/angular/angular/commit/0cb32c2))
* **renderer:** use a comment instead of an element when stamping out template>` elements ([194dc7d](https://github.com/angular/angular/commit/194dc7d)), closes [#4805](https://github.com/angular/angular/issues/4805)
### BREAKING CHANGES
* `Observable` are no more re-exported from `angular2/core`
Before
```
import {Observable} from 'angular2/core'
```
After
```
import {Observable} from 'rxjs/Observable';
```
* The setupWebWorker function exported from
angular2/platform/worker_app no longer returns a promise of providers,
but instead synchronously returns providers.
Related to #5815
* `angular2/angular2` was removed. Use the correct import from one of the barrels. E.g. `angular2/core`, `angular2/platform/browser`, `angular2/common`, …
Note: This only applies to JavaScript, Dart is not changed.
* The following symbols are not exported from angular2/angular2 any more:
`UrlResolver`, `AppRootUrl`, `getUrlScheme`, `DEFAULT_PACKAGE_URL_PROVIDER`.
Use imports from `angular2/compiler` instead.
<a name="2.0.0-alpha.52"></a>
# 2.0.0-alpha.52 (2015-12-10)
### Features
* **core:** case-sensitive camelCase templates (kebab-case removal) ([da9b46a](https://github.com/angular/angular/commit/da9b46a))
### BREAKING CHANGES
* Angular templates are now case-sensitive and use camelCase instead of kebab-case (dash-case).
Before:
```
<p *ng-if="cond">
<my-cmp [my-prop]="exp">
<my-cmp (my-event)="action()">
<my-cmp [(my-prop)]="prop">
<input #my-input>
<template ng-for #my-item [ng-for-of]=items #my-index="index">
```
After:
```
<p *ngIf="cond">
<my-cmp [myProp]="exp">
<my-cmp (myEvent)="action()">
<my-cmp [(myProp)]="prop">
<input #myInput>`,
<template ngFor="#myItem" [ngForOf]=items #myIndex="index">
```
The full migration instruction can be found at [angular2/docs/migration/kebab-case.md](https://github.com/angular/angular/blob/master/modules/angular2/docs/migration/kebab-case.md).
<a name="2.0.0-alpha.51"></a>
# 2.0.0-alpha.51 (2015-12-10)
### Features
* **bundles:** add angular2-testing UMD bundle ([d6d759d](https://github.com/angular/angular/commit/d6d759d)), closes [#5581](https://github.com/angular/angular/issues/5581) [#5734](https://github.com/angular/angular/issues/5734)
* **core:** provide support for relative assets for components ([28860d3](https://github.com/angular/angular/commit/28860d3)), closes [#5634](https://github.com/angular/angular/issues/5634)
* **core:** typescript 1.7.3 compatibility ([#5758](https://github.com/angular/angular/pull/5758))
<a name="2.0.0-alpha.50"></a>
# 2.0.0-alpha.50 (2015-12-09)
### Bug Fixes
* **http:** fix syntax error in package.json ([869a392](https://github.com/angular/angular/commit/869a3923574de9ed34b953e84e1744cc007ca629)), closes [#5636](https://github.com/angular/angular/issues/5636) [#5726](https://github.com/angular/angular/issues/5726)
* **http:** use `any` for res.json() return ([cbf7888](https://github.com/angular/angular/commit/cbf7888)), closes [#5636](https://github.com/angular/angular/issues/5636) [#5646](https://github.com/angular/angular/issues/5646)
* **testing:** remove Symbol dummy shim ([c1ae49d](https://github.com/angular/angular/commit/c1ae49d)), closes [#5067](https://github.com/angular/angular/issues/5067) [#5719](https://github.com/angular/angular/issues/5719)
* **package:** update RxJS to alpha.14 ([4432cf5](https://github.com/angular/angular/commit/4432cf5438b8c615d297e8965f0ad69f0188169e)), closes [#5722](https://github.com/angular/angular/issues/5722)
### Features
* **testing:** package angular2_testing to prepare it for publishing ([cc8f1f9](https://github.com/angular/angular/commit/cc8f1f9)), closes [#5682](https://github.com/angular/angular/issues/5682)
<a name="2.0.0-alpha.49"></a>
# 2.0.0-alpha.49 (2015-12-09)
@ -50,11 +240,38 @@ Use `angular-polyfills.js` instead.
- instrumentation is exported as `ng.instrumentation`
- upgrade is exported as `ng.upgrade`
* Before:
<form #f="form">
After:
<form #f="ngForm">
* Form directives are exportedAs 'ngForm' (was 'form')
Before:
```html
<form #f="form">
```
After:
```html
<form #f="ngForm">
```
* rxjs, reflect-metadata, zone.js and es6-shims now must be specified as
explicit dependencies of each angular app that uses npm for package management.
To migrate, please add the following into the "dependencies" section of your package.json:
```
"dependencies": {
...
"es6-promise": "^3.0.2",
"es6-shim": "^0.33.3",
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-alpha.11",
"zone.js": "0.5.8"
...
}
```
or [check angular2's package.json](https://github.com/angular/angular/blob/master/package.json#L34) for the latest peer dependencies
<a name="2.0.0-alpha.48"></a>
# 2.0.0-alpha.48 (2015-12-05)
@ -106,15 +323,15 @@ import * as core from 'angular2/core';
* Operators and Observables from RxJS (e.g. .map(), .toArray(), .toPromise(), etc ) now need to be explicitly imported (once per operator in your app)
```
import {Observable} from 'angular2/angular2'
import 'rxjs/operators/map';
import 'rxjs/observable/interval'
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operators/map';
import 'rxjs/add/observable/interval';
Observable.interval(1000).subscribe(...);
http.get('foos.json').map(res => res.json()).subscribe(...);
```
<a name="2.0.0-alpha.47"></a>
# 2.0.0-alpha.47 (2015-12-01)

View File

@ -48,14 +48,18 @@ features, by not reporting duplicate issues. Providing the following informatio
chances of your issue being dealt with quickly:
* **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps
* **Motivation for or Use Case** - explain why this is a bug for you
* **Angular Version** - what version of Angular is affected (e.g. 2.0.0-alpha.53)
* **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you
* **Browsers and Operating System** - is this a problem with all browsers?
* **Reproduce the Error** - provide a live example (using [Plunker][plunker],
[JSFiddle][jsfiddle] or [Runnable][runnable]) or a unambiguous set of steps.
[JSFiddle][jsfiddle] or [Runnable][runnable]) or a unambiguous set of steps
* **Related Issues** - has a similar issue been reported before?
* **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be
causing the problem (line of code or commit)
You can file new issues by providing the above information [here](https://github.com/angular/angular/issues/new).
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
Before you submit your Pull Request (PR) consider the following guidelines:

View File

@ -137,17 +137,35 @@ var CONFIG = {
dart: 'dist/dart',
docs: 'dist/docs',
docs_angular_io: 'dist/angular.io',
benchpress_bundle: 'dist/build/benchpress_bundle/'
bundles: {all: 'dist/build', benchpress: 'dist/build/benchpress_bundle/'}
}
};
var ANGULAR2_BUNDLE_CONFIG = [
'angular2/common',
'angular2/core',
'angular2/compiler',
'angular2/instrumentation',
'angular2/platform/browser',
'angular2/platform/common_dom'
];
var NG2_BUNDLE_CONTENT = ANGULAR2_BUNDLE_CONFIG.join(' + ') + ' - rxjs/*';
var HTTP_BUNDLE_CONTENT = 'angular2/http - rxjs/* - ' + ANGULAR2_BUNDLE_CONFIG.join(' - ');
var ROUTER_BUNDLE_CONTENT = 'angular2/router + angular2/router/router_link_dsl - rxjs/* - ' +
ANGULAR2_BUNDLE_CONFIG.join(' - ');
var TESTING_BUNDLE_CONTENT =
'angular2/testing + angular2/http/testing + angular2/router/testing - rxjs/* - ' +
ANGULAR2_BUNDLE_CONFIG.join(' - ');
var UPGRADE_BUNDLE_CONTENT = 'angular2/upgrade - rxjs/* - ' + ANGULAR2_BUNDLE_CONFIG.join(' - ');
var BENCHPRESS_BUNDLE_CONFIG = {
entries: ['./dist/js/cjs/benchpress/index.js'],
packageJson: './dist/js/cjs/benchpress/package.json',
includes: ['angular2'],
excludes: ['reflect-metadata', 'selenium-webdriver', 'zone.js'],
ignore: [],
dest: CONFIG.dest.benchpress_bundle
dest: CONFIG.dest.bundles.benchpress
};
// ------------
@ -164,8 +182,10 @@ gulp.task('build/clean.docs', function(done) { del(CONFIG.dest.docs, done); });
gulp.task('build/clean.docs_angular_io',
function(done) { del(CONFIG.dest.docs_angular_io, done); });
gulp.task('build/clean.benchpress.bundle',
function(done) { del(CONFIG.dest.benchpress_bundle, done); });
gulp.task('build/clean.bundles', function(done) { del(CONFIG.dest.bundles.all, done); });
gulp.task('build/clean.bundles.benchpress',
function(done) { del(CONFIG.dest.bundles.benchpress, done); });
// ------------
// transpile
@ -791,7 +811,7 @@ gulp.task('test.transpiler.unittest',
// Make a temporary directory and symlink dartium from there (just for this command)
// so that it can run.
var dartiumTmpdir = path.join(os.tmpdir(), 'dartium' + new Date().getTime().toString());
gulp.task('test.dart.angular2_testing/ci', ['!pubget.angular2_testing.dart'], function(done) {
gulp.task('test.dart.angular2_testing/ci', ['build/pubspec.dart'], function(done) {
runSequence('test.dart.angular2_testing_symlink', 'test.dart.angular2_testing',
sequenceComplete(done));
});
@ -802,11 +822,8 @@ gulp.task(
gulp.task('test.dart.angular2_testing',
shell.task(['PATH=$PATH:' + dartiumTmpdir + ' pub run test -p dartium'],
{'cwd': 'modules_dart/angular2_testing'}));
{'cwd': 'dist/dart/angular2_testing'}));
gulp.task(
'!pubget.angular2_testing.dart',
pubget.dir(gulp, gulpPlugins, {dir: 'modules_dart/angular2_testing', command: DART_SDK.PUB}));
// -----------------
// Pre-test checks
@ -865,18 +882,42 @@ gulp.task('test.typings',
// unmodified and directory structure is preserved.
//
// This task is expected to be run after build/tree.dart
gulp.task('build/pure-packages.dart', function() {
var yaml = require('js-yaml');
return gulp.src([
'modules_dart/transform/**/*',
'!modules_dart/transform/**/*.proto',
'!modules_dart/transform/pubspec.yaml',
'!modules_dart/transform/**/packages{,/**}',
])
.pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2')));
gulp.task('build/pure-packages.dart', function(done) {
runSequence('build/pure-packages.dart/standalone', 'build/pure-packages.dart/license',
'build/pure-packages.dart/angular2', sequenceComplete(done));
});
gulp.task('build/pure-packages.dart/standalone', function() {
return gulp.src([
'modules_dart/**/*',
'!modules_dart/**/*.proto',
'!modules_dart/**/packages{,/**}',
'!modules_dart/payload{,/**}',
'!modules_dart/transform{,/**}',
])
.pipe(gulp.dest(CONFIG.dest.dart));
});
gulp.task('build/pure-packages.dart/license',
function() {
return gulp.src(['LICENSE'])
.pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2_testing')));
})
gulp.task('build/pure-packages.dart/angular2', function() {
var yaml = require('js-yaml');
return gulp.src([
'modules_dart/transform/**/*',
'!modules_dart/transform/**/*.proto',
'!modules_dart/transform/pubspec.yaml',
'!modules_dart/transform/**/packages{,/**}',
])
.pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2')));
});
// Builds all Dart packages, but does not compile them
gulp.task('build/packages.dart', function(done) {
runSequence('lint_protos.dart', 'build/tree.dart', 'build/pure-packages.dart',
@ -994,13 +1035,13 @@ gulp.task('!bundle.js.prod', ['build.js.prod'], function() {
var bundler = require('./tools/build/bundle');
var bundlerConfig = {sourceMaps: true};
return bundler.bundle(bundleConfig, 'angular2/angular2', './dist/build/angular2.js',
bundlerConfig)
return bundler.bundle(bundleConfig, NG2_BUNDLE_CONTENT, './dist/build/angular2.js', bundlerConfig)
.then(function() {
return Promise.all([
bundler.bundle(bundleConfig, 'angular2/http - angular2/core', './dist/build/http.js',
bundler.bundle(bundleConfig, HTTP_BUNDLE_CONTENT, './dist/build/http.js', bundlerConfig),
bundler.bundle(bundleConfig, ROUTER_BUNDLE_CONTENT, './dist/build/router.js',
bundlerConfig),
bundler.bundle(bundleConfig, 'angular2/router - angular2/core', './dist/build/router.js',
bundler.bundle(bundleConfig, UPGRADE_BUNDLE_CONTENT, './dist/build/upgrade.js',
bundlerConfig)
]);
});
@ -1011,14 +1052,16 @@ gulp.task('!bundle.js.min', ['build.js.prod'], function() {
var bundler = require('./tools/build/bundle');
var bundlerConfig = {sourceMaps: true, minify: true};
return bundler.bundle(bundleConfig, 'angular2/angular2', './dist/build/angular2.min.js',
return bundler.bundle(bundleConfig, NG2_BUNDLE_CONTENT, './dist/build/angular2.min.js',
bundlerConfig)
.then(function() {
return Promise.all([
bundler.bundle(bundleConfig, 'angular2/http - angular2/core', './dist/build/http.min.js',
bundler.bundle(bundleConfig, HTTP_BUNDLE_CONTENT, './dist/build/http.min.js',
bundlerConfig),
bundler.bundle(bundleConfig, 'angular2/router - angular2/core',
'./dist/build/router.min.js', bundlerConfig)
bundler.bundle(bundleConfig, ROUTER_BUNDLE_CONTENT, './dist/build/router.min.js',
bundlerConfig),
bundler.bundle(bundleConfig, UPGRADE_BUNDLE_CONTENT, './dist/build/upgrade.min.js',
bundlerConfig)
]);
});
});
@ -1031,14 +1074,16 @@ gulp.task('!bundle.js.dev', ['build.js.dev'], function() {
var devBundleConfig = merge(true, bundleConfig);
devBundleConfig.paths = merge(true, devBundleConfig.paths, {"*": "dist/js/dev/es5/*.js"});
return bundler.bundle(devBundleConfig, 'angular2/angular2', './dist/build/angular2.dev.js',
return bundler.bundle(devBundleConfig, NG2_BUNDLE_CONTENT, './dist/build/angular2.dev.js',
bundlerConfig)
.then(function() {
return Promise.all([
bundler.bundle(devBundleConfig, 'angular2/http - angular2/core',
'./dist/build/http.dev.js', bundlerConfig),
bundler.bundle(bundleConfig, 'angular2/router - angular2/core',
'./dist/build/router.dev.js', bundlerConfig)
bundler.bundle(devBundleConfig, HTTP_BUNDLE_CONTENT, './dist/build/http.dev.js',
bundlerConfig),
bundler.bundle(devBundleConfig, ROUTER_BUNDLE_CONTENT, './dist/build/router.dev.js',
bundlerConfig),
bundler.bundle(devBundleConfig, UPGRADE_BUNDLE_CONTENT, './dist/build/upgrade.dev.js',
bundlerConfig)
]);
});
});
@ -1064,8 +1109,12 @@ gulp.task('!bundle.testing', ['build.js.dev'], function() {
var devBundleConfig = merge(true, bundleConfig);
devBundleConfig.paths = merge(true, devBundleConfig.paths, {"*": "dist/js/dev/es5/*.js"});
return bundler.bundle(devBundleConfig, 'angular2/testing - angular2/angular2',
'./dist/js/bundle/testing.js', {sourceMaps: true});
return bundler.bundle(devBundleConfig, TESTING_BUNDLE_CONTENT, './dist/js/bundle/testing.dev.js',
{sourceMaps: true});
});
gulp.task('!bundles.js.docs', function() {
gulp.src('modules/angular2/docs/bundles/*').pipe(gulp.dest('dist/js/bundle'));
});
gulp.task('!bundles.js.umd', ['build.js.dev'], function() {
@ -1094,13 +1143,45 @@ gulp.task('!bundles.js.umd', ['build.js.dev'], function() {
resolve: resolveOptions(devOrProd),
module: {preLoaders: [{test: /\.js$/, loader: 'source-map-loader'}]},
devtool: devOrProd === 'dev' ? 'inline-source-map' : undefined,
output: outputOptions(outFileName, devOrProd)
output: outputOptions(outFileName, devOrProd),
externals: {
'rxjs/Observable': 'umd Rx',
'rxjs/Subject': 'umd Rx',
'rxjs/subject/ReplaySubject': {
commonjs: 'rxjs/subject/ReplaySubject',
commonjs2: 'rxjs/subject/ReplaySubject',
amd: 'rxjs/subject/ReplaySubject',
root: ['Rx']
},
'rxjs/operator/take': {
commonjs: 'rxjs/operator/take',
commonjs2: 'rxjs/operator/take',
amd: 'rxjs/operator/take',
root: ['Rx', 'Observable', 'prototype']
},
'rxjs/observable/fromPromise': {
commonjs: 'rxjs/observable/fromPromise',
commonjs2: 'rxjs/observable/fromPromise',
amd: 'rxjs/observable/fromPromise',
root: ['Rx', 'Observable']
},
'rxjs/operator/toPromise': {
commonjs: 'rxjs/operator/toPromise',
commonjs2: 'rxjs/operator/toPromise',
amd: 'rxjs/operator/toPromise',
root: ['Rx', 'Observable', 'prototype']
}
}
};
}
return q.all([
webpack(webPackConf([__dirname + '/tools/build/webpack/angular2.umd.js'], 'angular2', 'dev')),
webpack(webPackConf([__dirname + '/tools/build/webpack/angular2.umd.js'], 'angular2', 'prod'))
webpack(webPackConf([__dirname + '/tools/build/webpack/angular2-all.umd.js'], 'angular2-all',
'dev')),
webpack(webPackConf([__dirname + '/tools/build/webpack/angular2-all.umd.js'], 'angular2-all',
'prod')),
webpack(webPackConf([__dirname + '/tools/build/webpack/angular2-all-testing.umd.js'],
'angular2-all-testing', 'dev'))
]);
});
@ -1109,11 +1190,7 @@ gulp.task('bundles.js.umd.min', ['!bundles.js.umd', '!bundle.ng.polyfills'], fun
var uglify = require('gulp-uglify');
// minify production bundles
return gulp.src([
'dist/js/bundle/angular2-polyfills.js',
'dist/js/bundle/angular2.umd.js',
'dist/js/bundle/angular2_all.umd.js'
])
return gulp.src(['dist/js/bundle/angular2-polyfills.js', 'dist/js/bundle/angular2-all.umd.js'])
.pipe(uglify())
.pipe(rename({extname: '.min.js'}))
.pipe(gulp.dest('dist/js/bundle'));
@ -1122,9 +1199,10 @@ gulp.task('bundles.js.umd.min', ['!bundles.js.umd', '!bundle.ng.polyfills'], fun
gulp.task('!bundle.js.prod.deps', ['!bundle.js.prod'], function() {
var bundler = require('./tools/build/bundle');
return merge2(addDevDependencies('angular2.js'),
return merge2(bundler.modify(['dist/build/angular2.js'], 'angular2.js'),
bundler.modify(['dist/build/http.js'], 'http.js'),
bundler.modify(['dist/build/router.js'], 'router.js'))
bundler.modify(['dist/build/router.js'], 'router.js'),
bundler.modify(['dist/build/upgrade.js'], 'upgrade.js'))
.pipe(gulp.dest('dist/js/bundle'));
});
@ -1132,9 +1210,10 @@ gulp.task('!bundle.js.min.deps', ['!bundle.js.min'], function() {
var bundler = require('./tools/build/bundle');
var uglify = require('gulp-uglify');
return merge2(addDevDependencies('angular2.min.js'),
return merge2(bundler.modify(['dist/build/angular2.min.js'], 'angular2.min.js'),
bundler.modify(['dist/build/http.min.js'], 'http.min.js'),
bundler.modify(['dist/build/router.min.js'], 'router.min.js'))
bundler.modify(['dist/build/router.min.js'], 'router.min.js'),
bundler.modify(['dist/build/upgrade.min.js'], 'upgrade.min.js'))
.pipe(uglify())
.pipe(gulp.dest('dist/js/bundle'));
});
@ -1150,40 +1229,30 @@ var JS_DEV_DEPS = [
'node_modules/reflect-metadata/Reflect.js'
];
// Splice in RX license if rx is in the bundle.
function insertRXLicense(source) {
var n = source.indexOf('System.register("rxjs/Subject"');
if (n >= 0) {
// TODO: point this to Rx once Rx includes license in dist
// https://github.com/angular/angular/issues/5558
var rxLicense = licenseWrap('LICENSE');
return source.slice(0, n) + rxLicense + source.slice(n);
} else {
return source;
}
}
function addDevDependencies(outputFile) {
var bundler = require('./tools/build/bundle');
var insert = require('gulp-insert');
return bundler.modify(JS_DEV_DEPS.concat(['dist/build/' + outputFile]), outputFile)
.pipe(insert.transform(insertRXLicense))
.pipe(gulp.dest('dist/js/bundle'));
}
gulp.task('!bundle.js.dev.deps', ['!bundle.js.dev'], function() {
var bundler = require('./tools/build/bundle');
return merge2(addDevDependencies('angular2.dev.js'),
return merge2(bundler.modify(['dist/build/angular2.dev.js'], 'angular2.dev.js'),
bundler.modify(['dist/build/http.dev.js'], 'http.dev.js'),
bundler.modify(['dist/build/router.dev.js'], 'router.dev.js'))
bundler.modify(['dist/build/router.dev.js'], 'router.dev.js'),
bundler.modify(['dist/build/upgrade.dev.js'], 'upgrade.dev.js'))
.pipe(gulp.dest('dist/js/bundle'));
});
gulp.task('!bundle.web_worker.js.dev.deps', ['!bundle.web_worker.js.dev'], function() {
return merge2(
addDevDependencies("web_worker/ui.dev.js", addDevDependencies("web_worker/worker.dev.js")));
var bundler = require('./tools/build/bundle');
return merge2(bundler.modify(['dist/build/web_worker/ui.dev.js'], "web_worker/ui.dev.js"),
bundler.modify(['dist/build/web_worker/worker.dev.js'], "web_worker/worker.dev.js"))
.pipe(gulp.dest('dist/js/bundle'));
});
gulp.task('!bundle.copy', function() {
@ -1204,7 +1273,8 @@ gulp.task('bundles.js',
'!bundle.web_worker.js.dev.deps',
'bundles.js.umd.min',
'!bundle.testing',
'!bundle.ng.polyfills'
'!bundle.ng.polyfills',
'!bundles.js.docs'
],
function(done) { runSequence('!bundle.copy', '!bundles.js.checksize', done); });
@ -1216,7 +1286,7 @@ gulp.task('clean', [
'build/clean.js',
'build/clean.dart',
'build/clean.docs',
'build/clean.benchpress.bundle'
'build/clean.bundles'
]);
gulp.task('build', ['build.js', 'build.dart']);
@ -1307,7 +1377,7 @@ gulp.task('build.dart.material', ['build/packages.dart'], function(done) {
gulp.task('cleanup.builder', function() { return angularBuilder.cleanup(); });
gulp.task('benchpress.bundle', ['build/clean.benchpress.bundle', 'build.js.cjs'], function(cb) {
gulp.task('benchpress.bundle', ['build/clean.bundles.benchpress', 'build.js.cjs'], function(cb) {
var bundler = require('./tools/build/bundle');
bundler.benchpressBundle(BENCHPRESS_BUNDLE_CONFIG.entries, BENCHPRESS_BUNDLE_CONFIG.packageJson,

View File

@ -16,4 +16,3 @@ export 'package:angular2/src/platform/dom/dom_tokens.dart';
export 'package:angular2/src/platform/dom/dom_adapter.dart';
export 'package:angular2/src/platform/dom/events/event_manager.dart';
export 'package:angular2/src/compiler/url_resolver.dart';
export 'package:angular2/src/compiler/app_root_url.dart';

View File

@ -1,8 +0,0 @@
export * from './common';
export * from './core';
export * from './instrumentation';
export * from './platform/browser';
export * from './src/platform/dom/dom_adapter';
export * from './src/platform/dom/events/event_manager';
export * from './upgrade';
export {UrlResolver, AppRootUrl} from './compiler';

View File

@ -5,5 +5,4 @@
*/
export * from './src/compiler/url_resolver';
export * from './src/compiler/xhr';
export * from './src/compiler/compiler';
export * from './src/compiler/app_root_url';
export * from './src/compiler/compiler';

View File

@ -0,0 +1,26 @@
library angular2.core;
export './src/core/metadata.dart';
export './src/core/util.dart';
export 'package:angular2/src/facade/lang.dart' show enableProdMode;
export './src/core/di.dart' hide ForwardRefFn, resolveForwardRef, forwardRef;
export './src/facade/facade.dart';
export './src/core/application_ref.dart' show platform, createNgZone, PlatformRef, ApplicationRef;
export './src/core/application_tokens.dart' show APP_ID,
APP_COMPONENT,
APP_INITIALIZER,
PACKAGE_ROOT_URL,
PLATFORM_INITIALIZER;
export './src/core/zone.dart';
export './src/core/render.dart';
export './src/core/linker.dart';
export './src/core/debug/debug_element.dart' show DebugElement,
Scope,
inspectElement,
asNativeElements;
export './src/core/testability/testability.dart';
export './src/core/change_detection.dart';
export './src/core/platform_directives_and_pipes.dart';
export './src/core/platform_common_providers.dart';
export './src/core/application_common_providers.dart';
export './src/core/reflection/reflection.dart';

View File

@ -5,14 +5,16 @@
*/
export * from './src/core/metadata';
export * from './src/core/util';
export * from './src/core/dev_mode';
export * from './src/core/prod_mode';
export * from './src/core/di';
export * from './src/facade/facade';
export {enableProdMode} from 'angular2/src/facade/lang';
export {platform, createNgZone, PlatformRef, ApplicationRef} from './src/core/application_ref';
export {
APP_ID,
APP_COMPONENT,
APP_INITIALIZER,
PACKAGE_ROOT_URL,
PLATFORM_INITIALIZER
} from './src/core/application_tokens';
export * from './src/core/zone';
@ -29,4 +31,4 @@ export * from './src/core/change_detection';
export * from './src/core/platform_directives_and_pipes';
export * from './src/core/platform_common_providers';
export * from './src/core/application_common_providers';
export * from './src/core/reflection/reflection';
export * from './src/core/reflection/reflection';

View File

@ -0,0 +1,92 @@
# TL;DR;
* If you write ES5 use _one_ of the `UMD` bundles.
* If you experiment with Angular2 using online prototyping tools like [plnkr](http://plnkr.co/) or similar use `System.register` bundles with SystemJS loader.
* If you use build tools like Browserify or WebPack - bundle Angular2 as part of your build.
* For all the above cases you must use `angular2-polyfills.js` in a `script` tag to easily include polyfills and external dependencies.
# Modules, barrels and bundles
Angular2 source code is authored using the ES2015 standardized module format where one module corresponds to exactly one file. Multiple modules (files) can be logically grouped into so-called "barrels".
A bundle is a file the contains all the code for one or more barrels.
Most bundles come in several flavors:
* regular and minified (got `.min` in their name);
* regular and "development" (have `.dev` in their name) - "development" bundles contain in-line source maps and don't have minified flavor (minification removes in-lined source maps).
# Bundles, their content and usage scenarios
Angular 2 distributes several types of bundles targeted at specific usages:
* users writing ES5 code without any transpilation steps
* users experimenting with Angular 2 and TypeScript/ES2015 using online tools like plunker, jsbin or similar
Since each identified scenario has slightly different requirements and constraints there are specific bundles for each use-case.
## ES5 and ngUpgrade users
ES5 users and AngularJS 1.x users interested in the `ngUpgrade` path can take advantage of the bundles in the [UMD format](https://github.com/umdjs/umd).
Those are coarse-grained bundles that combine many barrels in one final file.
filename | list of barrels | dev/prod | minified?
------------|-------------------|----------|-------------|--------------|-------------
`angular2-all.umd.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade`| prod | no
`angular2-all.umd.min.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade` | prod | yes
`angular2-all.umd.dev.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade` | dev | no
`angular2-all-testing.umd.dev.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade`, `angular2/testing`, `angular2/http/testing`, `angular2/router/testing` | dev | no
**Warning**: bundles in the `UMD` format are _not_ "additive". A single application should use only one bundle from the above list.
## SystemJS loader users
[SystemJS loader](https://github.com/systemjs/systemjs) with on-the-fly (in a browser) transpilations support is very useful for quick experiments using tools like plunker, jsbin or similar.
For this scenario Angular 2 is distributed with bundles in the [System.register format](https://github.com/ModuleLoader/es6-module-loader/wiki/System.register-Explained):
filename | list of barrels | dev/prod | minified?
------------|-------------------|----------|-------------|--------------|-------------
`angular2.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/instrumentation`| prod | no
`angular2.min.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/instrumentation`| prod | yes
`angular2.dev.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/instrumentation`| dev | no
`http.js` | `angular2/http` | prod | no
`http.min.js` | `angular2/http` | prod | yes
`http.dev.js` | `angular2/http` | dev | no
`router.js` | `angular2/router` | prod | no
`router.min.js` | `angular2/router` | prod | yes
`router.dev.js` | `angular2/router` | dev | no
`upgrade.js` | `angular2/upgrade` | prod | no
`upgrade.min.js` | `angular2/upgrade` | prod | yes
`upgrade.dev.js` | `angular2/upgrade` | dev | no
`testing.dev.js` | `angular2/testing`, `angular2/http/testing`, `angular2/router/testing` | dev | no
**Note**: bundles in the `System.register` format are "additive" - it is quite common to include several bundles in one application.
For example people using Angular 2 with `http` and `router` would include: `angular2.js`, `http.js` and `router.js`.
## Browserify / JSPM / Rollup / WebPack users
Angular 2 doesn't provide any bundles for use with packaging tools Browserify or WebPack. Those tools are sophisticated enough to build optimal bundles for production use from individual Angular 2 files distributed in the npm package.
An example of an Angular 2 project built with WebPack can be found in the [angular2-seed](https://github.com/angular/angular2-seed) repository.
# Polyfills and external dependencies
## Required Polyfills
Polyfills are required for Angular 2 to function properly (the exact list depends on the browser used) and external dependencies ([zone.js](https://github.com/angular/zone.js)).
To ease setup of Angular 2 applications there is one file - `angular2-polyfills.js` - that combines:
* a pollyfill mandatory for all browsers: [reflect-metadata](https://www.npmjs.com/package/reflect-metadata)
* [zone.js](https://github.com/angular/zone.js)
**Note**: `angular2-polyfills.js` contains code that should be loaded into the browser as the very first code of the web application even before the module loader. The preferred solution is to load the mentioned file in a `script` tag as early as possible.
## RxJS
[RxJS](https://github.com/ReactiveX/RxJS) is a required dependency of Angular 2.
You should include RxJS in your project by declaring a dependency on the [`rxjs` npm package](https://www.npmjs.com/package/rxjs).
Depending on if you are using Angular bundles or not you can either use RxJS bundles from `node_modules/rxjs/bundles/` or configure your bundler to pull in the individual files from the npm package.
## ES6 shims (optional)
Users of pre-ES6 browsers might need to add an ES6 shim (e.g. [es6-shim](https://github.com/paulmillr/es6-shim))

View File

@ -2,8 +2,17 @@
Bootstrapping
@cheatsheetIndex 0
@description
`import {bootstrap} from 'angular2/angular2';`
{@target ts}`import {bootstrap} from 'angular2/angular2';`{@endtarget}
{@target js}Available from the `ng.platform.browser` namespace.{@endtarget}
{@target dart}`import 'package:angular2/bootstrap.dart';`{@endtarget}
@cheatsheetItem
`bootstrap(MyAppComponent, [MyService, provide(...)]);`
Bootstraps an application with MyAppComponent as the root component and configures the DI providers.
syntax(ts dart):
`bootstrap(MyAppComponent, [MyService, provide(...)]);`|`provide`
syntax(js):
`document.addEventListener('DOMContentLoaded', function () {
ng.platform.browser.bootstrap(MyAppComponent,
[MyService, ng.core.provide(...)]);
});`|`provide`
description:
Bootstraps an application with MyAppComponent as the root component and configures the DI providers. {@target js}Must be wrapped in the event listener to fire when the page loads.{@endtarget}

View File

@ -2,24 +2,34 @@
Built-in directives
@cheatsheetIndex 2
@description
`import {NgIf, ...} from 'angular2/angular2';`
{@target ts}`import {NgIf, ...} from 'angular2/common';`{@endtarget}
{@target js}Available from the `ng.common` namespace{@endtarget}
{@target dart}`import 'package:angular2/common.dart';`{@endtarget}
@cheatsheetItem
`<section *ng-if="showSection">`|`*ng-if`
syntax:
`<section *ngIf="showSection">`|`*ngIf`
description:
Removes or recreates a portion of the DOM tree based on the showSection expression.
@cheatsheetItem
`<li *ng-for="#item of list">`|`*ng-for`
syntax:
`<li *ngFor="#item of list">`|`*ngFor`
description:
Turns the li element and its contents into a template, and uses that to instantiate a view for each item in list.
@cheatsheetItem
`<div [ng-switch]="conditionExpression">
<template [ng-switch-when]="case1Exp">...</template>
<template ng-switch-when="case2LiteralString">...</template>
<template ng-switch-default>...</template>
</div>`|`[ng-switch]`|`[ng-switch-when]`|`ng-switch-when`|`ng-switch-default`
syntax:
`<div [ngSwitch]="conditionExpression">
<template [ngSwitchWhen]="case1Exp">...</template>
<template ngSwitchWhen="case2LiteralString">...</template>
<template ngSwitchDefault>...</template>
</div>`|`[ngSwitch]`|`[ngSwitchWhen]`|`ngSwitchWhen`|`ngSwitchDefault`
description:
Conditionally swaps the contents of the div by selecting one of the embedded templates based on the current value of conditionExpression.
@cheatsheetItem
`<div [ng-class]="{active: isActive, disabled: isDisabled}">`|`[ng-class]`
Binds the presence of css classes on the element to the truthiness of the associated map values. The right-hand side expression should return {class-name: true/false} map.
syntax:
`<div [ngClass]="{active: isActive, disabled: isDisabled}">`|`[ngClass]`
description:
Binds the presence of CSS classes on the element to the truthiness of the associated map values. The right-hand side expression should return {class-name: true/false} map.

View File

@ -2,20 +2,47 @@
Class decorators
@cheatsheetIndex 4
@description
`import {Directive, ...} from 'angular2/angular2';`
{@target ts}`import {Directive, ...} from 'angular2/core';`{@endtarget}
{@target js}Available from the `ng.core` namespace{@endtarget}
{@target dart}`import 'package:angular2/core.dart';`{@endtarget}
@cheatsheetItem
syntax(ts):
`@Component({...})
class MyComponent() {}`|`@Component({...})`
syntax(js):
`var MyComponent = ng.core.Component({...}).Class({...})`|`ng.core.Component({...})`
syntax(dart):
`@Component(...)
class MyComponent() {}`|`@Component(...)`
description:
Declares that a class is a component and provides metadata about the component.
@cheatsheetItem
syntax(ts):
`@Pipe({...})
class MyPipe() {}`|`@Pipe({...})`
syntax(js):
`var MyPipe = ng.core.Pipe({...}).Class({...})`|`ng.core.Pipe({...})`
syntax(dart):
`@Pipe(...)
class MyPipe() {}`|`@Pipe(...)`
description:
Declares that a class is a pipe and provides metadata about the pipe.
@cheatsheetItem
syntax(ts):
`@Injectable()
class MyService() {}`|`@Injectable()`
Declares that a class has dependencies that should be injected into the constructor when the dependency
injector is creating an instance of this class.
syntax(js):
`var OtherService = ng.core.Class({constructor: function() { }});
var MyService = ng.core.Class({constructor: [OtherService, function(otherService) { }]});`|`var MyService = ng.core.Class({constructor: [OtherService, function(otherService) { }]});`
syntax(dart):
`@Injectable()
class MyService() {}`|`@Injectable()`
description:
{@target ts dart}Declares that a class has dependencies that should be injected into the constructor when the dependency injector is creating an instance of this class.
{@endtarget}
{@target js}
Declares a service to inject into a class by providing an array with the services with the final item being the function which will receive the injected services.
{@endtarget}

View File

@ -2,31 +2,45 @@
Component configuration
@cheatsheetIndex 6
@description
`@Component` extends `@Directive`,
so the `@Directive` configuration applies to components as well
{@target js}`ng.core.Component` extends `ng.core.Directive`,
so the `ng.core.Directive` configuration applies to components as well{@endtarget}
{@target ts dart}`@Component` extends `@Directive`,
so the `@Directive` configuration applies to components as well{@endtarget}
@cheatsheetItem
syntax(ts dart):
`viewProviders: [MyService, provide(...)]`|`viewProviders:`
syntax(js):
`viewProviders: [MyService, ng.core.provide(...)]`|`viewProviders:`
description:
Array of dependency injection providers scoped to this component's view.
@cheatsheetItem
syntax:
`template: 'Hello {{name}}'
templateUrl: 'my-component.html'`|`template:`|`templateUrl:`
Inline template / external template url of the component's view.
description:
Inline template / external template URL of the component's view.
@cheatsheetItem
syntax:
`styles: ['.primary {color: red}']
styleUrls: ['my-component.css']`|`styles:`|`styleUrls:`
List of inline css styles / external stylesheet urls for styling components view.
description:
List of inline CSS styles / external stylesheet URLs for styling components view.
@cheatsheetItem
syntax:
`directives: [MyDirective, MyComponent]`|`directives:`
description:
List of directives used in the the components template.
@cheatsheetItem
syntax:
`pipes: [MyPipe, OtherPipe]`|`pipes:`
List of pipes used in the component's template.
description:
List of pipes used in the component's template.

View File

@ -2,19 +2,32 @@
Dependency injection configuration
@cheatsheetIndex 9
@description
`import {provide} from 'angular2/angular2';`
{@target ts}`import {provide} from 'angular2/core';`{@endtarget}
{@target js}Available from the `ng.core` namespace{@endtarget}
{@target dart}`import 'package:angular2/core.dart';`{@endtarget}
@cheatsheetItem
`provide(MyService, {useClass: MyMockService})``provide`|`useClass`
syntax(ts dart):
`provide(MyService, {useClass: MyMockService})`|`provide`|`useClass`
syntax(js):
`ng.core.provide(MyService, {useClass: MyMockService})`|`provide`|`useClass`
description:
Sets or overrides the provider for MyService to the MyMockService class.
@cheatsheetItem
`provide(MyService, {useFactory: myFactory})``provide`|`useFactory`
syntax(ts dart):
`provide(MyService, {useFactory: myFactory})`|`provide`|`useFactory`
syntax(js):
`ng.core.provide(MyService, {useFactory: myFactory})`|`provide`|`useFactory`
description:
Sets or overrides the provider for MyService to the myFactory factory function.
@cheatsheetItem
`provide(MyValue, {useValue: 41})``provide`|`useValue`
syntax(ts dart):
`provide(MyValue, {useValue: 41})`|`provide`|`useValue`
syntax(js):
`provide(MyValue, {useValue: 41})`|`provide`|`useValue`
description:
Sets or overrides the provider for MyValue to the value 41.

View File

@ -2,45 +2,79 @@
Class field decorators for directives and components
@cheatsheetIndex 7
@description
`import {Input, ...} from 'angular2/angular2';`
{@target ts}`import {Input, ...} from 'angular2/core';`{@endtarget}
{@target js}Available from the `ng.core` namespace{@endtarget}
{@target dart}`import 'package:angular2/core.dart';`{@endtarget}
@cheatsheetItem
syntax(ts dart):
`@Input() myProperty;`|`@Input()`
Declares an input property that we can update via property binding, e.g.
`<my-cmp [my-property]="someExpression">`
syntax(js):
`ng.core.Input(myProperty, myComponent);`|`ng.core.Input(`|`);`
description:
Declares an input property that we can update via property binding (e.g.
`<my-cmp [my-property]="someExpression">`).
@cheatsheetItem
syntax(ts dart):
`@Output() myEvent = new EventEmitter();`|`@Output()`
Declares an output property that fires events to which we can subscribe with an event binding, e.g. `<my-cmp (my-event)="doSomething()">`
syntax(js):
`myEvent = new ng.core.EventEmitter(); ng.core.Output(myEvent, myComponent);`|`ng.core.Output(`|`);`
description:
Declares an output property that fires events to which we can subscribe with an event binding (e.g. `<my-cmp (my-event)="doSomething()">`).
@cheatsheetItem
syntax(ts dart):
`@HostBinding('[class.valid]') isValid;`|`@HostBinding('[class.valid]')`
Binds a host element property (e.g. css class valid) to directive/component property (e.g. isValid)
syntax(js):
`ng.core.HostBinding('[class.valid]', 'isValid', myComponent);`|`ng.core.HostBinding('[class.valid]', 'isValid'`|`);`
description:
Binds a host element property (e.g. CSS class valid) to directive/component property (e.g. isValid).
@cheatsheetItem
syntax(ts dart):
`@HostListener('click', ['$event']) onClick(e) {...}`|`@HostListener('click', ['$event'])`
Subscribes to a host element event (e.g. click) with a directive/component method (e.g., onClick), optionally passing an argument ($event)
syntax(js):
`ng.core.HostListener('click', ['$event'], onClick(e) {...}, myComponent);`|`ng.core.HostListener('click', ['$event'], onClick(e)`|`);`
description:
Subscribes to a host element event (e.g. click) with a directive/component method (e.g. onClick), optionally passing an argument ($event).
@cheatsheetItem
syntax(ts dart):
`@ContentChild(myPredicate) myChildComponent;`|`@ContentChild(myPredicate)`
syntax(js):
`ng.core.ContentChild(myPredicate, 'myChildComponent', myComponent);`|`ng.core.ContentChild(myPredicate,`|`);`
description:
Binds the first result of the component content query (myPredicate) to the myChildComponent property of the class.
@cheatsheetItem
syntax(ts dart):
`@ContentChildren(myPredicate) myChildComponents;`|`@ContentChildren(myPredicate)`
syntax(js):
`ng.core.ContentChildren(myPredicate, 'myChildComponents', myComponent);`|`ng.core.ContentChildren(myPredicate,`|`);`
description:
Binds the results of the component content query (myPredicate) to the myChildComponents property of the class.
@cheatsheetItem
syntax(ts dart):
`@ViewChild(myPredicate) myChildComponent;`|`@ViewChild(myPredicate)`
syntax(js):
`ng.core.ViewChild(myPredicate, 'myChildComponent', myComponent);`|`ng.core.ViewChild(myPredicate,`|`);`
description:
Binds the first result of the component view query (myPredicate) to the myChildComponent property of the class. Not available for directives.
@cheatsheetItem
syntax(ts dart):
`@ViewChildren(myPredicate) myChildComponents;`|`@ViewChildren(myPredicate)`
Binds the results of the component view query (myPredicate) to the myChildComponents property of the class. Not available for directives.
syntax(js):
`ng.core.ViewChildren(myPredicate, 'myChildComponents', myComponent);`|`ng.core.ViewChildren(myPredicate,`|`);`
description:
Binds the results of the component view query (myPredicate) to the myChildComponents property of the class. Not available for directives.

View File

@ -2,15 +2,23 @@
Directive configuration
@cheatsheetIndex 5
@description
`@Directive({ property1: value1, ... }) )`
{@target ts}`@Directive({ property1: value1, ... })`{@endtarget}
{@target js}`ng.core.Directive({ property1: value1, ... }).Class({...})`{@endtarget}
{@target dart}`@Directive(property1: value1, ...)`{@endtarget}
@cheatsheetItem
syntax:
`selector: '.cool-button:not(a)'`|`selector:`
Specifies a css selector that identifies this directive within a template. Supported selectors include: `element`,
description:
Specifies a CSS selector that identifies this directive within a template. Supported selectors include `element`,
`[attribute]`, `.class`, and `:not()`.
Does not support parent-child relationship selectors.
@cheatsheetItem
syntax(ts dart):
`providers: [MyService, provide(...)]`|`providers:`
Array of dependency injection providers for this directive and its children.
syntax(js):
`providers: [MyService, ng.core.provide(...)]`|`providers:`
description:
Array of dependency injection providers for this directive and its children.

View File

@ -2,8 +2,12 @@
Forms
@cheatsheetIndex 3
@description
`import {FORM_DIRECTIVES} from 'angular2/angular2';`
{@target ts}`import {FORM_DIRECTIVES} from 'angular2/common';`{@endtarget}
{@target js}Available from `ng.common.FORM_DIRECTIVES`{@endtarget}
{@target dart}`import 'package:angular2/common.dart';`{@endtarget}
@cheatsheetItem
`<input [(ng-model)]="userName">`|`[(ng-model)]`
Provides two-way data-binding, parsing and validation for form controls.
syntax:
`<input [(ngModel)]="userName">`|`[(ngModel)]`
description:
Provides two-way data-binding, parsing and validation for form controls.

View File

@ -2,48 +2,87 @@
Directive and component change detection and lifecycle hooks
@cheatsheetIndex 8
@description
(implemented as class methods)
{@target ts dart}(implemented as class methods){@endtarget}
{@target js}(implemented as component properties){@endtarget}
@cheatsheetItem
syntax(ts):
`constructor(myService: MyService, ...) { ... }`|`constructor(myService: MyService, ...)`
syntax(js):
`constructor: function(MyService, ...) { ... }`|`constructor: function(MyService, ...)`
syntax(dart):
`MyAppComponent(MyService myService, ...) { ... }`|`MyAppComponent(MyService myService, ...)`
description:
The class constructor is called before any other lifecycle hook. Use it to inject dependencies, but avoid any serious work here.
@cheatsheetItem
syntax(ts dart):
`ngOnChanges(changeRecord) { ... }`|`ngOnChanges(changeRecord)`
syntax(js):
`ngOnChanges: function(changeRecord) { ... }`|`ngOnChanges: function(changeRecord)`
description:
Called after every change to input properties and before processing content or child views.
@cheatsheetItem
syntax(ts dart):
`ngOnInit() { ... }`|`ngOnInit()`
syntax(js):
`ngOnInit: function() { ... }`|`ngOnInit: function()`
description:
Called after the constructor, initializing input properties, and the first call to ngOnChanges.
@cheatsheetItem
syntax(ts dart):
`ngDoCheck() { ... }`|`ngDoCheck()`
syntax(js):
`ngDoCheck: function() { ... }`|`ngDoCheck: function()`
description:
Called every time that the input properties of a component or a directive are checked. Use it to extend change detection by performing a custom check.
@cheatsheetItem
syntax(ts dart):
`ngAfterContentInit() { ... }`|`ngAfterContentInit()`
syntax(js):
`ngAfterContentInit: function() { ... }`|`ngAfterContentInit: function()`
description:
Called after ngOnInit when the component's or directive's content has been initialized.
@cheatsheetItem
syntax(ts dart):
`ngAfterContentChecked() { ... }`|`ngAfterContentChecked()`
syntax(js):
`ngAfterContentChecked: function() { ... }`|`ngAfterContentChecked: function()`
description:
Called after every check of the component's or directive's content.
@cheatsheetItem
syntax(ts dart):
`ngAfterViewInit() { ... }`|`ngAfterViewInit()`
syntax(js):
`ngAfterViewInit: function() { ... }`|`ngAfterViewInit: function()`
description:
Called after ngAfterContentInit when the component's view has been initialized. Applies to components only.
@cheatsheetItem
syntax(ts dart):
`ngAfterViewChecked() { ... }`|`ngAfterViewChecked()`
syntax(js):
`ngAfterViewChecked: function() { ... }`|`ngAfterViewChecked: function()`
description:
Called after every check of the component's view. Applies to components only.
@cheatsheetItem
syntax(ts dart):
`ngOnDestroy() { ... }`|`ngOnDestroy()`
Called once, before the instance is destroyed.
syntax(js):
`ngOnDestroy: function() { ... }`|`ngOnDestroy: function()`
description:
Called once, before the instance is destroyed.

View File

@ -2,54 +2,100 @@
Routing and navigation
@cheatsheetIndex 10
@description
`import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, ...} from 'angular2/router';`
{@target ts}`import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, ...} from 'angular2/router';`{@endtarget}
{@target js}Available from the `ng.router` namespace{@endtarget}
{@target dart}`import 'package:angular2/router.dart';`{@endtarget}
@cheatsheetItem
syntax(ts):
`@RouteConfig([
{ path: '/:myParam', component: MyComponent, as: 'MyCmp' },
{ path: '/staticPath', component: ..., as: ...},
{ path: '/*wildCardParam', component: ..., as: ...}
])
class MyComponent() {}`|`@RouteConfig`
Configures routes for the decorated component. Supports static, parameterized and wildcard routes.
syntax(js):
`var MyComponent = ng.router.RouteConfig([
{ path: '/:myParam', component: MyComponent, as: 'MyCmp' },
{ path: '/staticPath', component: ..., as: ...},
{ path: '/*wildCardParam', component: ..., as: ...}
]).Class({
constructor: function() {}
});`|`ng.router.RouteConfig`
syntax(dart):
`@RouteConfig(const [
const Route(path: '/:myParam', component: MyComponent, name: 'MyCmp' ),
])`|`@RouteConfig`
description:
Configures routes for the decorated component. Supports static, parameterized, and wildcard routes.
@cheatsheetItem
syntax:
`<router-outlet></router-outlet>`|`router-outlet`
description:
Marks the location to load the component of the active route.
@cheatsheetItem
`<a [router-link]="[ '/MyCmp', {myParam: 'value' } ]">`|`[router-link]`
syntax:
`<a [routerLink]="[ '/MyCmp', {myParam: 'value' } ]">`|`[routerLink]`
description:
Creates a link to a different view based on a route instruction consisting of a route name and optional parameters. The route name matches the as property of a configured route. Add the '/' prefix to navigate to a root route; add the './' prefix for a child route.
@cheatsheetItem
syntax(ts):
`@CanActivate(() => { ... })class MyComponent() {}`|`@CanActivate`
A component decorator defining a function that the router should call first to determine if it should activate this component. Should return a boolean or a promise.
syntax(js):
`var MyComponent = ng.router.CanActivate(function() { ... }).Component({...}).Class({constructor: ...});`|`ng.router.CanActivate(function() { ... })`
syntax(dart):
`@CanActivate(() => ...)class MyComponent() {}`|`@CanActivate`
description:
A component decorator defining a function that the router should call first to determine if it should activate this component. Should return a boolean or a {@target js ts}promise{@endtarget}{@target dart}future{@endtarget}.
@cheatsheetItem
syntax(ts dart):
`routerOnActivate(nextInstruction, prevInstruction) { ... }`|`routerOnActivate`
After navigating to a component, the router calls component's routerOnActivate method (if defined).
syntax(js):
`routerOnActivate: function(nextInstruction, prevInstruction) { ... }`|`routerOnActivate`
description:
After navigating to a component, the router calls the component's routerOnActivate method (if defined).
@cheatsheetItem
syntax(ts dart):
`routerCanReuse(nextInstruction, prevInstruction) { ... }`|`routerCanReuse`
The router calls a component's routerCanReuse method (if defined) to determine whether to reuse the instance or destroy it and create a new instance. Should return a boolean or a promise.
syntax(js):
`routerCanReuse: function(nextInstruction, prevInstruction) { ... }`|`routerCanReuse`
description:
The router calls a component's routerCanReuse method (if defined) to determine whether to reuse the instance or destroy it and create a new instance. Should return a boolean or a {@target js ts}promise{@endtarget}{@target dart}future{@endtarget}.
@cheatsheetItem
syntax(ts dart):
`routerOnReuse(nextInstruction, prevInstruction) { ... }`|`routerOnReuse`
syntax(js):
`routerOnReuse: function(nextInstruction, prevInstruction) { ... }`|`routerOnReuse`
description:
The router calls the component's routerOnReuse method (if defined) when it re-uses a component instance.
@cheatsheetItem
syntax(ts dart):
`routerCanDeactivate(nextInstruction, prevInstruction) { ... }`|`routerCanDeactivate`
The router calls the routerCanDeactivate methods (if defined) of every component that would be removed after a navigation. The navigation proceeds if and only if all such methods return true or a promise that is resolved.
syntax(js):
`routerCanDeactivate: function(nextInstruction, prevInstruction) { ... }`|`routerCanDeactivate`
description:
The router calls the routerCanDeactivate methods (if defined) of every component that would be removed after a navigation. The navigation proceeds if and only if all such methods return true or a {@target js ts}promise that is resolved{@endtarget}{@target dart}future that completes successfully{@endtarget}.
@cheatsheetItem
syntax(ts dart):
`routerOnDeactivate(nextInstruction, prevInstruction) { ... }`|`routerOnDeactivate`
Called before the directive is removed as the result of a route change. May return a promise that pauses removing the directive until the promise resolves.
syntax(js):
`routerOnDeactivate: function(nextInstruction, prevInstruction) { ... }`|`routerOnDeactivate`
description:
Called before the directive is removed as the result of a route change. May return a {@target js ts}promise{@endtarget}{@target dart}future{@endtarget} that pauses removing the directive until the {@target js ts}promise resolves{@endtarget}{@target dart}future completes{@endtarget}.

View File

@ -4,53 +4,77 @@ Template syntax
@description
@cheatsheetItem
syntax:
`<input [value]="firstName">`|`[value]`
description:
Binds property `value` to the result of expression `firstName`.
@cheatsheetItem
syntax:
`<div [attr.role]="myAriaRole">`|`[attr.role]`
description:
Binds attribute `role` to the result of expression `myAriaRole`.
@cheatsheetItem
syntax:
`<div [class.extra-sparkle]="isDelightful">`|`[class.extra-sparkle]`
Binds the presence of the css class `extra-sparkle` on the element to the truthiness of the expression `isDelightful`.
description:
Binds the presence of the CSS class `extra-sparkle` on the element to the truthiness of the expression `isDelightful`.
@cheatsheetItem
syntax:
`<div [style.width.px]="mySize">`|`[style.width.px]`
description:
Binds style property `width` to the result of expression `mySize` in pixels. Units are optional.
@cheatsheetItem
syntax:
`<button (click)="readRainbow($event)">`|`(click)`
description:
Calls method `readRainbow` when a click event is triggered on this button element (or its children) and passes in the event object.
@cheatsheetItem
syntax:
`<div title="Hello {{ponyName}}">`|`{{ponyName}}`
description:
Binds a property to an interpolated string, e.g. "Hello Seabiscuit". Equivalent to:
`<div [title]="'Hello' + ponyName">`
@cheatsheetItem
syntax:
`<p>Hello {{ponyName}}</p>`|`{{ponyName}}`
description:
Binds text content to an interpolated string, e.g. "Hello Seabiscuit".
@cheatsheetItem
syntax:
`<my-cmp [(title)]="name">`|`[(title)]`
Sets up two-way data binding. Equivalent to: `<my-cmp [title]="name" (title-change)="name=$event">`
description:
Sets up two-way data binding. Equivalent to: `<my-cmp [title]="name" (titleChange)="name=$event">`
@cheatsheetItem
syntax:
`<video #movieplayer ...>
<button (click)="movieplayer.play()">
</video>`|`#movieplayer`|`(click)`
description:
Creates a local variable `movieplayer` that provides access to the `video` element instance in data-binding and event-binding expressions in the current template.
@cheatsheetItem
syntax:
`<p *my-unless="myExpression">...</p>`|`*my-unless`
description:
The `*` symbol means that the current element will be turned into an embedded template. Equivalent to:
`<template [myless]="myExpression"><p>...</p></template>`
@cheatsheetItem
syntax:
`<p>Card No.: {{cardNumber | myCreditCardNumberFormatter}}</p>`|`{{cardNumber | myCreditCardNumberFormatter}}`
description:
Transforms the current value of expression `cardNumber` via the pipe called `creditCardNumberFormatter`.
@cheatsheetItem
syntax:
`<p>Employer: {{employer?.companyName}}</p>`|`{{employer?.companyName}}`
description:
The Elvis operator (`?`) means that the `employer` field is optional and if `undefined`, the rest of the expression should be ignored.

View File

@ -359,20 +359,20 @@ Example of conditionally included template:
```
Hello {{user}}!
<div template="ng-if: isAdministrator">
<div template="ngIf: isAdministrator">
...administrator menu here...
</div>
```
In the above example the `ng-if` directive determines whether the child view (an instance of the child template) should be
inserted into the root view. The `ng-if` makes this decision based on if the `isAdministrator` binding is true.
In the above example the `ngIf` directive determines whether the child view (an instance of the child template) should be
inserted into the root view. The `ngIf` makes this decision based on if the `isAdministrator` binding is true.
The above example is in the short form, for better clarity let's rewrite it in the canonical form, which is functionally
identical.
```
Hello {{user}}!
<template [ng-if]="isAdministrator">
<template [ngIf]="isAdministrator">
<div>
...administrator menu here...
</div>
@ -383,22 +383,22 @@ Hello {{user}}!
### Template Microsyntax
Often times it is necessary to encode a lot of different bindings into a template to control how the instantiation
of the templates occurs. One such example is `ng-for`.
of the templates occurs. One such example is `ngFor`.
```
<form #foo=form>
</form>
<ul>
<template [ng-for] #person [ng-for-of]="people" #i="index">
<template [ngFor] #person [ngForOf]="people" #i="index">
<li>{{i}}. {{person}}<li>
</template>
</ul>
```
Where:
* `[ng-for]` triggers the for directive.
* `#person` exports the implicit `ng-for` item.
* `[ng-for-of]="people"` binds an iterable object to the `ng-for` controller.
* `[ngFor]` triggers the for directive.
* `#person` exports the implicit `ngFor` item.
* `[ngForOf]="people"` binds an iterable object to the `ngFor` controller.
* `#i=index` exports item index as `i`.
The above example is explicit but quite wordy. For this reason in most situations a short hand version of the
@ -406,7 +406,7 @@ syntax is preferable.
```
<ul>
<li template="ng-for; #person; of=people; #i=index;">{{i}}. {{person}}<li>
<li template="ngFor; #person; of=people; #i=index;">{{i}}. {{person}}<li>
</ul>
```
@ -416,24 +416,24 @@ which allows us to further shorten the text.
```
<ul>
<li template="ng-for #person of people #i=index">{{i}}. {{person}}<li>
<li template="ngFor #person of people #i=index">{{i}}. {{person}}<li>
</ul>
```
We can also optionally use `var` instead of `#` and add `:` to `for` which creates the following recommended
microsyntax for `ng-for`.
microsyntax for `ngFor`.
```
<ul>
<li template="ng-for: var person of people; var i=index">{{i}}. {{person}}<li>
<li template="ngFor: var person of people; var i=index">{{i}}. {{person}}<li>
</ul>
```
Finally, we can move the `ng-for` keyword to the left hand side and prefix it with `*` as so:
Finally, we can move the `ngFor` keyword to the left hand side and prefix it with `*` as so:
```
<ul>
<li *ng-for="var person of people; var i=index">{{i}}. {{person}}<li>
<li *ngFor="var person of people; var i=index">{{i}}. {{person}}<li>
</ul>
```
@ -544,7 +544,7 @@ Angular are:
<div title="{{expression}}">{{expression}}</div>
<div [title]="expression">...</div>
<div bind-title="expression">...</div>
<div template="ng-if: expression">...</div>
<div template="ngIf: expression">...</div>
```
Expressions are simplified version of expression in the language in which you are writing your application. (i.e.

View File

@ -161,7 +161,7 @@ Example of usage:
## Directives that use a ViewContainer
Directives that use a ViewContainer can control instantiation of child views which are then inserted into the DOM. (Examples are `ng-if` and `ng-for`.)
Directives that use a ViewContainer can control instantiation of child views which are then inserted into the DOM. (Examples are `ngIf` and `ngFor`.)
* Every `template` element creates a `ProtoView` which can be used to create Views via the ViewContainer.
* The child views show up as siblings of the directive in the DOM.

View File

@ -94,7 +94,7 @@ Let's start with a View such as:
```
<ul>
<li template="ng-for: #person of people">{{person}}</li>
<li template="ngFor: #person of people">{{person}}</li>
</ul>
```

View File

@ -0,0 +1,239 @@
Angular2 templates are now case-sensitive and use camelCase in many places where dash-case was previously used ([design doc] (https://docs.google.com/document/d/1UMxTIUBTIUZNfOqwMhkLg0ANFSBtLIK9JsIu77EZaBA/edit?ts=564f7dd4)).
## Overview
Where you used to write:
```
<my-cmp (some-event)="someAction()" [some-property]="expression" #some-var>
```
in order to:
- bind to the `someEvent` event,
- bind to the `someProperty` property,
- create a `someVar` local variable
You should now write:
```
<my-cmp (someEvent)="someAction()" [someProperty]="expression" #someVar>
```
Notes:
- while tag name are case sensitive, the best practice is to use dash case for component elements so that the browser
interpret them as custom elements,
- `(some-event)` would now bind to the `some-event` event (i.e. there is no implicit dash to camel case conversion),
- `[some-property]` would now bind to the `some-property` property (i.e. there is no implicit dash to camel case conversion),
- `#some-var` is not allowed any more ("-" can not be used in variable names).
## Migration
#### Templates
1. Directives selectors, property bindings, event bindings, template variables and template element attributes should be changed to camel case:
Examples:
- `<p *ng-if="cond">` should be changed to `<p *ngIf="cond">`,
- `<my-cmp [my-prop]="exp">` should be changed to `<my-cmp [myProp]="exp">`,
- `<my-cmp (my-event)="action()">` should be changed to `<my-cmp (myEvent)="action()">`,
- `<my-cmp [(my-prop)]="prop">` should be changed to `<my-cmp [(myProp)]="prop">`,
- `<input #my-input>` should be changed to `<input #myInput>`,
- `<template ng-for #my-item [ng-for-of]=items #my-index="index">` should be changed to `<template ngFor #myItem [ngForOf]=items #myIndex="index">`,
Note: while the tag names are now case-sensitive the best practice is to keep them lower-dash-cased so that the browser
treat them as custom elements. Using dashes in custom element names is required by the [Custom Element HTML Spec](http://www.w3.org/TR/custom-elements/#concepts).
This explains why the `<router-outlet>` component is left unchanged.
`on-`, `bindon-`, `bind-` and `var-` prefixes are still part of the canonical syntax and should remain unchanged (lower cased):
- `on-some-event` should be changed to `on-someEvent`,
- `bind-my-prop` should be changed to `bind-myProp`,
- `bindon-my-prop` should be changed to `bindon-myProp`,
- `var-my-var` should be changed to `var-myVar`.
2. Update variable binding
- `<p #var1="a-b" var-var2="c-d">` should be changed to `<p #var1="aB" var-var2="cD">`
3. The `template` attribute values should also be updated in the same way
`<p template="ng-for #my-item of items #my-index = index">` should be changed to `<p template="ngFor #myItem of items #myIndex = index">`.
Note that both angular directives and your own directives must be updated in the same way.
#### Directives and Components
Take the following steps to upgrade your directives and components:
1. Update the selector:
```
@Directive({selector: 'tag[attr][name=value]'})
@Component({selector: 'tag[attr][name=value]'})
```
Tag and attributes names are case sensitive:
- For tag names, the best practice is to keep them lower dash cased, do not update them,
- For attribute names, the best practice is to convert them from lower dash case to camel case.
Examples:
- `custom-tag` should stay `custom-tag` (do not update tag names),
- `[attr-name]` should be updated to `[attrName]`,
- `[attr-name=someValue]` should be updated to `[attrName=someValue]`,
- `custom-tag[attr-name=someValue]` should be updated to `custom-tag[attrName=someValue]`
Note: attribute values and classes are still matched case insensitive.
2. Update the inputs
```
@Directive({inputs: ['myProp', 'myOtherProp: my-attr-name']})
```
As attribute names are now case sensitive, they should be converted from dash to camel case where they are specified.
The previous decorator becomes:
```
@Directive({inputs: ['myProp', 'myOtherProp: myAttrName']})
```
Notes:
- only the long syntax (with ":") needs to be updated,
- `properties` is the legacy name for `inputs` and should be updated in the same way - it is a good idea to replace
`properties` with `inputs` at the same time as support for the former will be removed soon.
The same applies for the `@Input` decorator:
```
@Input() myProp;
@Input('my-attr-name') myProp;
```
That is they only need to be updated when the attribute name is specified:
```
@Input() myProp; // Nothing to update
@Input('myAttrName') myProp; // Convert the attribute name to camel case
```
3. Update the outputs
Update the outputs in the same way the inputs are updated:
```
@Directive({outputs: ['myEvent', 'myOtherEvent: my-event-name']})
```
should be updated to:
```
@Directive({outputs: ['myEvent', 'myOtherEvent: myEventName']})
```
If you use `events` instead of `outputs` you should update in the same way and switch to `outputs` as `events` is deprecated.
```
@Output() myEvent;
@Output('my-event-name') myEvent;
```
should be changed to:
```
@Output() myEvent;
@Output('myEventName') myEvent;
```
4. Update the host bindings
```
@Directive({
host: {
'[some-prop]': 'exp',
'[style.background-color]': 'exp',
'[class.some-class]': 'exp',
'[attr.some-attr]': 'exp',
'(some-event)': 'action()',
'some-attr': 'value'
}
})
```
should be changed to:
```
@Directive({
host: {
'[someProp]': 'exp',
'[style.background-color]': 'exp',
'[class.some-class]': 'exp',
'[attr.some-attr]': 'exp',
'(someEvent)': 'action()',
'some-attr': 'value'
}
})
```
The property bindings (`[...]`) and event bindings (`(...)`) must be updated in the same way as they are updated in a
template - ie converted to camel case (reminder: `[attr.]`, `[class.]` and `[style.]` should not be converted to camel case).
5. Update export name
```
@Directive({
exportAs: 'some-name'
})
```
should be changed to:
```
@Directive({
exportAs: 'someName'
})
```
# CSS
As the attribute names from your templates have been updated from dash to camel case, you should also reflect the changes
in your stylesheets.
The attributes that need to be updated are the ones used in the selector and the inputs of your directives.
Before:
```
// Directive
@Directive({
selector: '[my-dir]',
inputs: ['someProp: some-input'],
})
<!-- template -->
<div my-dir some-input="some value" not-an-input></div>
/* css */
[my-dir] { ... }
[some-input] { ... }
[not-an-input] { ... }
```
After:
```
// Directive
@Directive({
selector: '[myDir]',
inputs: ['someProp: someInput'],
})
<!-- template -->
<div myDir someInput="some value" not-an-input></div>
/* css */
[myDir] { ... }
[someInput] { ... }
[not-an-input] { ... }
```
Notes:
- `not-an-input` is not used in a selector nor it is an input of a directive, it need not be camel cased,
- CSS selectors are case insensitive you can use `[myDir]`, `[mydir]` or any other casing.

View File

@ -55,7 +55,7 @@ System.import("app");
```TypeScript
// app.ts
import {Component, View, platform} from "angular2/core";
import {WORKER_APP_PLATFORM, setupWebWorker} from "angular2/platform/worker_app";
import {WORKER_APP_PLATFORM, WORKER_APP_APPLICATION} from "angular2/platform/worker_app";
@Component({
selector: "hello-world"
@ -68,7 +68,7 @@ export class HelloWorld {
}
platform([WORKER_APP_PLATFORM])
.asyncApplication(setupWebWorker, optionalProviders?)
.application([WORKER_APP_APPLICATION])
.then((ref) => ref.bootstrap(RootComponent));
```
There's a few important things to note here:
@ -125,26 +125,26 @@ class HelloWorld {
main(List<String> args, SendPort replyTo) {
reflector.reflectionCapabilities = new ReflectionCapabilities();
platform([WORKER_APP_PLATFORM])
.asyncApplication(setupIsolate(replyTo))
.then((ref) => ref.bootstrap(RootComponent));
platform([WORKER_APP_PLATFORM, new Provider(RENDER_SEND_PORT, useValue: replyTo)])
.application([WORKER_APP_APPLICATION])
.bootstrap(RootComponent);
}
```
This code is nearly the same as the TypeScript version with just a couple key differences:
* We don't have a `loader.js` file. Dart applications don't need this file because you don't need a module loader.
* We pass a `SendPort` to `bootstrapWebWorker`. Dart applications use the Isolate API, which communicates via
* We provide a `SendPort` through DI using the token `RENDER_SEND_PORT`. Dart applications use the Isolate API, which communicates via
Dart's Port abstraction. When you call `setupIsolate` from the UI thread, angular starts a new Isolate to run
your application logic. When Dart starts a new Isolate it passes a `SendPort` to that Isolate so that it
can communicate with the Isolate that spawned it. You need to pass this `SendPort` to `bootstrapWebWorker`
can communicate with the Isolate that spawned it. You need to provide this `SendPort` through DI
so that Angular can communicate with the UI.
* You need to set up `ReflectionCapabilities` on both the UI and Worker. Just like writing non-concurrent
Angular2 Dart applications you need to set up the reflector. You should not use Reflection in production,
but should use the angular 2 transformer to remove it in your final JS code. Note there's currently a bug
with running the transformer on your UI code (#3971). You can (and should) pass the file where you call
`bootstrapWebWorker` as an entry point to the transformer, but you should not pass your UI index file
`bootstrap` as an entry point to the transformer, but you should not pass your UI index file
to the transformer until that bug is fixed.
* In dart we call `asyncApplication` instead of `application` because starting an isolate in Dart is asyncronous
* In dart we call `asyncApplication` instead of `application` from the render thread because starting an isolate in Dart is asyncronous
whereas starting a new WebWorker in JavaScript is a synchronous operation.
## Writing WebWorker Compatible Components
@ -392,18 +392,22 @@ import {WORKER_APP_PLATFORM, genericWorkerAppProviders} from "angular2/platform/
import {NgZone, platform, Provider} from "angular/core";
import {MyApp} from './app';
platform([WORKER_APP_PLATFORM_PROVIDERS])
.asyncApplication(initAppThread, optionalProviders?)
.then((ref) => ref.bootstrap(MyApp));
/**
* Do initialization work here to set up the app thread and MessageBus;
* Once you have a working MessageBus you should bootstrap your app.
*/
function initAppThread(zone: NgZone): Promise<Array<Type | Provider | any[]>> {
platform([WORKER_APP_PLATFORM_PROVIDERS])
.application([WORKER_APP_APPLICATION_COMMON, new Provider(MessageBus, {useValue: bus}),
new Provider(APP_INITIALIZER, {useFactory: (zone, bus) => () => initAppThread(zone, bus), multi: true, deps: [NgZone, MessageBus]})])
.bootstrap(MyApp);
function initAppThread(zone: NgZone, bus: MyAwesomeMessageBus): void{
/**
* Do initializtion work here to set up the app thread and MessageBus
* Once you have a working MessageBus that communicates with the render thread you should call genericWorkerAppProviders
* to get a list of Providers.
*/
var bus = new MyAwesomeMessageBus();
return genericWorkerAppProviders(myBus, zone);
* Here you can do any initilization work that requires the app providers to be initialized.
* At a minimum, you must attach your bus to the zone and setup a DOM adapter.
* Depending on your environment you may choose to do more work here.
*/
}
```
In Dart:
@ -432,27 +436,30 @@ import "package:angular2/core.dart";
import "./app.dart" show MyApp;
main() {
/**
* Do initialization work here to set up the app thread and MessageBus;
* Once you have a working MessageBus you should bootstrap your app.
*/
reflector.reflectionCapabilities = new ReflectionCapabilities();
platform([WORKER_APP_PLATFORM_PROVIDERS])
.asyncApplication(initAppThread, optionalProviders?)
.then((ref) => ref.bootstrap(MyApp));
.application([WORKER_APP_APPLICATION_COMMON, new Provider(MessageBus, useValue: bus),
new Provider(APP_INITIALIZER, useFactory: (zone, bus) => () => initAppThread(zone, bus), multi: true, deps: [NgZone, MessageBus])])
.bootstrap(MyApp);
}
Future<dynamic> initAppThread(NgZone zone) {
var bus = new MyAwesomeMessageBus();
return genericWorkerAppProviders(myBus, zone);
void initAppThread(NgZone zone) {
/**
* Here you can do any initilization work that requires the app providers to be initialized.
* At a minimum, you must attach your bus to the zone and setup a DOM adapter.
* Depending on your environment you may choose to do more work here.
*/
}
```
Notice how we use the `WORKER_RENDER_APP_COMMON` providers instead of the `WORKER_RENDER_APP` providers on the render thread.
This is because the `WORKER_RENDER_APP` providers include an application initializer that starts a new WebWorker/Isolate.
The `WORKER_RENDER_APP_COMMON` providers make no assumption about where your application code lives.
However, we now need to provide our own app initializer. At the very least this initializer needs to call `initializeGenericWorkerRenderer`.
This function performs necessary setup work to bootstrap the application.
Similarly we don&amp;t call `setupWebWorker` or `setupIsolate` from the application thread.
Instead we have our own initilization method that sets up our MessageBus and calls `genericWorkerAppProviders`
to finish setting up the application injector.
## MessageBroker
The MessageBroker is a higher level messaging abstraction that sits on top of the MessageBus. It is used when you

View File

@ -0,0 +1,30 @@
import {Component} from 'angular2/core';
import {MinLengthValidator, MaxLengthValidator} from 'angular2/common';
// #docregion min
@Component({
selector: 'min-cmp',
directives: [MinLengthValidator],
template: `
<form>
<p>Year: <input ngControl="year" minlength="2"></p>
</form>
`
})
class MinLengthTestComponent {
}
// #enddocregion
// #docregion max
@Component({
selector: 'max-cmp',
directives: [MaxLengthValidator],
template: `
<form>
<p>Year: <input ngControl="year" maxlength="4"></p>
</form>
`
})
class MaxLengthTestComponent {
}
// #enddocregion

View File

@ -0,0 +1,19 @@
import {provide} from 'angular2/core';
import {bootstrap} from 'angular2/bootstrap';
import {UrlResolver} from 'angular2/compiler';
var MyApp;
// #docregion url_resolver
class MyUrlResolver extends UrlResolver {
resolve(baseUrl: string, url: string): string {
// Serve CSS files from a special CDN.
if (url.substr(-4) === '.css') {
return super.resolve('http://cdn.myapp.com/css/', url);
}
return super.resolve(baseUrl, url);
}
}
bootstrap(MyApp, [provide(UrlResolver, {useClass: MyUrlResolver})]);
// #enddocregion

View File

@ -0,0 +1,16 @@
import {DebugElement, Scope} from 'angular2/core';
var debugElement: DebugElement;
var predicate;
// #docregion scope_all
debugElement.query(predicate, Scope.all);
// #enddocregion
// #docregion scope_light
debugElement.query(predicate, Scope.light);
// #enddocregion
// #docregion scope_view
debugElement.query(predicate, Scope.view);
// #enddocregion

View File

@ -0,0 +1,26 @@
import {Inject, Injector, forwardRef, resolveForwardRef, ForwardRefFn} from 'angular2/core';
// #docregion forward_ref_fn
var ref = forwardRef(() => Lock);
// #enddocregion
// #docregion forward_ref
class Door {
lock: Lock;
constructor(@Inject(forwardRef(() => Lock)) lock: Lock) { this.lock = lock; }
}
// Only at this point Lock is defined.
class Lock {}
var injector = Injector.resolveAndCreate([Door, Lock]);
var door = injector.get(Door);
expect(door instanceof Door).toBe(true);
expect(door.lock instanceof Lock).toBe(true);
// #enddocregion
// #docregion resolve_forward_ref
var ref = forwardRef(() => "refValue");
expect(resolveForwardRef(ref)).toEqual("refValue");
expect(resolveForwardRef("regularValue")).toEqual("regularValue");
// #enddocregion

View File

@ -0,0 +1,10 @@
import {bootstrap} from 'angular2/bootstrap';
import {NG_VALIDATORS} from 'angular2/common';
import {Provider} from 'angular2/core';
let MyApp = null;
let myValidator = null;
// #docregion ng_validators
bootstrap(MyApp, [new Provider(NG_VALIDATORS, {useValue: myValidator, multi: true})]);
// #enddocregion

View File

@ -1,12 +1,13 @@
import {Component, provide, Observable} from 'angular2/angular2';
import {Component, provide} from 'angular2/core';
import {bootstrap} from 'angular2/bootstrap';
import {Observable} from 'rxjs/Observable';
// #docregion AsyncPipe
@Component({
selector: 'async-example',
template: `<div>
<p>Wait for it... {{ greeting | async }}</p>
<button (click)="clicked()">{{ arrived ? 'Reset' : 'Resolve' }}</button>
<button (click)="clicked()">{{ arrived ? 'Reset' : 'Resolve' }}</button>
</div>`
})
export class AsyncPipeExample {
@ -44,7 +45,7 @@ class Task {
@Component({
selector: 'example-app',
directives: [AsyncPipeExample],
template: `
template: `
<h1>AsyncPipe Example</h1>
<async-example></async-example>
`

View File

@ -1,4 +1,4 @@
import {Component, provide} from 'angular2/angular2';
import {Component, provide} from 'angular2/core';
import {bootstrap} from 'angular2/bootstrap';
// #docregion DatePipe

View File

@ -1,4 +1,4 @@
import {Component, provide} from 'angular2/angular2';
import {Component, provide} from 'angular2/core';
import {bootstrap} from 'angular2/bootstrap';
// #docregion JsonPipe
@ -19,7 +19,7 @@ export class JsonPipeExample {
@Component({
selector: 'example-app',
directives: [JsonPipeExample],
template: `
template: `
<h1>JsonPipe Example</h1>
<json-example></json-example>
`

View File

@ -1,11 +1,11 @@
import {Component, provide} from 'angular2/angular2';
import {Component, provide} from 'angular2/core';
import {bootstrap} from 'angular2/bootstrap';
// #docregion LowerUpperPipe
@Component({
selector: 'lowerupper-example',
template: `<div>
<label>Name: </label><input #name (keyup)="change(name.value)" type="text"></input>
<label>Name: </label><input #name (keyup)="change(name.value)" type="text">
<p>In lowercase: <pre>'{{value | lowercase}}'</pre></p>
<p>In uppercase: <pre>'{{value | uppercase}}'</pre></p>
</div>`
@ -19,7 +19,7 @@ export class LowerUpperPipeExample {
@Component({
selector: 'example-app',
directives: [LowerUpperPipeExample],
template: `
template: `
<h1>LowercasePipe &amp; UppercasePipe Example</h1>
<lowerupper-example></lowerupper-example>
`

View File

@ -1,4 +1,4 @@
import {Component, provide} from 'angular2/angular2';
import {Component, provide} from 'angular2/core';
import {bootstrap} from 'angular2/bootstrap';
// #docregion NumberPipe
@ -48,7 +48,7 @@ export class CurrencyPipeExample {
@Component({
selector: 'example-app',
directives: [NumberPipeExample, PercentPipeExample, CurrencyPipeExample],
template: `
template: `
<h1>Numeric Pipe Examples</h1>
<h2>NumberPipe Example</h2>
<number-example></number-example>

View File

@ -1,4 +1,4 @@
import {Component, provide} from 'angular2/angular2';
import {Component, provide} from 'angular2/core';
import {bootstrap} from 'angular2/bootstrap';
// #docregion SlicePipe_string
@ -22,7 +22,7 @@ export class SlicePipeStringExample {
@Component({
selector: 'slice-list-example',
template: `<div>
<li *ng-for="var i of collection | slice:1:3">{{i}}</li>
<li *ngFor="var i of collection | slice:1:3">{{i}}</li>
</div>`
})
export class SlicePipeListExample {
@ -33,7 +33,7 @@ export class SlicePipeListExample {
@Component({
selector: 'example-app',
directives: [SlicePipeListExample, SlicePipeStringExample],
template: `
template: `
<h1>SlicePipe Examples</h1>
<slice-list-example></slice-list-example>
<slice-string-example></slice-string-example>

View File

@ -0,0 +1,13 @@
import {Component} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
// #docregion bootstrap
@Component({selector: 'my-app', template: 'Hello {{ name }}!'})
class MyApp {
name: string = 'World';
}
function main() {
return bootstrap(MyApp);
}
// #enddocregion

View File

@ -1,7 +0,0 @@
// #docregion enableDevMode
import {bootstrap, enableDevMode} from 'angular2/angular2';
import {MyComponent} from 'my_component';
enableDevMode();
bootstrap(MyComponent);
// #enddocregion

View File

@ -0,0 +1,43 @@
import {Component, Attribute, Directive, Pipe} from 'angular2/core';
var CustomDirective;
// #docregion component
@Component({selector: 'greet', template: 'Hello {{name}}!', directives: [CustomDirective]})
class Greet {
name: string = 'World';
}
// #enddocregion
// #docregion attributeFactory
@Component({selector: 'page', template: 'Title: {{title}}'})
class Page {
title: string;
constructor(@Attribute('title') title: string) { this.title = title; }
}
// #enddocregion
// #docregion attributeMetadata
@Directive({selector: 'input'})
class InputAttrDirective {
constructor(@Attribute('type') type) {
// type would be 'text' in this example
}
}
// #enddocregion
// #docregion directive
@Directive({selector: 'input'})
class InputDirective {
constructor() {
// Add some logic.
}
}
// #enddocregion
// #docregion pipe
@Pipe({name: 'lowercase'})
class Lowercase {
transform(v, args) { return v.toLowerCase(); }
}
// #enddocregion

View File

@ -0,0 +1,13 @@
import {Component, platform} from 'angular2/core';
import {BROWSER_PROVIDERS, BROWSER_APP_PROVIDERS} from 'angular2/platform/browser';
var appProviders: any[] = [];
// #docregion longform
@Component({selector: 'my-app', template: 'Hello World'})
class MyApp {
}
var app = platform(BROWSER_PROVIDERS).application([BROWSER_APP_PROVIDERS, appProviders]);
app.bootstrap(MyApp);
// #enddocregion

View File

@ -0,0 +1,8 @@
// #docregion enableProdMode
import {enableProdMode} from 'angular2/core';
import {bootstrap} from 'angular2/bootstrap';
import {MyComponent} from 'my_component';
enableProdMode();
bootstrap(MyComponent);
// #enddocregion

View File

@ -0,0 +1,8 @@
// #docregion Observable
import {Observable} from 'rxjs/Observable';
var obs = new Observable<number>(obs => {
var i = 0;
setInterval(_ => { obs.next(++i); }, 1000);
});
obs.subscribe(i => console.log(`${i} seconds elapsed`));
// #enddocregion

View File

@ -0,0 +1,3 @@
// #docregion Observable
import 'rxjs';
// #enddocregion

View File

@ -0,0 +1,10 @@
// #docregion Observable
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
var obs = new Observable(obs => {
var i = 0;
setInterval(_ => obs.next(++i), 1000);
});
obs.map(i => `${i} seconds elapsed`).subscribe(msg => console.log(msg));
// #enddocregion

View File

@ -0,0 +1,10 @@
// #docregion Observable
import {Observable} from 'rxjs/Observable';
import {map} from 'rxjs/operator/map';
var obs = new Observable(obs => {
var i = 0;
setInterval(_ => obs.next(++i), 1000);
});
map.call(obs, i => `${i} seconds elapsed`).subscribe(msg => console.log(msg));
// #enddocregion

View File

@ -0,0 +1,17 @@
import {By} from 'angular2/platform/browser';
import {DebugElement, Scope} from 'angular2/core';
var debugElement: DebugElement;
class MyDirective {}
// #docregion by_all
debugElement.query(By.all(), Scope.all);
// #enddocregion
// #docregion by_css
debugElement.query(By.css('[attribute]'), Scope.all);
// #enddocregion
// #docregion by_directive
debugElement.query(By.directive(MyDirective), Scope.all);
// #enddocregion

View File

@ -0,0 +1,10 @@
import {Component} from 'angular2/core';
import {bootstrap, ELEMENT_PROBE_PROVIDERS} from 'angular2/platform/browser';
@Component({selector: 'my-component'})
class MyAppComponent {
}
// #docregion providers
bootstrap(MyAppComponent, [ELEMENT_PROBE_PROVIDERS]);
// #enddocregion

View File

@ -1,4 +1,5 @@
import {bootstrap, provide, Component} from 'angular2/angular2';
import {provide, Component} from 'angular2/core';
import {bootstrap} from 'angular2/bootstrap';
import {
CanActivate,
RouteConfig,
@ -24,8 +25,8 @@ class ControlPanelCmp {
template: `
<h1>Welcome Home!</h1>
<div>
Edit <a [router-link]="['/ControlPanelCmp', {id: 1}]" id="user-1-link">User 1</a> |
Edit <a [router-link]="['/ControlPanelCmp', {id: 2}]" id="user-2-link">User 2</a>
Edit <a [routerLink]="['/ControlPanelCmp', {id: 1}]" id="user-1-link">User 1</a> |
Edit <a [routerLink]="['/ControlPanelCmp', {id: 2}]" id="user-2-link">User 2</a>
</div>
`,
directives: [ROUTER_DIRECTIVES]

View File

@ -1,4 +1,5 @@
import {provide, bootstrap, Component} from 'angular2/angular2';
import {provide, Component} from 'angular2/core';
import {bootstrap} from 'angular2/bootstrap';
import {
CanDeactivate,
RouteConfig,
@ -34,8 +35,8 @@ class NoteCmp implements CanDeactivate {
template: `
<h1>Your Notes</h1>
<div>
Edit <a [router-link]="['/NoteCmp', {id: 1}]" id="note-1-link">Note 1</a> |
Edit <a [router-link]="['/NoteCmp', {id: 2}]" id="note-2-link">Note 2</a>
Edit <a [routerLink]="['/NoteCmp', {id: 1}]" id="note-1-link">Note 1</a> |
Edit <a [routerLink]="['/NoteCmp', {id: 2}]" id="note-2-link">Note 2</a>
</div>
`,
directives: [ROUTER_DIRECTIVES]

View File

@ -1,4 +1,5 @@
import {Component, provide, bootstrap} from 'angular2/angular2';
import {Component, provide} from 'angular2/core';
import {bootstrap} from 'angular2/bootstrap';
import {
OnActivate,
ComponentInstruction,
@ -25,8 +26,8 @@ class MyCmp implements OnActivate {
template: `
<h1>My App</h1>
<nav>
<a [router-link]="['/HomeCmp']" id="home-link">Navigate Home</a> |
<a [router-link]="['/ParamCmp', {param: 1}]" id="param-link">Navigate with a Param</a>
<a [routerLink]="['/HomeCmp']" id="home-link">Navigate Home</a> |
<a [routerLink]="['/ParamCmp', {param: 1}]" id="param-link">Navigate with a Param</a>
</nav>
<router-outlet></router-outlet>
`,

View File

@ -1,4 +1,5 @@
import {Component, Injectable, NgFor, provide, bootstrap} from 'angular2/angular2';
import {Component, Injectable, provide} from 'angular2/core';
import {bootstrap} from 'angular2/bootstrap';
import {
OnDeactivate,
ComponentInstruction,
@ -34,16 +35,16 @@ class MyCmp implements OnDeactivate {
template: `
<h1>My App</h1>
<nav>
<a [router-link]="['/HomeCmp']" id="home-link">Navigate Home</a> |
<a [router-link]="['/ParamCmp', {param: 1}]" id="param-link">Navigate with a Param</a>
<a [routerLink]="['/HomeCmp']" id="home-link">Navigate Home</a> |
<a [routerLink]="['/ParamCmp', {param: 1}]" id="param-link">Navigate with a Param</a>
</nav>
<router-outlet></router-outlet>
<div id="log">
<h2>Log:</h2>
<p *ng-for="#logItem of logService.logs">{{ logItem }}</p>
<p *ngFor="#logItem of logService.logs">{{ logItem }}</p>
</div>
`,
directives: [ROUTER_DIRECTIVES, NgFor]
directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
{path: '/', component: MyCmp, name: 'HomeCmp'},

View File

@ -1,4 +1,5 @@
import {bootstrap, Component, provide} from 'angular2/angular2';
import {Component, provide} from 'angular2/core';
import {bootstrap} from 'angular2/bootstrap';
import {
CanActivate,
RouteConfig,
@ -37,8 +38,8 @@ class MyCmp implements CanReuse,
selector: 'example-app',
template: `
<h1>Say hi to...</h1>
<a [router-link]="['/HomeCmp', {name: 'naomi'}]" id="naomi-link">Naomi</a> |
<a [router-link]="['/HomeCmp', {name: 'brad'}]" id="brad-link">Brad</a>
<a [routerLink]="['/HomeCmp', {name: 'naomi'}]" id="naomi-link">Naomi</a> |
<a [routerLink]="['/HomeCmp', {name: 'brad'}]" id="brad-link">Brad</a>
<router-outlet></router-outlet>
`,
directives: [ROUTER_DIRECTIVES]

View File

@ -0,0 +1,29 @@
import {describe, it, fakeAsync, expect, tick, clearPendingTimers} from 'angular2/testing';
// #docregion basic
describe('this test', () => {
it('looks async but is synchronous', <any>fakeAsync((): void => {
var flag = false;
setTimeout(() => { flag = true; }, 100);
expect(flag).toBe(false);
tick(50);
expect(flag).toBe(false);
tick(50);
expect(flag).toBe(true);
}));
});
// #enddocregion
// #docregion pending
describe('this test', () => {
it('aborts a timer', <any>fakeAsync((): void => {
// This timer is scheduled but doesn't need to complete for the
// test to pass (maybe it's a timeout for some operation).
// Leaving it will cause the test to fail...
setTimeout(() => {}, 100);
// Unless we clean it up first.
clearPendingTimers();
}));
});
// #enddocregion

View File

@ -0,0 +1,40 @@
import {expect} from 'angular2/testing';
var value: any;
var element: any;
var exception: any;
abstract class OtherClass {}
class SomeClass {}
// #docregion toBePromise
expect(value).toBePromise();
// #enddocregion
// #docregion toBeAnInstanceOf
expect(value).toBeAnInstanceOf(SomeClass);
// #enddocregion
// #docregion toHaveText
expect(element).toHaveText('Hello world!');
// #enddocregion
// #docregion toHaveCssClass
expect(element).toHaveCssClass('current');
// #enddocregion
// #docregion toHaveCssStyle
expect(element).toHaveCssStyle({width: '100px', height: 'auto'});
// #enddocregion
// #docregion toContainError
expect(exception).toContainError('Failed to load');
// #enddocregion
// #docregion toThrowErrorWith
expect(() => { throw 'Failed to load'; }).toThrowErrorWith('Failed to load');
// #enddocregion
// #docregion toImplement
expect(SomeClass).toImplement(OtherClass);
// #enddocregion

View File

@ -0,0 +1,90 @@
import {
describe,
fdescribe,
xdescribe,
it,
fit,
xit,
beforeEach,
afterEach,
beforeEachProviders,
inject
} from 'angular2/testing';
import {provide} from 'angular2/core';
var db: any;
class MyService {}
class MyMockService implements MyService {}
// #docregion describeIt
describe('some component', () => {
it('does something', () => {
// This is a test.
});
});
// #enddocregion
// #docregion fdescribe
fdescribe('some component', () => {
it('has a test', () => {
// This test will run.
});
});
describe('another component',
() => { it('also has a test', () => { throw 'This test will not run.'; }); });
// #enddocregion
// #docregion xdescribe
xdescribe('some component', () => { it('has a test', () => {throw 'This test will not run.'}); });
describe('another component', () => {
it('also has a test', () => {
// This test will run.
});
});
// #enddocregion
// #docregion fit
describe('some component', () => {
fit('has a test', () => {
// This test will run.
});
it('has another test', () => { throw 'This test will not run.'; });
});
// #enddocregion
// #docregion xit
describe('some component', () => {
xit('has a test', () => { throw 'This test will not run.'; });
it('has another test', () => {
// This test will run.
});
});
// #enddocregion
// #docregion beforeEach
describe('some component', () => {
beforeEach(() => { db.connect(); });
it('uses the db', () => {
// Database is connected.
});
});
// #enddocregion
// #docregion beforeEachProviders
describe('some component', () => {
beforeEachProviders(() => [provide(MyService, {useClass: MyMockService})]);
it('uses MyService', inject([MyService], (service) => {
// service is an instance of MyMockService.
}));
});
// #enddocregion
// #docregion afterEach
describe('some component', () => {
afterEach((done) => { db.reset().then((_) => done()); });
it('uses the db', () => {
// This test can leave the database in a dirty state.
// The afterEach will ensure it gets reset.
});
});
// #enddocregion

View File

@ -44,7 +44,9 @@ export {URLSearchParams} from './src/http/url_search_params';
* ### Example ([live demo](http://plnkr.co/edit/snj7Nv?p=preview))
*
* ```
* import {bootstrap, Component, NgFor, View} from 'angular2/angular2';
* import {Component} from 'angular2/core';
* import {bootstrap} from 'angular2/platform/browser';
* import {NgFor} from 'angular2/common';
* import {HTTP_PROVIDERS, Http} from 'angular2/http';
*
* @Component({
@ -54,7 +56,7 @@ export {URLSearchParams} from './src/http/url_search_params';
* <div>
* <h1>People</h1>
* <ul>
* <li *ng-for="#person of people">
* <li *ngFor="#person of people">
* {{person.name}}
* </li>
* </ul>
@ -98,7 +100,8 @@ export {URLSearchParams} from './src/http/url_search_params';
* ### Example ([live demo](http://plnkr.co/edit/aCMEXi?p=preview))
*
* ```
* import {provide, bootstrap} from 'angular2/angular2';
* import {provide} from 'angular2/core';
* import {bootstrap} from 'angular2/platform/browser';
* import {HTTP_PROVIDERS, BaseRequestOptions, RequestOptions} from 'angular2/http';
*
* class MyOptions extends BaseRequestOptions {
@ -115,7 +118,8 @@ export {URLSearchParams} from './src/http/url_search_params';
* ### Example ([live demo](http://plnkr.co/edit/7LWALD?p=preview))
*
* ```
* import {provide, Injector} from 'angular2/angular2';
* import {provide} from 'angular2/core';
* import {bootstrap} from 'angular2/platform/browser';
* import {HTTP_PROVIDERS, Http, Response, XHRBackend} from 'angular2/http';
* import {MockBackend} from 'angular2/http/testing';
*
@ -162,6 +166,8 @@ export const HTTP_PROVIDERS: any[] = [
];
/**
* See {@link HTTP_PROVIDERS} instead.
*
* @deprecated
*/
export const HTTP_BINDINGS = HTTP_PROVIDERS;
@ -175,7 +181,8 @@ export const HTTP_BINDINGS = HTTP_PROVIDERS;
* ### Example ([live demo](http://plnkr.co/edit/vmeN4F?p=preview))
*
* ```
* import {Component, NgFor, View} from 'angular2/angular2';
* import {Component} from 'angular2/core';
* import {NgFor} from 'angular2/common';
* import {JSONP_PROVIDERS, Jsonp} from 'angular2/http';
*
* @Component({
@ -185,7 +192,7 @@ export const HTTP_BINDINGS = HTTP_PROVIDERS;
* <div>
* <h1>People</h1>
* <ul>
* <li *ng-for="#person of people">
* <li *ngFor="#person of people">
* {{person.name}}
* </li>
* </ul>
@ -222,7 +229,8 @@ export const HTTP_BINDINGS = HTTP_PROVIDERS;
* ### Example ([live demo](http://plnkr.co/edit/TFug7x?p=preview))
*
* ```
* import {provide, bootstrap} from 'angular2/angular2';
* import {provide} from 'angular2/core';
* import {bootstrap} from 'angular2/platform/browser';
* import {JSONP_PROVIDERS, BaseRequestOptions, RequestOptions} from 'angular2/http';
*
* class MyOptions extends BaseRequestOptions {
@ -239,7 +247,7 @@ export const HTTP_BINDINGS = HTTP_PROVIDERS;
* ### Example ([live demo](http://plnkr.co/edit/HDqZWL?p=preview))
*
* ```
* import {provide, Injector} from 'angular2/angular2';
* import {provide, Injector} from 'angular2/core';
* import {JSONP_PROVIDERS, Jsonp, Response, JSONPBackend} from 'angular2/http';
* import {MockBackend} from 'angular2/http/testing';
*
@ -285,6 +293,8 @@ export const JSONP_PROVIDERS: any[] = [
];
/**
* See {@link JSONP_PROVIDERS} instead.
*
* @deprecated
*/
export const JSON_BINDINGS = JSONP_PROVIDERS;

View File

@ -30,7 +30,6 @@ interface BrowserNodeGlobal {
zone: Zone;
getAngularTestability: Function;
getAllAngularTestabilities: Function;
angularDevMode: boolean;
setTimeout: Function;
clearTimeout: Function;
setInterval: Function;

View File

@ -62,23 +62,7 @@ export const BROWSER_APP_PROVIDERS: Array<any /*Type | Provider | any[]*/> = CON
*
* We can use this script code:
*
* ```
* @Component({
* selector: 'my-app',
* template: 'Hello {{ name }}!'
* })
* class MyApp {
* name:string;
*
* constructor() {
* this.name = 'World';
* }
* }
*
* main() {
* return bootstrap(MyApp);
* }
* ```
* {@example core/ts/bootstrap/bootstrap.ts region='bootstrap'}
*
* When the app developer invokes `bootstrap()` with the root component `MyApp` as its
* argument, Angular performs the following tasks:

View File

@ -0,0 +1,14 @@
library angular2.platform.worker_app;
export "package:angular2/src/platform/worker_app_common.dart"
show WORKER_APP_PLATFORM, WORKER_APP_APPLICATION_COMMON;
export "package:angular2/src/core/angular_entrypoint.dart"
show AngularEntrypoint;
export "package:angular2/src/platform/worker_app.dart"
show WORKER_APP_APPLICATION, RENDER_SEND_PORT;
export 'package:angular2/src/web_workers/shared/client_message_broker.dart'
show ClientMessageBroker, ClientMessageBrokerFactory, FnArg, UiArguments;
export 'package:angular2/src/web_workers/shared/service_message_broker.dart'
show ReceivedMessage, ServiceMessageBroker, ServiceMessageBrokerFactory;
export 'package:angular2/src/web_workers/shared/serializer.dart' show PRIMITIVE;
export 'package:angular2/src/web_workers/shared/message_bus.dart';

View File

@ -1,8 +1,8 @@
export {
WORKER_APP_PLATFORM,
genericWorkerAppProviders
WORKER_APP_APPLICATION_COMMON
} from 'angular2/src/platform/worker_app_common';
export * from 'angular2/src/platform/worker_app';
export {WORKER_APP_APPLICATION} from 'angular2/src/platform/worker_app';
export {
ClientMessageBroker,
ClientMessageBrokerFactory,

View File

@ -41,7 +41,7 @@ import {BaseException} from 'angular2/src/facade/exceptions';
* ### Example ([live demo](http://plnkr.co/edit/iRUP8B5OUbxCWQ3AcIDm))
*
* ```
* import {Component} from 'angular2/angular2';
* import {Component} from 'angular2/core';
* import {ROUTER_DIRECTIVES, ROUTER_PROVIDERS, RouteConfig} from 'angular2/router';
*
* @Component({directives: [ROUTER_DIRECTIVES]})
@ -63,7 +63,7 @@ export const ROUTER_DIRECTIVES: any[] = CONST_EXPR([RouterOutlet, RouterLink]);
* ### Example ([live demo](http://plnkr.co/edit/iRUP8B5OUbxCWQ3AcIDm))
*
* ```
* import {Component} from 'angular2/angular2';
* import {Component} from 'angular2/core';
* import {
* ROUTER_DIRECTIVES,
* ROUTER_PROVIDERS,
@ -98,6 +98,8 @@ export const ROUTER_PROVIDERS: any[] = CONST_EXPR([
]);
/**
* Use {@link ROUTER_PROVIDERS} instead.
*
* @deprecated
*/
export const ROUTER_BINDINGS = ROUTER_PROVIDERS;

View File

@ -31,5 +31,5 @@ export {RouterLinkTransform} from 'angular2/src/router/router_link_transform';
* <a [routerLink]="User[Modal]"> <!-- Same as <a [routerLink]="['User', ['Modal']]"> -->
* ```
*/
const ROUTER_LINK_DSL_PROVIDER =
CONST_EXPR(new Provider(TEMPLATE_TRANSFORMS, {useClass: RouterLinkTransform, multi: true}));
export const ROUTER_LINK_DSL_PROVIDER =
CONST_EXPR(new Provider(TEMPLATE_TRANSFORMS, {useClass: RouterLinkTransform, multi: true}));

View File

@ -17,7 +17,7 @@ import {CORE_DIRECTIVES} from './directives';
*
* ```typescript
* import {NgClass, NgIf, NgFor, NgSwitch, NgSwitchWhen, NgSwitchDefault, NgModel, NgForm} from
* 'angular2/angular2';
* 'angular2/common';
* import {OtherDirective} from './myDirectives';
*
* @Component({
@ -33,7 +33,7 @@ import {CORE_DIRECTIVES} from './directives';
* one could import all the common directives at once:
*
* ```typescript
* import {COMMON_DIRECTIVES} from 'angular2/angular2';
* import {COMMON_DIRECTIVES} from 'angular2/common';
* import {OtherDirective} from './myDirectives';
*
* @Component({
@ -46,4 +46,4 @@ import {CORE_DIRECTIVES} from './directives';
* }
* ```
*/
export const COMMON_DIRECTIVES: Type[][] = CONST_EXPR([CORE_DIRECTIVES, FORM_DIRECTIVES]);
export const COMMON_DIRECTIVES: Type[][] = CONST_EXPR([CORE_DIRECTIVES, FORM_DIRECTIVES]);

View File

@ -17,7 +17,7 @@ import {NgSwitch, NgSwitchWhen, NgSwitchDefault} from './ng_switch';
* Instead of writing:
*
* ```typescript
* import {NgClass, NgIf, NgFor, NgSwitch, NgSwitchWhen, NgSwitchDefault} from 'angular2/angular2';
* import {NgClass, NgIf, NgFor, NgSwitch, NgSwitchWhen, NgSwitchDefault} from 'angular2/common';
* import {OtherDirective} from './myDirectives';
*
* @Component({
@ -32,7 +32,7 @@ import {NgSwitch, NgSwitchWhen, NgSwitchDefault} from './ng_switch';
* one could import all the core directives at once:
*
* ```typescript
* import {CORE_DIRECTIVES} from 'angular2/angular2';
* import {CORE_DIRECTIVES} from 'angular2/common';
* import {OtherDirective} from './myDirectives';
*
* @Component({

View File

@ -31,13 +31,14 @@ import {StringMapWrapper, isListLikeIterable} from 'angular2/src/facade/collecti
* ### Example ([live demo](http://plnkr.co/edit/a4YdtmWywhJ33uqfpPPn?p=preview)):
*
* ```
* import {Component, NgClass} from 'angular2/angular2';
* import {Component} from 'angular2/core';
* import {NgClass} from 'angular2/common';
*
* @Component({
* selector: 'toggle-button',
* inputs: ['isDisabled'],
* template: `
* <div class="button" [ng-class]="{active: isOn, disabled: isDisabled}"
* <div class="button" [ngClass]="{active: isOn, disabled: isDisabled}"
* (click)="toggle(!isOn)">
* Click me!
* </div>`,
@ -70,7 +71,7 @@ import {StringMapWrapper, isListLikeIterable} from 'angular2/src/facade/collecti
* }
* ```
*/
@Directive({selector: '[ng-class]', inputs: ['rawClass: ng-class', 'initialClasses: class']})
@Directive({selector: '[ngClass]', inputs: ['rawClass: ngClass', 'initialClasses: class']})
export class NgClass implements DoCheck, OnDestroy {
private _differ: any;
private _mode: string;

View File

@ -50,16 +50,16 @@ import {isPresent, isBlank} from 'angular2/src/facade/lang';
*
* # Syntax
*
* - `<li *ng-for="#item of items; #i = index">...</li>`
* - `<li template="ng-for #item of items; #i = index">...</li>`
* - `<template ng-for #item [ng-for-of]="items" #i="index"><li>...</li></template>`
* - `<li *ngFor="#item of items; #i = index">...</li>`
* - `<li template="ngFor #item of items; #i = index">...</li>`
* - `<template ngFor #item [ngForOf]="items" #i="index"><li>...</li></template>`
*
* ### Example
*
* See a [live demo](http://plnkr.co/edit/KVuXxDp0qinGDyo307QW?p=preview) for a more detailed
* example.
*/
@Directive({selector: '[ng-for][ng-for-of]', inputs: ['ngForOf', 'ngForTemplate']})
@Directive({selector: '[ngFor][ngForOf]', inputs: ['ngForOf', 'ngForTemplate']})
export class NgFor implements DoCheck {
/** @internal */
_ngForOf: any;

View File

@ -4,13 +4,13 @@ import {isBlank} from 'angular2/src/facade/lang';
/**
* Removes or recreates a portion of the DOM tree based on an {expression}.
*
* If the expression assigned to `ng-if` evaluates to a false value then the element
* If the expression assigned to `ngIf` evaluates to a false value then the element
* is removed from the DOM, otherwise a clone of the element is reinserted into the DOM.
*
* ### Example ([live demo](http://plnkr.co/edit/fe0kgemFBtmQOY31b4tw?p=preview)):
*
* ```
* <div *ng-if="errorCount > 0" class="error">
* <div *ngIf="errorCount > 0" class="error">
* <!-- Error message displayed when the errorCount property on the current context is greater
* than 0. -->
* {{errorCount}} errors detected
@ -19,11 +19,11 @@ import {isBlank} from 'angular2/src/facade/lang';
*
* ### Syntax
*
* - `<div *ng-if="condition">...</div>`
* - `<div template="ng-if condition">...</div>`
* - `<template [ng-if]="condition"><div>...</div></template>`
* - `<div *ngIf="condition">...</div>`
* - `<div template="ngIf condition">...</div>`
* - `<template [ngIf]="condition"><div>...</div></template>`
*/
@Directive({selector: '[ng-if]', inputs: ['ngIf']})
@Directive({selector: '[ngIf]', inputs: ['ngIf']})
export class NgIf {
private _prevCondition: boolean = null;

View File

@ -11,24 +11,25 @@ import {isPresent, isBlank, print} from 'angular2/src/facade/lang';
/**
* The `NgStyle` directive changes styles based on a result of expression evaluation.
*
* An expression assigned to the `ng-style` property must evaluate to an object and the
* An expression assigned to the `ngStyle` property must evaluate to an object and the
* corresponding element styles are updated based on changes to this object. Style names to update
* are taken from the object's keys, and values - from the corresponding object's values.
*
* ### Syntax
*
* - `<div [ng-style]="{'font-style': style}"></div>`
* - `<div [ng-style]="styleExp"></div>` - here the `styleExp` must evaluate to an object
* - `<div [ngStyle]="{'font-style': style}"></div>`
* - `<div [ngStyle]="styleExp"></div>` - here the `styleExp` must evaluate to an object
*
* ### Example ([live demo](http://plnkr.co/edit/YamGS6GkUh9GqWNQhCyM?p=preview)):
*
* ```
* import {Component, NgStyle} from 'angular2/angular2';
* import {Component} from 'angular2/core';
* import {NgStyle} from 'angular2/common';
*
* @Component({
* selector: 'ng-style-example',
* selector: 'ngStyle-example',
* template: `
* <h1 [ng-style]="{'font-style': style, 'font-size': size, 'font-weight': weight}">
* <h1 [ngStyle]="{'font-style': style, 'font-size': size, 'font-weight': weight}">
* Change style of this text!
* </h1>
*
@ -58,7 +59,7 @@ import {isPresent, isBlank, print} from 'angular2/src/facade/lang';
* In this example the `font-style`, `font-size` and `font-weight` styles will be updated
* based on the `style` property's value changes.
*/
@Directive({selector: '[ng-style]', inputs: ['rawStyle: ng-style']})
@Directive({selector: '[ngStyle]', inputs: ['rawStyle: ngStyle']})
export class NgStyle implements DoCheck {
/** @internal */
_rawStyle;

View File

@ -21,12 +21,12 @@ class SwitchView {
* `NgSwitch` simply inserts nested elements based on which match expression matches the value
* obtained from the evaluated switch expression. In other words, you define a container element
* (where you place the directive with a switch expression on the
* **`[ng-switch]="..."` attribute**), define any inner elements inside of the directive and
* place a `[ng-switch-when]` attribute per element.
* **`[ngSwitch]="..."` attribute**), define any inner elements inside of the directive and
* place a `[ngSwitchWhen]` attribute per element.
*
* The `ng-switch-when` property is used to inform `NgSwitch` which element to display when the
* expression is evaluated. If a matching expression is not found via a `ng-switch-when` property
* then an element with the `ng-switch-default` attribute is displayed.
* The `ngSwitchWhen` property is used to inform `NgSwitch` which element to display when the
* expression is evaluated. If a matching expression is not found via a `ngSwitchWhen` property
* then an element with the `ngSwitchDefault` attribute is displayed.
*
* ### Example ([live demo](http://plnkr.co/edit/DQMTII95CbuqWrl3lYAs?p=preview))
*
@ -37,22 +37,22 @@ class SwitchView {
* <p>Value = {{value}}</p>
* <button (click)="inc()">Increment</button>
*
* <div [ng-switch]="value">
* <p *ng-switch-when="'init'">increment to start</p>
* <p *ng-switch-when="0">0, increment again</p>
* <p *ng-switch-when="1">1, increment again</p>
* <p *ng-switch-when="2">2, stop incrementing</p>
* <p *ng-switch-default>&gt; 2, STOP!</p>
* <div [ngSwitch]="value">
* <p *ngSwitchWhen="'init'">increment to start</p>
* <p *ngSwitchWhen="0">0, increment again</p>
* <p *ngSwitchWhen="1">1, increment again</p>
* <p *ngSwitchWhen="2">2, stop incrementing</p>
* <p *ngSwitchDefault>&gt; 2, STOP!</p>
* </div>
*
* <!-- alternate syntax -->
*
* <p [ng-switch]="value">
* <template ng-switch-when="init">increment to start</template>
* <template [ng-switch-when]="0">0, increment again</template>
* <template [ng-switch-when]="1">1, increment again</template>
* <template [ng-switch-when]="2">2, stop incrementing</template>
* <template ng-switch-default>&gt; 2, STOP!</template>
* <p [ngSwitch]="value">
* <template ngSwitchWhen="init">increment to start</template>
* <template [ngSwitchWhen]="0">0, increment again</template>
* <template [ngSwitchWhen]="1">1, increment again</template>
* <template [ngSwitchWhen]="2">2, stop incrementing</template>
* <template ngSwitchDefault>&gt; 2, STOP!</template>
* </p>
* `,
* directives: [NgSwitch, NgSwitchWhen, NgSwitchDefault]
@ -68,7 +68,7 @@ class SwitchView {
* bootstrap(App).catch(err => console.error(err));
* ```
*/
@Directive({selector: '[ng-switch]', inputs: ['ngSwitch']})
@Directive({selector: '[ngSwitch]', inputs: ['ngSwitch']})
export class NgSwitch {
private _switchValue: any;
private _useDefault: boolean = false;
@ -159,14 +159,14 @@ export class NgSwitch {
}
/**
* Insert the sub-tree when the `ng-switch-when` expression evaluates to the same value as the
* Insert the sub-tree when the `ngSwitchWhen` expression evaluates to the same value as the
* enclosing switch expression.
*
* If multiple match expression match the switch expression value, all of them are displayed.
*
* See {@link NgSwitch} for more details and example.
*/
@Directive({selector: '[ng-switch-when]', inputs: ['ngSwitchWhen']})
@Directive({selector: '[ngSwitchWhen]', inputs: ['ngSwitchWhen']})
export class NgSwitchWhen {
// `_WHEN_DEFAULT` is used as a marker for a not yet initialized value
/** @internal */
@ -193,7 +193,7 @@ export class NgSwitchWhen {
*
* See {@link NgSwitch} for more details and example.
*/
@Directive({selector: '[ng-switch-default]'})
@Directive({selector: '[ngSwitchDefault]'})
export class NgSwitchDefault {
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef,
@Host() sswitch: NgSwitch) {

View File

@ -2,4 +2,9 @@
// I need to be here to make TypeScript think this is a module.
import {} from 'angular2/src/facade/lang';
/**
* This module exists in Dart, but not in Typescript. This exported symbol
* is only here to help Typescript think this is a module.
*/
export var workaround_empty_observable_list_diff: any;

View File

@ -11,12 +11,12 @@ const CHECKBOX_VALUE_ACCESSOR = CONST_EXPR(new Provider(
*
* ### Example
* ```
* <input type="checkbox" ng-control="rememberLogin">
* <input type="checkbox" ngControl="rememberLogin">
* ```
*/
@Directive({
selector:
'input[type=checkbox][ng-control],input[type=checkbox][ng-form-control],input[type=checkbox][ng-model]',
'input[type=checkbox][ngControl],input[type=checkbox][ngFormControl],input[type=checkbox][ngModel]',
host: {'(change)': 'onChange($event.target.checked)', '(blur)': 'onTouched()'},
bindings: [CHECKBOX_VALUE_ACCESSOR]
})

View File

@ -26,4 +26,9 @@ export interface ControlValueAccessor {
registerOnTouched(fn: any): void;
}
/**
* Used to provide a {@link ControlValueAccessor} for form controls.
*
* See {@link DefaultValueAccessor} for how to implement one.
*/
export const NG_VALUE_ACCESSOR: OpaqueToken = CONST_EXPR(new OpaqueToken("NgValueAccessor"));

View File

@ -11,15 +11,15 @@ const DEFAULT_VALUE_ACCESSOR = CONST_EXPR(new Provider(
*
* ### Example
* ```
* <input type="text" ng-control="searchQuery">
* <input type="text" ngControl="searchQuery">
* ```
*/
@Directive({
selector:
'input:not([type=checkbox])[ng-control],textarea[ng-control],input:not([type=checkbox])[ng-form-control],textarea[ng-form-control],input:not([type=checkbox])[ng-model],textarea[ng-model],[ng-default-control]',
'input:not([type=checkbox])[ngControl],textarea[ngControl],input:not([type=checkbox])[ngFormControl],textarea[ngFormControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]',
// TODO: vsavkin replace the above selector with the one below it once
// https://github.com/angular/angular/issues/3011 is implemented
// selector: '[ng-control],[ng-model],[ng-form-control]',
// selector: '[ngControl],[ngModel],[ngFormControl]',
host: {'(input)': 'onChange($event.target.value)', '(blur)': 'onTouched()'},
bindings: [DEFAULT_VALUE_ACCESSOR]
})

View File

@ -38,17 +38,17 @@ const controlGroupProvider =
* <div>
* <h2>Angular2 Control &amp; ControlGroup Example</h2>
* <form #f="ngForm">
* <div ng-control-group="name" #cg-name="ngForm">
* <div ngControlGroup="name" #cg-name="form">
* <h3>Enter your name:</h3>
* <p>First: <input ng-control="first" required></p>
* <p>Middle: <input ng-control="middle"></p>
* <p>Last: <input ng-control="last" required></p>
* <p>First: <input ngControl="first" required></p>
* <p>Middle: <input ngControl="middle"></p>
* <p>Last: <input ngControl="last" required></p>
* </div>
* <h3>Name value:</h3>
* <pre>{{valueOf(cgName)}}</pre>
* <p>Name is {{cgName?.control?.valid ? "valid" : "invalid"}}</p>
* <h3>What's your favorite food?</h3>
* <p><input ng-control="food"></p>
* <p><input ngControl="food"></p>
* <h3>Form value</h3>
* <pre>{{valueOf(f)}}</pre>
* </form>
@ -70,9 +70,9 @@ const controlGroupProvider =
* this group can be accessed separately from the overall form.
*/
@Directive({
selector: '[ng-control-group]',
selector: '[ngControlGroup]',
providers: [controlGroupProvider],
inputs: ['name: ng-control-group'],
inputs: ['name: ngControlGroup'],
exportAs: 'ngForm'
})
export class NgControlGroup extends ControlContainer implements OnInit,

View File

@ -50,10 +50,10 @@ const controlNameBinding =
* directives: [FORM_DIRECTIVES],
* template: `
* <form #f="ngForm" (submit)='onLogIn(f.value)'>
* Login <input type='text' ng-control='login' #l="ngForm">
* <div *ng-if="!l.valid">Login is invalid</div>
* Login <input type='text' ngControl='login' #l="form">
* <div *ngIf="!l.valid">Login is invalid</div>
*
* Password <input type='password' ng-control='password'>
* Password <input type='password' ngControl='password'>
* <button type='submit'>Log in!</button>
* </form>
* `})
@ -64,7 +64,7 @@ const controlNameBinding =
* }
* ```
*
* We can also use ng-model to bind a domain model to the form.
* We can also use ngModel to bind a domain model to the form.
*
* ```
* @Component({
@ -72,9 +72,9 @@ const controlNameBinding =
* directives: [FORM_DIRECTIVES],
* template: `
* <form (submit)='onLogIn()'>
* Login <input type='text' ng-control='login' [(ng-model)]="credentials.login">
* Password <input type='password' ng-control='password'
* [(ng-model)]="credentials.password">
* Login <input type='text' ngControl='login' [(ngModel)]="credentials.login">
* Password <input type='password' ngControl='password'
* [(ngModel)]="credentials.password">
* <button type='submit'>Log in!</button>
* </form>
* `})
@ -89,7 +89,7 @@ const controlNameBinding =
* ```
*/
@Directive({
selector: '[ng-control]',
selector: '[ngControl]',
bindings: [controlNameBinding],
inputs: ['name: ngControl', 'model: ngModel'],
outputs: ['update: ngModelChange'],

View File

@ -2,8 +2,12 @@ import {Directive, Self} from 'angular2/core';
import {NgControl} from './ng_control';
import {isBlank, isPresent} from 'angular2/src/facade/lang';
/**
* Directive automatically applied to Angular forms that sets CSS classes
* based on control status (valid/invalid/dirty/etc).
*/
@Directive({
selector: '[ng-control],[ng-model],[ng-form-control]',
selector: '[ngControl],[ngModel],[ngFormControl]',
host: {
'[class.ng-untouched]': 'ngClassUntouched',
'[class.ng-touched]': 'ngClassTouched',

View File

@ -36,7 +36,7 @@ const formDirectiveProvider =
*
* ### Submission
*
* The `ng-submit` event signals when the user triggers a form submission.
* The `ngSubmit` event signals when the user triggers a form submission.
*
* ### Example ([live demo](http://plnkr.co/edit/ltdgYj4P0iY64AR71EpL?p=preview))
*
@ -47,16 +47,16 @@ const formDirectiveProvider =
* <div>
* <p>Submit the form to see the data object Angular builds</p>
* <h2>NgForm demo</h2>
* <form #f="ngForm" (ng-submit)="onSubmit(f.value)">
* <form #f="ngForm" (ngSubmit)="onSubmit(f.value)">
* <h3>Control group: credentials</h3>
* <div ng-control-group="credentials">
* <p>Login: <input type="text" ng-control="login"></p>
* <p>Password: <input type="password" ng-control="password"></p>
* <div ngControlGroup="credentials">
* <p>Login: <input type="text" ngControl="login"></p>
* <p>Password: <input type="password" ngControl="password"></p>
* </div>
* <h3>Control group: person</h3>
* <div ng-control-group="person">
* <p>First name: <input type="text" ng-control="firstName"></p>
* <p>Last name: <input type="text" ng-control="lastName"></p>
* <div ngControlGroup="person">
* <p>First name: <input type="text" ngControl="firstName"></p>
* <p>Last name: <input type="text" ngControl="lastName"></p>
* </div>
* <button type="submit">Submit Form</button>
* <p>Form data submitted:</p>
@ -78,7 +78,7 @@ const formDirectiveProvider =
* ```
*/
@Directive({
selector: 'form:not([ng-no-form]):not([ng-form-model]),ng-form,[ng-form]',
selector: 'form:not([ngNoForm]):not([ngFormModel]),ngForm,[ngForm]',
bindings: [formDirectiveProvider],
host: {
'(submit)': 'onSubmit()',

View File

@ -44,7 +44,7 @@ const formControlBinding =
* <h2>NgFormControl Example</h2>
* <form>
* <p>Element with existing control: <input type="text"
* [ng-form-control]="loginControl"></p>
* [ngFormControl]="loginControl"></p>
* <p>Value of existing control: {{loginControl.value}}</p>
* </form>
* </div>
@ -56,9 +56,9 @@ const formControlBinding =
* }
* ```
*
* ###ng-model
* ###ngModel
*
* We can also use `ng-model` to bind a domain model to the form.
* We can also use `ngModel` to bind a domain model to the form.
*
* ### Example ([live demo](http://plnkr.co/edit/yHMLuHO7DNgT8XvtjTDH?p=preview))
*
@ -66,7 +66,7 @@ const formControlBinding =
* @Component({
* selector: "login-comp",
* directives: [FORM_DIRECTIVES],
* template: "<input type='text' [ng-form-control]='loginControl' [(ng-model)]='login'>"
* template: "<input type='text' [ngFormControl]='loginControl' [(ngModel)]='login'>"
* })
* class LoginComp {
* loginControl: Control = new Control('');
@ -75,7 +75,7 @@ const formControlBinding =
* ```
*/
@Directive({
selector: '[ng-form-control]',
selector: '[ngFormControl]',
bindings: [formControlBinding],
inputs: ['form: ngFormControl', 'model: ngModel'],
outputs: ['update: ngModelChange'],

View File

@ -36,9 +36,9 @@ const formDirectiveProvider =
* template: `
* <div>
* <h2>NgFormModel Example</h2>
* <form [ng-form-model]="loginForm">
* <p>Login: <input type="text" ng-control="login"></p>
* <p>Password: <input type="password" ng-control="password"></p>
* <form [ngFormModel]="loginForm">
* <p>Login: <input type="text" ngControl="login"></p>
* <p>Password: <input type="password" ngControl="password"></p>
* </form>
* <p>Value:</p>
* <pre>{{value}}</pre>
@ -62,17 +62,17 @@ const formDirectiveProvider =
* }
* ```
*
* We can also use ng-model to bind a domain model to the form.
* We can also use ngModel to bind a domain model to the form.
*
* ```typescript
* @Component({
* selector: "login-comp",
* directives: [FORM_DIRECTIVES],
* template: `
* <form [ng-form-model]='loginForm'>
* Login <input type='text' ng-control='login' [(ng-model)]='credentials.login'>
* Password <input type='password' ng-control='password'
* [(ng-model)]='credentials.password'>
* <form [ngFormModel]='loginForm'>
* Login <input type='text' ngControl='login' [(ngModel)]='credentials.login'>
* Password <input type='password' ngControl='password'
* [(ngModel)]='credentials.password'>
* <button (click)="onLogin()">Login</button>
* </form>`
* })
@ -95,9 +95,9 @@ const formDirectiveProvider =
* ```
*/
@Directive({
selector: '[ng-form-model]',
selector: '[ngFormModel]',
bindings: [formDirectiveProvider],
inputs: ['form: ng-form-model'],
inputs: ['form: ngFormModel'],
host: {'(submit)': 'onSubmit()'},
outputs: ['ngSubmit'],
exportAs: 'ngForm'

View File

@ -31,8 +31,8 @@ const formControlBinding =
*
* ### Usage
*
* `ng-model` binds an existing domain model to a form control. For a
* two-way binding, use `[(ng-model)]` to ensure the model updates in
* `ngModel` binds an existing domain model to a form control. For a
* two-way binding, use `[(ngModel)]` to ensure the model updates in
* both directions.
*
* ### Example ([live demo](http://plnkr.co/edit/R3UX5qDaUqFO2VYR0UzH?p=preview))
@ -40,7 +40,7 @@ const formControlBinding =
* @Component({
* selector: "search-comp",
* directives: [FORM_DIRECTIVES],
* template: `<input type='text' [(ng-model)]="searchQuery">`
* template: `<input type='text' [(ngModel)]="searchQuery">`
* })
* class SearchComp {
* searchQuery: string;
@ -48,7 +48,7 @@ const formControlBinding =
* ```
*/
@Directive({
selector: '[ng-model]:not([ng-control]):not([ng-form-control])',
selector: '[ngModel]:not([ngControl]):not([ngFormControl])',
bindings: [formControlBinding],
inputs: ['model: ngModel'],
outputs: ['update: ngModelChange'],

View File

@ -11,12 +11,12 @@ const NUMBER_VALUE_ACCESSOR = CONST_EXPR(new Provider(
*
* ### Example
* ```
* <input type="number" [(ng-model)]="age">
* <input type="number" [(ngModel)]="age">
* ```
*/
@Directive({
selector:
'input[type=number][ng-control],input[type=number][ng-form-control],input[type=number][ng-model]',
'input[type=number][ngControl],input[type=number][ngFormControl],input[type=number][ngModel]',
host: {
'(change)': 'onChange($event.target.value)',
'(input)': 'onChange($event.target.value)',

View File

@ -22,8 +22,8 @@ const SELECT_VALUE_ACCESSOR = CONST_EXPR(new Provider(
* ### Example
*
* ```
* <select ng-control="city">
* <option *ng-for="#c of cities" [value]="c"></option>
* <select ngControl="city">
* <option *ngFor="#c of cities" [value]="c"></option>
* </select>
* ```
*/
@ -35,7 +35,7 @@ export class NgSelectOption {
* The accessor for writing a value and listening to changes on a select element.
*/
@Directive({
selector: 'select[ng-control],select[ng-form-control],select[ng-model]',
selector: 'select[ngControl],select[ngFormControl],select[ngModel]',
host: {
'(change)': 'onChange($event.target.value)',
'(input)': 'onChange($event.target.value)',

View File

@ -35,20 +35,32 @@ const REQUIRED_VALIDATOR =
* ### Example
*
* ```
* <input ng-control="fullName" required>
* <input ngControl="fullName" required>
* ```
*/
@Directive({
selector: '[required][ng-control],[required][ng-form-control],[required][ng-model]',
selector: '[required][ngControl],[required][ngFormControl],[required][ngModel]',
providers: [REQUIRED_VALIDATOR]
})
export class RequiredValidator {
}
/**
* Provivder which adds {@link MinLengthValidator} to {@link NG_VALIDATORS}.
*
* ## Example:
*
* {@example common/forms/ts/validators/validators.ts region='min'}
*/
const MIN_LENGTH_VALIDATOR = CONST_EXPR(
new Provider(NG_VALIDATORS, {useExisting: forwardRef(() => MinLengthValidator), multi: true}));
/**
* A directive which installs the {@link MinLengthValidator} for any `ngControl`,
* `ngFormControl`, or control with `ngModel` that also has a `minlength` attribute.
*/
@Directive({
selector: '[minlength][ng-control],[minlength][ng-form-control],[minlength][ng-model]',
selector: '[minlength][ngControl],[minlength][ngFormControl],[minlength][ngModel]',
providers: [MIN_LENGTH_VALIDATOR]
})
export class MinLengthValidator implements Validator {
@ -61,10 +73,22 @@ export class MinLengthValidator implements Validator {
validate(c: Control): {[key: string]: any} { return this._validator(c); }
}
/**
* Provider which adds {@link MaxLengthValidator} to {@link NG_VALIDATORS}.
*
* ## Example:
*
* {@example common/forms/ts/validators/validators.ts region='max'}
*/
const MAX_LENGTH_VALIDATOR = CONST_EXPR(
new Provider(NG_VALIDATORS, {useExisting: forwardRef(() => MaxLengthValidator), multi: true}));
/**
* A directive which installs the {@link MaxLengthValidator} for any `ngControl, `ngFormControl`,
* or control with `ngModel` that also has a `maxlength` attribute.
*/
@Directive({
selector: '[maxlength][ng-control],[maxlength][ng-form-control],[maxlength][ng-model]',
selector: '[maxlength][ngControl],[maxlength][ngFormControl],[maxlength][ngModel]',
providers: [MAX_LENGTH_VALIDATOR]
})
export class MaxLengthValidator implements Validator {

View File

@ -14,11 +14,11 @@ import * as modelModule from './model';
* selector: 'my-app',
* viewBindings: [FORM_BINDINGS]
* template: `
* <form [ng-form-model]="loginForm">
* <p>Login <input ng-control="login"></p>
* <div ng-control-group="passwordRetry">
* <p>Password <input type="password" ng-control="password"></p>
* <p>Confirm password <input type="password" ng-control="passwordConfirmation"></p>
* <form [ngFormModel]="loginForm">
* <p>Login <input ngControl="login"></p>
* <div ngControlGroup="passwordRetry">
* <p>Password <input type="password" ngControl="password"></p>
* <p>Confirm password <input type="password" ngControl="passwordConfirmation"></p>
* </div>
* </form>
* <h3>Form value:</h3>
@ -119,6 +119,8 @@ export class FormBuilder {
export const FORM_PROVIDERS: Type[] = CONST_EXPR([FormBuilder]);
/**
* See {@link FORM_PROVIDERS} instead.
*
* @deprecated
*/
export const FORM_BINDINGS = FORM_PROVIDERS;

View File

@ -13,21 +13,25 @@ import * as modelModule from './model';
*
* ### Example
*
* ```typescript
* var providers = [
* new Provider(NG_VALIDATORS, {useValue: myValidator, multi: true})
* ];
* ```
* {@example core/forms/ts/ng_validators/ng_validators.ts region='ng_validators'}
*/
export const NG_VALIDATORS: OpaqueToken = CONST_EXPR(new OpaqueToken("NgValidators"));
/**
* Providers for asynchronous validators to be used for {@link Control}s
* in a form.
*
* Provide this using `multi: true` to add validators.
*
* See {@link NG_VALIDATORS} for more details.
*/
export const NG_ASYNC_VALIDATORS: OpaqueToken = CONST_EXPR(new OpaqueToken("NgAsyncValidators"));
/**
* Provides a set of validators used by form controls.
*
* A validator is a function that processes a {@link Control} or collection of
* controls and returns a {@link StringMap} of errors. A null map means that
* validation has passed.
* controls and returns a map of errors. A null map means that validation has passed.
*
* ### Example
*

View File

@ -20,6 +20,13 @@ export {LowerCasePipe} from './pipes/lowercase_pipe';
export {NumberPipe, DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe';
export {UpperCasePipe} from './pipes/uppercase_pipe';
/**
* A collection of Angular core pipes that are likely to be used in each and every
* application.
*
* This collection can be used to quickly enumerate all the built-in pipes in the `pipes`
* property of the `@Component` or `@View` decorators.
*/
export const COMMON_PIPES = CONST_EXPR([
AsyncPipe,
UpperCasePipe,

View File

@ -81,7 +81,7 @@ export class AsyncPipe implements PipeTransform, OnDestroy {
if (isPresent(obj)) {
this._subscribe(obj);
}
return null;
return this._latestValue;
}
if (obj !== this._obj) {

View File

@ -12,6 +12,13 @@ import {DatePipe} from './date_pipe';
import {DecimalPipe, PercentPipe, CurrencyPipe} from './number_pipe';
import {CONST_EXPR} from 'angular2/src/facade/lang';
/**
* A collection of Angular core pipes that are likely to be used in each and every
* application.
*
* This collection can be used to quickly enumerate all the built-in pipes in the `pipes`
* property of the `@Component` or `@View` decorators.
*/
export const COMMON_PIPES = CONST_EXPR([
AsyncPipe,
UpperCasePipe,

View File

@ -42,7 +42,7 @@ import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
*
* ## List Example
*
* This `ng-for` example:
* This `ngFor` example:
*
* {@example core/pipes/ts/slice_pipe/slice_pipe_example.ts region='SlicePipe_list'}
*

View File

@ -1,18 +0,0 @@
import {AppRootUrl} from "angular2/src/compiler/app_root_url";
import {DOM} from "angular2/src/platform/dom/dom_adapter";
import {Injectable} from "angular2/src/core/di";
/**
* Extension of {@link AppRootUrl} that uses a DOM anchor tag to set the root url to
* the current page's url.
*/
@Injectable()
export class AnchorBasedAppRootUrl extends AppRootUrl {
constructor() {
super("");
// compute the root url to pass to AppRootUrl
var a = DOM.createElement('a');
DOM.resolveAndSetHref(a, './', null);
this.value = DOM.getHref(a);
}
}

View File

@ -1,16 +0,0 @@
import {Injectable} from 'angular2/src/core/di';
import {isBlank} from 'angular2/src/facade/lang';
/**
* Specifies app root url for the application.
*
* Used by the {@link Compiler} when resolving HTML and CSS template URLs.
*
* This interface can be overridden by the application developer to create custom behavior.
*
* See {@link Compiler}
*/
@Injectable()
export class AppRootUrl {
constructor(public value: string) {}
}

View File

@ -24,15 +24,17 @@ import {Compiler} from 'angular2/src/core/linker/compiler';
import {RuntimeCompiler} from 'angular2/src/compiler/runtime_compiler';
import {ElementSchemaRegistry} from 'angular2/src/compiler/schema/element_schema_registry';
import {DomElementSchemaRegistry} from 'angular2/src/compiler/schema/dom_element_schema_registry';
import {UrlResolver} from 'angular2/src/compiler/url_resolver';
import {AppRootUrl} from 'angular2/src/compiler/app_root_url';
import {AnchorBasedAppRootUrl} from 'angular2/src/compiler/anchor_based_app_root_url';
import {UrlResolver, DEFAULT_PACKAGE_URL_PROVIDER} from 'angular2/src/compiler/url_resolver';
import {Parser, Lexer} from 'angular2/src/core/change_detection/change_detection';
function _createChangeDetectorGenConfig() {
return new ChangeDetectorGenConfig(assertionsEnabled(), false, true);
}
/**
* A set of providers that provide `RuntimeCompiler` and its dependencies to use for
* template compilation.
*/
export const COMPILER_PROVIDERS: Array<Type | Provider | any[]> = CONST_EXPR([
Lexer,
Parser,
@ -40,6 +42,7 @@ export const COMPILER_PROVIDERS: Array<Type | Provider | any[]> = CONST_EXPR([
TemplateParser,
TemplateNormalizer,
RuntimeMetadataResolver,
DEFAULT_PACKAGE_URL_PROVIDER,
StyleCompiler,
CommandCompiler,
ChangeDetectionCompiler,
@ -49,7 +52,5 @@ export const COMPILER_PROVIDERS: Array<Type | Provider | any[]> = CONST_EXPR([
new Provider(Compiler, {useExisting: RuntimeCompiler}),
DomElementSchemaRegistry,
new Provider(ElementSchemaRegistry, {useExisting: DomElementSchemaRegistry}),
AnchorBasedAppRootUrl,
new Provider(AppRootUrl, {useExisting: AnchorBasedAppRootUrl}),
UrlResolver
]);

View File

@ -21,6 +21,9 @@ import {LifecycleHooks, LIFECYCLE_HOOKS_VALUES} from 'angular2/src/core/linker/i
// group 2: "event" from "(event)"
var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g;
/**
* Metadata regarding compilation of a type.
*/
export class CompileTypeMetadata {
runtime: Type;
name: string;
@ -49,6 +52,9 @@ export class CompileTypeMetadata {
}
}
/**
* Metadata regarding compilation of a template.
*/
export class CompileTemplateMetadata {
encapsulation: ViewEncapsulation;
template: string;
@ -98,6 +104,9 @@ export class CompileTemplateMetadata {
}
}
/**
* Metadata regarding compilation of a directive.
*/
export class CompileDirectiveMetadata {
static create({type, isComponent, dynamicLoadable, selector, exportAs, changeDetection, inputs,
outputs, host, lifecycleHooks, template}: {
@ -250,6 +259,9 @@ export class CompileDirectiveMetadata {
}
}
/**
* Construct {@link CompileDirectiveMetadata} from {@link ComponentTypeMetadata} and a selector.
*/
export function createHostComponentMeta(componentType: CompileTypeMetadata,
componentSelector: string): CompileDirectiveMetadata {
var template = CssSelector.parse(componentSelector)[0].getMatchingElementTemplate();

View File

@ -84,8 +84,7 @@ const $x = 120;
const $NBSP = 160;
var CRLF_REGEXP = /\r\n/g;
var CR_REGEXP = /\r/g;
var CR_OR_CRLF_REGEXP = /\r\n?/g;
function unexpectedCharacterErrorMsg(charCode: number): string {
var char = charCode === $EOF ? 'EOF' : StringWrapper.fromCharCode(charCode);
@ -127,8 +126,7 @@ class _HtmlTokenizer {
// http://www.w3.org/TR/html5/syntax.html#preprocessing-the-input-stream
// In order to keep the original position in the source, we can not pre-process it.
// Instead CRs are processed right before instantiating the tokens.
content = StringWrapper.replaceAll(content, CRLF_REGEXP, '\r');
return StringWrapper.replaceAll(content, CR_REGEXP, '\n');
return StringWrapper.replaceAll(content, CR_OR_CRLF_REGEXP, '\n');
}
tokenize(): HtmlTokenizeResult {

View File

@ -16,7 +16,7 @@ import {HtmlAst, HtmlAttrAst, HtmlTextAst, HtmlElementAst} from './html_ast';
import {Injectable} from 'angular2/src/core/di';
import {HtmlToken, HtmlTokenType, tokenizeHtml} from './html_lexer';
import {ParseError, ParseLocation, ParseSourceSpan} from './parse_util';
import {HtmlTagDefinition, getHtmlTagDefinition, getHtmlTagNamespacePrefix} from './html_tags';
import {HtmlTagDefinition, getHtmlTagDefinition, getNsPrefix} from './html_tags';
export class HtmlTreeError extends ParseError {
static create(elementName: string, location: ParseLocation, msg: string): HtmlTreeError {
@ -144,7 +144,7 @@ class TreeBuilder {
if (this.peek.type === HtmlTokenType.TAG_OPEN_END_VOID) {
this._advance();
selfClosing = true;
if (getHtmlTagNamespacePrefix(fullName) == null && !getHtmlTagDefinition(fullName).isVoid) {
if (getNsPrefix(fullName) == null && !getHtmlTagDefinition(fullName).isVoid) {
this.errors.push(HtmlTreeError.create(
fullName, startTagToken.sourceSpan.start,
`Only void and foreign elements can be self closed "${startTagToken.parts[1]}"`));
@ -200,7 +200,7 @@ class TreeBuilder {
private _popElement(fullName: string): boolean {
for (let stackIndex = this.elementStack.length - 1; stackIndex >= 0; stackIndex--) {
let el = this.elementStack[stackIndex];
if (el.name.toLowerCase() == fullName.toLowerCase()) {
if (el.name == fullName) {
ListWrapper.splice(this.elementStack, stackIndex, this.elementStack.length - stackIndex);
return true;
}
@ -247,7 +247,7 @@ function getElementFullName(prefix: string, localName: string,
if (isBlank(prefix)) {
prefix = getHtmlTagDefinition(localName).implicitNamespacePrefix;
if (isBlank(prefix) && isPresent(parentElement)) {
prefix = getHtmlTagNamespacePrefix(parentElement.name);
prefix = getNsPrefix(parentElement.name);
}
}

View File

@ -409,7 +409,7 @@ export function getHtmlTagDefinition(tagName: string): HtmlTagDefinition {
var NS_PREFIX_RE = /^@([^:]+):(.+)/g;
export function splitHtmlTagNamespace(elementName: string): string[] {
export function splitNsName(elementName: string): string[] {
if (elementName[0] != '@') {
return [null, elementName];
}
@ -417,6 +417,6 @@ export function splitHtmlTagNamespace(elementName: string): string[] {
return [match[1], match[2]];
}
export function getHtmlTagNamespacePrefix(elementName: string): string {
return splitHtmlTagNamespace(elementName)[0];
export function getNsPrefix(elementName: string): string {
return splitNsName(elementName)[0];
}

View File

@ -0,0 +1,214 @@
import {Injectable, Provider, provide} from 'angular2/src/core/di';
import {
StringWrapper,
RegExpWrapper,
CONST_EXPR,
isBlank,
isPresent
} from 'angular2/src/facade/lang';
import {HtmlAstVisitor, HtmlAttrAst, HtmlElementAst, HtmlTextAst, HtmlAst} from './html_ast';
import {HtmlParser, HtmlParseTreeResult} from './html_parser';
import {dashCaseToCamelCase, camelCaseToDashCase} from './util';
var LONG_SYNTAX_REGEXP = /^(?:on-(.*)|bindon-(.*)|bind-(.*)|var-(.*))$/ig;
var SHORT_SYNTAX_REGEXP = /^(?:\((.*)\)|\[\((.*)\)\]|\[(.*)\]|#(.*))$/ig;
var VARIABLE_TPL_BINDING_REGEXP = /(\bvar\s+|#)(\S+)/ig;
var TEMPLATE_SELECTOR_REGEXP = /^(\S+)/g;
var SPECIAL_PREFIXES_REGEXP = /^(class|style|attr)\./ig;
var INTERPOLATION_REGEXP = /\{\{.*?\}\}/g;
const SPECIAL_CASES = CONST_EXPR([
'ng-non-bindable',
'ng-default-control',
'ng-no-form',
]);
/**
* Convert templates to the case sensitive syntax
*
* @internal
*/
export class LegacyHtmlAstTransformer implements HtmlAstVisitor {
rewrittenAst: HtmlAst[] = [];
visitingTemplateEl: boolean = false;
constructor(private dashCaseSelectors?: string[]) {}
visitElement(ast: HtmlElementAst, context: any): HtmlElementAst {
this.visitingTemplateEl = ast.name.toLowerCase() == 'template';
let attrs = ast.attrs.map(attr => attr.visit(this, null));
let children = ast.children.map(child => child.visit(this, null));
return new HtmlElementAst(ast.name, attrs, children, ast.sourceSpan);
}
visitAttr(originalAst: HtmlAttrAst, context: any): HtmlAttrAst {
let ast = originalAst;
if (this.visitingTemplateEl) {
if (isPresent(RegExpWrapper.firstMatch(LONG_SYNTAX_REGEXP, ast.name))) {
// preserve the "-" in the prefix for the long syntax
ast = this._rewriteLongSyntax(ast);
} else {
// rewrite any other attribute
let name = dashCaseToCamelCase(ast.name);
ast = name == ast.name ? ast : new HtmlAttrAst(name, ast.value, ast.sourceSpan);
}
} else {
ast = this._rewriteTemplateAttribute(ast);
ast = this._rewriteLongSyntax(ast);
ast = this._rewriteShortSyntax(ast);
ast = this._rewriteStar(ast);
ast = this._rewriteInterpolation(ast);
ast = this._rewriteSpecialCases(ast);
}
if (ast !== originalAst) {
this.rewrittenAst.push(ast);
}
return ast;
}
visitText(ast: HtmlTextAst, context: any): HtmlTextAst { return ast; }
private _rewriteLongSyntax(ast: HtmlAttrAst): HtmlAttrAst {
let m = RegExpWrapper.firstMatch(LONG_SYNTAX_REGEXP, ast.name);
let attrName = ast.name;
let attrValue = ast.value;
if (isPresent(m)) {
if (isPresent(m[1])) {
attrName = `on-${dashCaseToCamelCase(m[1])}`;
} else if (isPresent(m[2])) {
attrName = `bindon-${dashCaseToCamelCase(m[2])}`;
} else if (isPresent(m[3])) {
attrName = `bind-${dashCaseToCamelCase(m[3])}`;
} else if (isPresent(m[4])) {
attrName = `var-${dashCaseToCamelCase(m[4])}`;
attrValue = dashCaseToCamelCase(attrValue);
}
}
return attrName == ast.name && attrValue == ast.value ?
ast :
new HtmlAttrAst(attrName, attrValue, ast.sourceSpan);
}
private _rewriteTemplateAttribute(ast: HtmlAttrAst): HtmlAttrAst {
let name = ast.name;
let value = ast.value;
if (name.toLowerCase() == 'template') {
name = 'template';
// rewrite the directive selector
value = StringWrapper.replaceAllMapped(value, TEMPLATE_SELECTOR_REGEXP,
(m) => { return dashCaseToCamelCase(m[1]); });
// rewrite the var declarations
value = StringWrapper.replaceAllMapped(value, VARIABLE_TPL_BINDING_REGEXP, m => {
return `${m[1].toLowerCase()}${dashCaseToCamelCase(m[2])}`;
});
}
if (name == ast.name && value == ast.value) {
return ast;
}
return new HtmlAttrAst(name, value, ast.sourceSpan);
}
private _rewriteShortSyntax(ast: HtmlAttrAst): HtmlAttrAst {
let m = RegExpWrapper.firstMatch(SHORT_SYNTAX_REGEXP, ast.name);
let attrName = ast.name;
let attrValue = ast.value;
if (isPresent(m)) {
if (isPresent(m[1])) {
attrName = `(${dashCaseToCamelCase(m[1])})`;
} else if (isPresent(m[2])) {
attrName = `[(${dashCaseToCamelCase(m[2])})]`;
} else if (isPresent(m[3])) {
let prop = StringWrapper.replaceAllMapped(m[3], SPECIAL_PREFIXES_REGEXP,
(m) => { return m[1].toLowerCase() + '.'; });
if (prop.startsWith('class.') || prop.startsWith('attr.') || prop.startsWith('style.')) {
attrName = `[${prop}]`;
} else {
attrName = `[${dashCaseToCamelCase(prop)}]`;
}
} else if (isPresent(m[4])) {
attrName = `#${dashCaseToCamelCase(m[4])}`;
attrValue = dashCaseToCamelCase(attrValue);
}
}
return attrName == ast.name && attrValue == ast.value ?
ast :
new HtmlAttrAst(attrName, attrValue, ast.sourceSpan);
}
private _rewriteStar(ast: HtmlAttrAst): HtmlAttrAst {
let attrName = ast.name;
let attrValue = ast.value;
if (attrName[0] == '*') {
attrName = dashCaseToCamelCase(attrName);
// rewrite the var declarations
attrValue = StringWrapper.replaceAllMapped(attrValue, VARIABLE_TPL_BINDING_REGEXP, m => {
return `${m[1].toLowerCase()}${dashCaseToCamelCase(m[2])}`;
});
}
return attrName == ast.name && attrValue == ast.value ?
ast :
new HtmlAttrAst(attrName, attrValue, ast.sourceSpan);
}
private _rewriteInterpolation(ast: HtmlAttrAst): HtmlAttrAst {
let hasInterpolation = RegExpWrapper.test(INTERPOLATION_REGEXP, ast.value);
if (!hasInterpolation) {
return ast;
}
let name = ast.name;
if (!(name.startsWith('attr.') || name.startsWith('class.') || name.startsWith('style.'))) {
name = dashCaseToCamelCase(ast.name);
}
return name == ast.name ? ast : new HtmlAttrAst(name, ast.value, ast.sourceSpan);
}
private _rewriteSpecialCases(ast: HtmlAttrAst): HtmlAttrAst {
let attrName = ast.name;
if (SPECIAL_CASES.indexOf(attrName) > -1) {
return new HtmlAttrAst(dashCaseToCamelCase(attrName), ast.value, ast.sourceSpan);
}
if (isPresent(this.dashCaseSelectors) && this.dashCaseSelectors.indexOf(attrName) > -1) {
return new HtmlAttrAst(dashCaseToCamelCase(attrName), ast.value, ast.sourceSpan);
}
return ast;
}
}
@Injectable()
export class LegacyHtmlParser extends HtmlParser {
parse(sourceContent: string, sourceUrl: string): HtmlParseTreeResult {
let transformer = new LegacyHtmlAstTransformer();
let htmlParseTreeResult = super.parse(sourceContent, sourceUrl);
let rootNodes = htmlParseTreeResult.rootNodes.map(node => node.visit(transformer, null));
return transformer.rewrittenAst.length > 0 ?
new HtmlParseTreeResult(rootNodes, htmlParseTreeResult.errors) :
htmlParseTreeResult;
}
}

View File

@ -19,6 +19,7 @@ import {reflector} from 'angular2/src/core/reflection/reflection';
import {Injectable, Inject, Optional} from 'angular2/src/core/di';
import {PLATFORM_DIRECTIVES} from 'angular2/src/core/platform_directives_and_pipes';
import {MODULE_SUFFIX} from './util';
import {getUrlScheme} from 'angular2/src/compiler/url_resolver';
@Injectable()
export class RuntimeMetadataResolver {
@ -31,12 +32,13 @@ export class RuntimeMetadataResolver {
var meta = this._cache.get(directiveType);
if (isBlank(meta)) {
var dirMeta = this._directiveResolver.resolve(directiveType);
var moduleUrl = calcModuleUrl(directiveType, dirMeta);
var moduleUrl = null;
var templateMeta = null;
var changeDetectionStrategy = null;
if (dirMeta instanceof md.ComponentMetadata) {
var cmpMeta = <md.ComponentMetadata>dirMeta;
moduleUrl = calcModuleUrl(directiveType, cmpMeta);
var viewMeta = this._viewResolver.resolve(directiveType);
templateMeta = new cpl.CompileTemplateMetadata({
encapsulation: viewMeta.encapsulation,
@ -106,9 +108,12 @@ function isValidDirective(value: Type): boolean {
return isPresent(value) && (value instanceof Type);
}
function calcModuleUrl(type: Type, dirMeta: md.DirectiveMetadata): string {
if (isPresent(dirMeta.moduleId)) {
return `package:${dirMeta.moduleId}${MODULE_SUFFIX}`;
function calcModuleUrl(type: Type, cmpMetadata: md.ComponentMetadata): string {
var moduleId = cmpMetadata.moduleId;
if (isPresent(moduleId)) {
var scheme = getUrlScheme(moduleId);
return isPresent(scheme) && scheme.length > 0 ? moduleId :
`package:${moduleId}${MODULE_SUFFIX}`;
} else {
return reflector.importUri(type);
}

View File

@ -2,7 +2,7 @@ import {Injectable} from 'angular2/src/core/di';
import {isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
import {StringMapWrapper} from 'angular2/src/facade/collection';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {splitHtmlTagNamespace} from 'angular2/src/compiler/html_tags';
import {splitNsName} from 'angular2/src/compiler/html_tags';
import {ElementSchemaRegistry} from './element_schema_registry';
@ -16,7 +16,7 @@ export class DomElementSchemaRegistry extends ElementSchemaRegistry {
private _getProtoElement(tagName: string): Element {
var element = this._protoElements.get(tagName);
if (isBlank(element)) {
var nsAndName = splitHtmlTagNamespace(tagName);
var nsAndName = splitNsName(tagName);
element = isPresent(nsAndName[0]) ?
DOM.createElementNS(NAMESPACE_URIS[nsAndName[0]], nsAndName[1]) :
DOM.createElement(nsAndName[1]);

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