Compare commits
2 Commits
2.0.0-beta
...
2.0.0-beta
Author | SHA1 | Date | |
---|---|---|---|
4f1f29d7d2 | |||
b1b73dc39e |
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,7 +22,6 @@ tmp
|
|||||||
*.js.map
|
*.js.map
|
||||||
|
|
||||||
# Or type definitions we mirror from github
|
# Or type definitions we mirror from github
|
||||||
# (NB: these lines are removed in publish-build-artifacts.sh)
|
|
||||||
**/typings/**/*.d.ts
|
**/typings/**/*.d.ts
|
||||||
**/typings/tsd.cached.json
|
**/typings/tsd.cached.json
|
||||||
|
|
||||||
|
23
.travis.yml
23
.travis.yml
@ -9,19 +9,13 @@ branches:
|
|||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
|
- node_modules
|
||||||
- $HOME/.pub-cache
|
- $HOME/.pub-cache
|
||||||
- $HOME/.chrome/chromium
|
|
||||||
|
|
||||||
before_cache:
|
|
||||||
# Undo the pollution of the typescript_next build
|
|
||||||
- npm install typescript
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- KARMA_DART_BROWSERS=DartiumWithWebPlatform
|
- KARMA_BROWSERS=DartiumWithWebPlatform
|
||||||
# No sandbox mode is needed for Chromium in Travis, it crashes otherwise: https://sites.google.com/a/chromium.org/chromedriver/help/chrome-doesn-t-start
|
- E2E_BROWSERS=Dartium
|
||||||
- KARMA_JS_BROWSERS=ChromeNoSandbox
|
|
||||||
- E2E_BROWSERS=ChromeOnTravis
|
|
||||||
- LOGS_DIR=/tmp/angular-build/logs
|
- LOGS_DIR=/tmp/angular-build/logs
|
||||||
- SAUCE_USERNAME=angular-ci
|
- SAUCE_USERNAME=angular-ci
|
||||||
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
|
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
|
||||||
@ -42,7 +36,8 @@ env:
|
|||||||
matrix:
|
matrix:
|
||||||
# Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete.
|
# Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete.
|
||||||
- MODE=dart DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION
|
- MODE=dart DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION
|
||||||
- MODE=dart DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
# Disable dart dev build, which is timing out after 2h. #6823
|
||||||
|
# - MODE=dart DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||||
- MODE=saucelabs_required DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
- MODE=saucelabs_required DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||||
- MODE=browserstack_required DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
- MODE=browserstack_required DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||||
- MODE=saucelabs_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
- MODE=saucelabs_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||||
@ -51,7 +46,6 @@ env:
|
|||||||
- MODE=js DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
- MODE=js DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||||
- MODE=router DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
- MODE=router DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||||
- MODE=build_only DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION
|
- MODE=build_only DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION
|
||||||
- MODE=typescript_next DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION
|
|
||||||
- MODE=lint DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
- MODE=lint DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
|
||||||
- MODE=payload DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION
|
- MODE=payload DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION
|
||||||
|
|
||||||
@ -59,8 +53,8 @@ matrix:
|
|||||||
allow_failures:
|
allow_failures:
|
||||||
- env: "MODE=saucelabs_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
|
- env: "MODE=saucelabs_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
|
||||||
- env: "MODE=browserstack_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
|
- env: "MODE=browserstack_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
|
||||||
# Tracked in https://github.com/angular/angular/issues/7050
|
# TODO(alxhub): remove when dartdoc #1039 is in dev channel
|
||||||
- env: "MODE=typescript_next DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION"
|
- env: "MODE=dart DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
firefox: "38.0"
|
firefox: "38.0"
|
||||||
@ -70,8 +64,6 @@ before_install:
|
|||||||
- node tools/analytics/build-analytics start ci job
|
- node tools/analytics/build-analytics start ci job
|
||||||
- node tools/analytics/build-analytics start ci before_install
|
- node tools/analytics/build-analytics start ci before_install
|
||||||
- echo ${TSDRC} > .tsdrc
|
- echo ${TSDRC} > .tsdrc
|
||||||
- ./scripts/ci/install_chromium.sh
|
|
||||||
- export CHROME_BIN=$HOME/.chrome/chromium/chrome-linux/chrome
|
|
||||||
- export DISPLAY=:99.0
|
- export DISPLAY=:99.0
|
||||||
- export GIT_SHA=$(git rev-parse HEAD)
|
- export GIT_SHA=$(git rev-parse HEAD)
|
||||||
- ./scripts/ci/init_android.sh
|
- ./scripts/ci/init_android.sh
|
||||||
@ -116,7 +108,6 @@ notifications:
|
|||||||
- https://webhooks.gitter.im/e/1ef62e23078036f9cee4
|
- https://webhooks.gitter.im/e/1ef62e23078036f9cee4
|
||||||
# trigger Buildtime Trend Service to parse Travis CI log
|
# trigger Buildtime Trend Service to parse Travis CI log
|
||||||
- https://buildtimetrend.herokuapp.com/travis
|
- https://buildtimetrend.herokuapp.com/travis
|
||||||
- http://104.197.9.155:8484/hubot/travis/activity
|
|
||||||
on_success: always # options: [always|never|change] default: always
|
on_success: always # options: [always|never|change] default: always
|
||||||
on_failure: always # options: [always|never|change] default: always
|
on_failure: always # options: [always|never|change] default: always
|
||||||
on_start: false # default: false
|
on_start: false # default: false
|
||||||
|
188
CHANGELOG.md
188
CHANGELOG.md
@ -1,145 +1,3 @@
|
|||||||
<a name="2.0.0-beta.8"></a>
|
|
||||||
# 2.0.0-beta.8 (2016-03-02)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **angular1_router:** rename `$route` service to `$rootRouter` ([a1c3be2](https://github.com/angular/angular/commit/a1c3be2))
|
|
||||||
* **angular1_router:** rename `router` component binding to `$router` ([edad8e3](https://github.com/angular/angular/commit/edad8e3))
|
|
||||||
* **angular1_router:** support templateUrl components ([d4a4d81](https://github.com/angular/angular/commit/d4a4d81))
|
|
||||||
* **change_detection:** allow to destroy `OnPush` components inside of a host event. ([280b86e](https://github.com/angular/angular/commit/280b86e))
|
|
||||||
* **change_detection:** allow to destroy `OnPush` components inside of a host event. ([ebd438f](https://github.com/angular/angular/commit/ebd438f)), closes [#7192](https://github.com/angular/angular/issues/7192)
|
|
||||||
* **core:** support `ngFor` that has an `ngIf` as last node ([1779caf](https://github.com/angular/angular/commit/1779caf)), closes [#6304](https://github.com/angular/angular/issues/6304) [#6878](https://github.com/angular/angular/issues/6878)
|
|
||||||
* **dart/payload:** Fix runtime error in hello_world payload app ([eeb594c](https://github.com/angular/angular/commit/eeb594c)), closes [#7358](https://github.com/angular/angular/issues/7358)
|
|
||||||
* **differ:** clean up stale identity change refs ([ab36ea0](https://github.com/angular/angular/commit/ab36ea0)), closes [#7193](https://github.com/angular/angular/issues/7193)
|
|
||||||
* **DomRenderer:** correctly handle namespaced attributes ([c6afea6](https://github.com/angular/angular/commit/c6afea6))
|
|
||||||
* **Router:** Query strings are copied for HashLocationStrategy ([b47f80e](https://github.com/angular/angular/commit/b47f80e)), closes [#7298](https://github.com/angular/angular/issues/7298)
|
|
||||||
* **test:** fix a broken test ([9aedef2](https://github.com/angular/angular/commit/9aedef2))
|
|
||||||
* **transformers:** record reflection info about abstract classes ([05c185a](https://github.com/angular/angular/commit/05c185a)), closes [#7347](https://github.com/angular/angular/issues/7347)
|
|
||||||
* **transformers:** replace an error with a warning when cannot resolve a symbol ([ee3c580](https://github.com/angular/angular/commit/ee3c580))
|
|
||||||
* **transformers:** special case types some built-in types, so they can be resolved ([331b9c1](https://github.com/angular/angular/commit/331b9c1))
|
|
||||||
* **web_worker:** wait for bindings in kitchen sink spec ([4a93f58](https://github.com/angular/angular/commit/4a93f58))
|
|
||||||
* **web_workers:** make waitForElementText function more stable ([f6a8d04](https://github.com/angular/angular/commit/f6a8d04))
|
|
||||||
* **WebWorker:** Fix PostMessageBusSink and Source undefined error. ([01fe7f5](https://github.com/angular/angular/commit/01fe7f5)), closes [#7156](https://github.com/angular/angular/issues/7156)
|
|
||||||
* **WebWorker:** Make MessageBus EventEmitter synchronous ([69c1694](https://github.com/angular/angular/commit/69c1694))
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **core:** Add `QueryList.forEach` to public api. ([e7470d5](https://github.com/angular/angular/commit/e7470d5))
|
|
||||||
* **core:** Add `QueryList#forEach` ([b634a25](https://github.com/angular/angular/commit/b634a25))
|
|
||||||
* **core:** add more debug APIs to inspect the application form a browser ([b5e6319](https://github.com/angular/angular/commit/b5e6319)), closes [#7045](https://github.com/angular/angular/issues/7045) [#7161](https://github.com/angular/angular/issues/7161)
|
|
||||||
* **core:** drop `ChangeDetectionStrategy.OnPushObserve` ([f60fa14](https://github.com/angular/angular/commit/f60fa14))
|
|
||||||
* **di:** drop support for injecting types with generics in Dart ([c9a3df9](https://github.com/angular/angular/commit/c9a3df9)), closes [#7262](https://github.com/angular/angular/issues/7262)
|
|
||||||
* **forms/validators:** pattern validator ([38cb526](https://github.com/angular/angular/commit/38cb526)), closes [#5561](https://github.com/angular/angular/issues/5561)
|
|
||||||
* **i18n:** added i18nPlural and i18nSelect pipes ([59629a0](https://github.com/angular/angular/commit/59629a0)), closes [#7268](https://github.com/angular/angular/issues/7268)
|
|
||||||
* **pipes:** add ReplacePipe for string manipulation ([6ef2121](https://github.com/angular/angular/commit/6ef2121))
|
|
||||||
* **test:** add withProviders for per test providers ([c1a0af5](https://github.com/angular/angular/commit/c1a0af5)), closes [#5128](https://github.com/angular/angular/issues/5128)
|
|
||||||
* **transformers:** collect data needed for the template compiler ([ebe531b](https://github.com/angular/angular/commit/ebe531b)), closes [#7299](https://github.com/angular/angular/issues/7299)
|
|
||||||
* **transformers:** collect information for CompileDiDependencyMetadata ([39b6e0e](https://github.com/angular/angular/commit/39b6e0e))
|
|
||||||
* **transformers:** makes the map of resolved identifiers configurable ([0bb10d6](https://github.com/angular/angular/commit/0bb10d6)), closes [#7359](https://github.com/angular/angular/issues/7359)
|
|
||||||
|
|
||||||
|
|
||||||
### BREAKING CHANGES
|
|
||||||
|
|
||||||
* `OnPushObserve` was an experimental
|
|
||||||
feature for Dart and had
|
|
||||||
conceptual performance problems,
|
|
||||||
as setting up observables is slow.
|
|
||||||
Use `OnPush` instead.
|
|
||||||
|
|
||||||
* In Dart we used to support injecting types with generics. As this feature is hard to implement with the upcoming codegen we are dropping it.
|
|
||||||
Merge cl/115454020 in G3 with this change.
|
|
||||||
|
|
||||||
* The `$router` injectable service has been renamed to `$rootRouter`
|
|
||||||
|
|
||||||
* The recently added binding of the current router to the current component
|
|
||||||
has been renamed from `router` to `$router`.
|
|
||||||
So now the recommended set up for your bindings in your routed component
|
|
||||||
is:
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
...
|
|
||||||
bindings: {
|
|
||||||
$router: '<'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
<a name="2.0.0-beta.7"></a>
|
|
||||||
# 2.0.0-beta.7 (2016-02-18)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **angular_1_router:** Added DI string tokens ([3478d5d](https://github.com/angular/angular/commit/3478d5d)), closes [#4269](https://github.com/angular/angular/issues/4269) [#7031](https://github.com/angular/angular/issues/7031)
|
|
||||||
* **typing:** Remove re-export of the Promise built-in type. ([265703b](https://github.com/angular/angular/commit/265703b)), closes [#6468](https://github.com/angular/angular/issues/6468)
|
|
||||||
|
|
||||||
<a name="2.0.0-beta.6"></a>
|
|
||||||
# 2.0.0-beta.6 (2016-02-11)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **angular1-router:** add missing wrapper methods ([55122cd](https://github.com/angular/angular/commit/55122cd)), closes [#6763](https://github.com/angular/angular/issues/6763) [#6861](https://github.com/angular/angular/issues/6861) [#6861](https://github.com/angular/angular/issues/6861)
|
|
||||||
* **angular1-router:** add support for using the component helper ([d86be24](https://github.com/angular/angular/commit/d86be24)), closes [angular/angular.js#13860](https://github.com/angular/angular.js/issues/13860) [#6076](https://github.com/angular/angular/issues/6076) [#5278](https://github.com/angular/angular/issues/5278)
|
|
||||||
* **async:** handle synchronous initial value in async pipe ([26e60d6](https://github.com/angular/angular/commit/26e60d6)), closes [#5996](https://github.com/angular/angular/issues/5996)
|
|
||||||
* **build:** don't try to copy .d.ts files into the npm distro ([16b5217](https://github.com/angular/angular/commit/16b5217)), closes [#6921](https://github.com/angular/angular/issues/6921)
|
|
||||||
* **compiler:** fix interpolation regexp ([9b0e10e](https://github.com/angular/angular/commit/9b0e10e)), closes [#6056](https://github.com/angular/angular/issues/6056)
|
|
||||||
* **compiler:** use event names for matching directives ([231773e](https://github.com/angular/angular/commit/231773e)), closes [#6870](https://github.com/angular/angular/issues/6870)
|
|
||||||
* **core:** add detail to dehydrated detector exception ([e7ad03c](https://github.com/angular/angular/commit/e7ad03c)), closes [#6939](https://github.com/angular/angular/issues/6939)
|
|
||||||
* **core:** mute mode printing in console in prod mode ([74be3d3](https://github.com/angular/angular/commit/74be3d3)), closes [#6873](https://github.com/angular/angular/issues/6873)
|
|
||||||
* **di:** throw if a token uses more than 20 dependencies. ([de77700](https://github.com/angular/angular/commit/de77700)), closes [#6690](https://github.com/angular/angular/issues/6690) [#6869](https://github.com/angular/angular/issues/6869)
|
|
||||||
* **forms:** add RadioButtonValueAccessor to the list of default value accessors ([8f47aa3](https://github.com/angular/angular/commit/8f47aa3))
|
|
||||||
* **forms:** add support for radio buttons ([e725542](https://github.com/angular/angular/commit/e725542)), closes [#6877](https://github.com/angular/angular/issues/6877)
|
|
||||||
* **forms:** use strict runtimeType checks instead of instanceof ([50548fb](https://github.com/angular/angular/commit/50548fb)), closes [#6981](https://github.com/angular/angular/issues/6981)
|
|
||||||
* **Headers:** serializable toJSON ([b55f176](https://github.com/angular/angular/commit/b55f176)), closes [#6073](https://github.com/angular/angular/issues/6073) [#6714](https://github.com/angular/angular/issues/6714)
|
|
||||||
* **ngFor:** update view locals if identity changes ([0f10624](https://github.com/angular/angular/commit/0f10624)), closes [#6923](https://github.com/angular/angular/issues/6923)
|
|
||||||
* **router:** Added route data to normalized async route ([df7885c](https://github.com/angular/angular/commit/df7885c)), closes [#6802](https://github.com/angular/angular/issues/6802)
|
|
||||||
* **router:** don't prepend `/` unnecessarily to Location paths ([c603643](https://github.com/angular/angular/commit/c603643)), closes [#6729](https://github.com/angular/angular/issues/6729) [#5502](https://github.com/angular/angular/issues/5502)
|
|
||||||
* **router:** fix incorrect url param value coercion of 1 to true ([995a9e0](https://github.com/angular/angular/commit/995a9e0)), closes [#5346](https://github.com/angular/angular/issues/5346) [#6286](https://github.com/angular/angular/issues/6286)
|
|
||||||
* **router:** fix url path for star segment in path recognizer ([6f1ef33](https://github.com/angular/angular/commit/6f1ef33)), closes [#6976](https://github.com/angular/angular/issues/6976)
|
|
||||||
* **router:** fixed the location wrapper for angular1 ([e73fee7](https://github.com/angular/angular/commit/e73fee7)), closes [#6943](https://github.com/angular/angular/issues/6943)
|
|
||||||
* **typings:** Don't expose typing dependencies to users. ([2a70f4e](https://github.com/angular/angular/commit/2a70f4e)), closes [#5973](https://github.com/angular/angular/issues/5973) [#5807](https://github.com/angular/angular/issues/5807) [#6266](https://github.com/angular/angular/issues/6266) [#5242](https://github.com/angular/angular/issues/5242) [#6817](https://github.com/angular/angular/issues/6817) [#6267](https://github.com/angular/angular/issues/6267)
|
|
||||||
* **upgrade:** fix infinite $rootScope.$digest() ([7e0f02f](https://github.com/angular/angular/commit/7e0f02f)), closes [#6385](https://github.com/angular/angular/issues/6385) [#6386](https://github.com/angular/angular/issues/6386)
|
|
||||||
* **Validators:** fix Validators.required marking number zero as invalid ([c2ceb7f](https://github.com/angular/angular/commit/c2ceb7f)), closes [#6617](https://github.com/angular/angular/issues/6617)
|
|
||||||
* **WebWorkers:** Fix flaky WebWorker test ([da1fcfd](https://github.com/angular/angular/commit/da1fcfd)), closes [#6851](https://github.com/angular/angular/issues/6851)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **angular1_router:** allow component to bind to router ([0f22dce](https://github.com/angular/angular/commit/0f22dce))
|
|
||||||
* **typings:** install es6-shim typings to a location users can reference. ([f1f5b45](https://github.com/angular/angular/commit/f1f5b45))
|
|
||||||
|
|
||||||
### BREAKING CHANGES
|
|
||||||
|
|
||||||
Transitive typings are no longer included in the distribution.
|
|
||||||
|
|
||||||
If you use `--target=es5`, you will need to add a line somewhere in your
|
|
||||||
application (for example, at the top of the `.ts` file where you call `bootstrap`):
|
|
||||||
```
|
|
||||||
///<reference path="node_modules/angular2/typings/browser.d.ts"/>
|
|
||||||
```
|
|
||||||
(Note that if your file is not in the same directory as `node_modules`, you'll
|
|
||||||
need to add one or more `../` to the start of that path.)
|
|
||||||
|
|
||||||
If you have unit tests, you need to install typings in your project using
|
|
||||||
http://github.com/typings/typings
|
|
||||||
And install typings such as `jasmine`, `angular-protractor`, or `selenium-webdriver`
|
|
||||||
to satisfy the type-checker.
|
|
||||||
|
|
||||||
If you rely on es6 APIs other than Promises and Collections, you will need to
|
|
||||||
install the es6-shim typing instead of using the <reference> tag above.
|
|
||||||
Angular previously exposed typings for the entire ES6 API.
|
|
||||||
|
|
||||||
<a name="2.0.0-beta.5"></a>
|
|
||||||
# 2.0.0-beta.5 (2016-02-10)
|
|
||||||
|
|
||||||
This release was incorrect; replaced with beta.6.
|
|
||||||
|
|
||||||
<a name="2.0.0-beta.4"></a>
|
|
||||||
# 2.0.0-beta.4 (2016-02-10)
|
|
||||||
|
|
||||||
This release was incorrect; replaced with beta.6.
|
|
||||||
|
|
||||||
<a name="2.0.0-beta.3"></a>
|
<a name="2.0.0-beta.3"></a>
|
||||||
# 2.0.0-beta.3 (2016-02-03)
|
# 2.0.0-beta.3 (2016-02-03)
|
||||||
|
|
||||||
@ -169,52 +27,6 @@ This release was incorrect; replaced with beta.6.
|
|||||||
|
|
||||||
* **dart/transform:** Only process deferred libs when necessary ([f56df65](https://github.com/angular/angular/commit/f56df65)), closes [#6745](https://github.com/angular/angular/issues/6745)
|
* **dart/transform:** Only process deferred libs when necessary ([f56df65](https://github.com/angular/angular/commit/f56df65)), closes [#6745](https://github.com/angular/angular/issues/6745)
|
||||||
|
|
||||||
### BREAKING CHANGES
|
|
||||||
|
|
||||||
This is a breaking change for unit tests. The API for the DebugElement
|
|
||||||
has changed. Now, there is a DebugElement or DebugNode for every node
|
|
||||||
in the DOM, not only nodes with an ElementRef. `componentViewChildren` is
|
|
||||||
removed, and `childNodes` is a list of ElementNodes corresponding to every
|
|
||||||
child in the DOM. `query` no longer takes a scope parameter, since
|
|
||||||
the entire rendered DOM is included in the `childNodes`.
|
|
||||||
|
|
||||||
Before:
|
|
||||||
|
|
||||||
```
|
|
||||||
componentFixture.debugElement.componentViewChildren[0];
|
|
||||||
```
|
|
||||||
|
|
||||||
After
|
|
||||||
```
|
|
||||||
// Depending on the DOM structure of your component, the
|
|
||||||
// index may have changed or the first component child
|
|
||||||
// may be a sub-child.
|
|
||||||
componentFixture.debugElement.children[0];
|
|
||||||
```
|
|
||||||
|
|
||||||
Before:
|
|
||||||
|
|
||||||
```
|
|
||||||
debugElement.query(By.css('div'), Scope.all());
|
|
||||||
```
|
|
||||||
|
|
||||||
After:
|
|
||||||
|
|
||||||
```
|
|
||||||
debugElement.query(By.css('div'));
|
|
||||||
```
|
|
||||||
|
|
||||||
Before:
|
|
||||||
|
|
||||||
```
|
|
||||||
componentFixture.debugElement.elementRef;
|
|
||||||
```
|
|
||||||
|
|
||||||
After:
|
|
||||||
|
|
||||||
```
|
|
||||||
componentFixture.elementRef;
|
|
||||||
```
|
|
||||||
|
|
||||||
<a name="2.0.0-beta.2"></a>
|
<a name="2.0.0-beta.2"></a>
|
||||||
# 2.0.0-beta.2 (2016-01-28)
|
# 2.0.0-beta.2 (2016-01-28)
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
var CIconfiguration = {
|
var CIconfiguration = {
|
||||||
'Chrome': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
'Chrome': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
||||||
'Firefox': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
'Firefox': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
||||||
|
'ChromeBeta': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
||||||
'FirefoxBeta': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
'FirefoxBeta': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
||||||
'ChromeDev': { unitTest: {target: null, required: true}, e2e: {target: null, required: true}},
|
'ChromeDev': { unitTest: {target: null, required: true}, e2e: {target: null, required: true}},
|
||||||
'FirefoxDev': { unitTest: {target: null, required: true}, e2e: {target: null, required: true}},
|
'FirefoxDev': { unitTest: {target: null, required: true}, e2e: {target: null, required: true}},
|
||||||
|
@ -981,16 +981,15 @@ gulp.task('!pre.test.typings.layoutNodeModule', ['build.js.cjs'], function() {
|
|||||||
.pipe(gulp.dest(path.join(tmpdir, 'node_modules')));
|
.pipe(gulp.dest(path.join(tmpdir, 'node_modules')));
|
||||||
});
|
});
|
||||||
gulp.task('!pre.test.typings.copyTypingsSpec', function() {
|
gulp.task('!pre.test.typings.copyTypingsSpec', function() {
|
||||||
return gulp.src(['typing_spec/*.ts'], {base: 'typing_spec'}).pipe(gulp.dest(tmpdir));
|
return gulp.src(['typing_spec/*.ts'], {base: 'typing_spec'}).pipe(gulp.dest(path.join(tmpdir)));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test.typings',
|
gulp.task('test.typings',
|
||||||
['!pre.test.typings.layoutNodeModule', '!pre.test.typings.copyTypingsSpec'], function() {
|
['!pre.test.typings.layoutNodeModule', '!pre.test.typings.copyTypingsSpec'], function() {
|
||||||
var tsc = require('gulp-typescript');
|
var tsc = require('gulp-typescript');
|
||||||
|
|
||||||
return gulp.src([tmpdir + '/*.ts'])
|
return gulp.src([tmpdir + '/**'])
|
||||||
.pipe(tsc({
|
.pipe(tsc({
|
||||||
target: 'ES6',
|
target: 'ES5',
|
||||||
module: 'commonjs',
|
module: 'commonjs',
|
||||||
experimentalDecorators: true,
|
experimentalDecorators: true,
|
||||||
noImplicitAny: true,
|
noImplicitAny: true,
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
<script src="../../dist/angular_1_router.js"></script>
|
<script src="../../dist/angular_1_router.js"></script>
|
||||||
<script>
|
<script>
|
||||||
angular.module('myApp', ['ngComponentRouter'])
|
angular.module('myApp', ['ngComponentRouter'])
|
||||||
.controller('MyCtrl', ['$rootRouter', function ($rootRouter) {
|
.controller('MyCtrl', ['$router', function ($router) {
|
||||||
console.log($rootRouter);
|
console.log($router);
|
||||||
$rootRouter.navigateByUrl('/')
|
$router.navigateByUrl('/')
|
||||||
.then(console.log.bind(console, 'resolve'), console.log.bind(console, 'reject'));
|
.then(console.log.bind(console, 'resolve'), console.log.bind(console, 'reject'));
|
||||||
}]);
|
}]);
|
||||||
</script>
|
</script>
|
||||||
|
@ -173,10 +173,6 @@ var StringMapWrapper = {
|
|||||||
|
|
||||||
var List = Array;
|
var List = Array;
|
||||||
var ListWrapper = {
|
var ListWrapper = {
|
||||||
toJSON: function(l) {
|
|
||||||
return JSON.stringify(l);
|
|
||||||
},
|
|
||||||
|
|
||||||
clear: function (l) {
|
clear: function (l) {
|
||||||
l.length = 0;
|
l.length = 0;
|
||||||
},
|
},
|
||||||
@ -251,10 +247,6 @@ var ListWrapper = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var StringWrapper = {
|
var StringWrapper = {
|
||||||
charCodeAt: function(s, i) {
|
|
||||||
return s.charCodeAt(i);
|
|
||||||
},
|
|
||||||
|
|
||||||
equals: function (s1, s2) {
|
equals: function (s1, s2) {
|
||||||
return s1 === s2;
|
return s1 === s2;
|
||||||
},
|
},
|
||||||
@ -311,8 +303,8 @@ Location.prototype.subscribe = function () {
|
|||||||
//TODO: implement
|
//TODO: implement
|
||||||
};
|
};
|
||||||
Location.prototype.path = function () {
|
Location.prototype.path = function () {
|
||||||
return $location.url();
|
return $location.path();
|
||||||
};
|
};
|
||||||
Location.prototype.go = function (path, query) {
|
Location.prototype.go = function (url) {
|
||||||
return $location.url(path + query);
|
return $location.path(url);
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@ angular.module('ngComponentRouter').
|
|||||||
// Because Angular 1 has no notion of a root component, we use an object with unique identity
|
// Because Angular 1 has no notion of a root component, we use an object with unique identity
|
||||||
// to represent this. Can be overloaded with a component name
|
// to represent this. Can be overloaded with a component name
|
||||||
value('$routerRootComponent', new Object()).
|
value('$routerRootComponent', new Object()).
|
||||||
factory('$rootRouter', ['$q', '$location', '$$directiveIntrospector', '$browser', '$rootScope', '$injector', '$routerRootComponent', routerFactory]);
|
factory('$router', ['$q', '$location', '$$directiveIntrospector', '$browser', '$rootScope', '$injector', '$routerRootComponent', routerFactory]);
|
||||||
|
|
||||||
function routerFactory($q, $location, $$directiveIntrospector, $browser, $rootScope, $injector, $routerRootComponent) {
|
function routerFactory($q, $location, $$directiveIntrospector, $browser, $rootScope, $injector, $routerRootComponent) {
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ function routerFactory($q, $location, $$directiveIntrospector, $browser, $rootSc
|
|||||||
});
|
});
|
||||||
|
|
||||||
var router = new RootRouter(registry, location, $routerRootComponent);
|
var router = new RootRouter(registry, location, $routerRootComponent);
|
||||||
$rootScope.$watch(function () { return $location.url(); }, function (path) {
|
$rootScope.$watch(function () { return $location.path(); }, function (path) {
|
||||||
if (router.lastNavigationAttempt !== path) {
|
if (router.lastNavigationAttempt !== path) {
|
||||||
router.navigateByUrl(path);
|
router.navigateByUrl(path);
|
||||||
}
|
}
|
||||||
|
@ -61,8 +61,8 @@ class DirectiveIntrospectorProvider {
|
|||||||
*
|
*
|
||||||
* The value for the `ngOutlet` attribute is optional.
|
* The value for the `ngOutlet` attribute is optional.
|
||||||
*/
|
*/
|
||||||
function ngOutletDirective($animate, $q: ng.IQService, $rootRouter) {
|
function ngOutletDirective($animate, $q: ng.IQService, $router) {
|
||||||
let rootRouter = $rootRouter;
|
let rootRouter = $router;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
restrict: 'AE',
|
restrict: 'AE',
|
||||||
@ -145,7 +145,7 @@ function ngOutletDirective($animate, $q: ng.IQService, $rootRouter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
activate(instruction) {
|
activate(instruction) {
|
||||||
this.previousInstruction = this.currentInstruction;
|
let previousInstruction = this.currentInstruction;
|
||||||
this.currentInstruction = instruction;
|
this.currentInstruction = instruction;
|
||||||
|
|
||||||
let componentName = this.controller.$$componentName = instruction.componentType;
|
let componentName = this.controller.$$componentName = instruction.componentType;
|
||||||
@ -154,14 +154,11 @@ function ngOutletDirective($animate, $q: ng.IQService, $rootRouter) {
|
|||||||
throw new Error('Component is not a string for ' + instruction.urlPath);
|
throw new Error('Component is not a string for ' + instruction.urlPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.controller.$$template = '<' + dashCase(componentName) + ' $router="::$$router"></' +
|
this.controller.$$routeParams = instruction.params;
|
||||||
dashCase(componentName) + '>';
|
this.controller.$$template = '<div ' + dashCase(componentName) + '></div>';
|
||||||
this.controller.$$router = this.router.childRouter(instruction.componentType);
|
this.controller.$$router = this.router.childRouter(instruction.componentType);
|
||||||
this.controller.$$outlet = this;
|
|
||||||
|
|
||||||
let newScope = scope.$new();
|
let newScope = scope.$new();
|
||||||
newScope.$$router = this.controller.$$router;
|
|
||||||
this.deferredActivation = $q.defer();
|
|
||||||
|
|
||||||
let clone = $transclude(newScope, clone => {
|
let clone = $transclude(newScope, clone => {
|
||||||
$animate.enter(clone, null, this.currentElement || element);
|
$animate.enter(clone, null, this.currentElement || element);
|
||||||
@ -170,7 +167,15 @@ function ngOutletDirective($animate, $q: ng.IQService, $rootRouter) {
|
|||||||
|
|
||||||
this.currentElement = clone;
|
this.currentElement = clone;
|
||||||
this.currentScope = newScope;
|
this.currentScope = newScope;
|
||||||
return this.deferredActivation.promise;
|
|
||||||
|
// TODO: prefer the other directive retrieving the controller
|
||||||
|
// by debug mode
|
||||||
|
this.currentController = this.currentElement.children().eq(0).controller(componentName);
|
||||||
|
|
||||||
|
if (this.currentController && this.currentController.$routerOnActivate) {
|
||||||
|
return this.currentController.$routerOnActivate(instruction, previousInstruction);
|
||||||
|
}
|
||||||
|
return $q.when();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,32 +198,21 @@ function ngOutletFillContentDirective($compile) {
|
|||||||
link: (scope, element, attrs, ctrl) => {
|
link: (scope, element, attrs, ctrl) => {
|
||||||
let template = ctrl.$$template;
|
let template = ctrl.$$template;
|
||||||
element.html(template);
|
element.html(template);
|
||||||
$compile(element.contents())(scope);
|
let link = $compile(element.contents());
|
||||||
|
link(scope);
|
||||||
|
|
||||||
|
// TODO: move to primary directive
|
||||||
|
let componentInstance = scope[ctrl.$$componentName];
|
||||||
|
if (componentInstance) {
|
||||||
|
ctrl.$$currentComponent = componentInstance;
|
||||||
|
|
||||||
|
componentInstance.$router = ctrl.$$router;
|
||||||
|
componentInstance.$routeParams = ctrl.$$routeParams;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function routerTriggerDirective($q) {
|
|
||||||
return {
|
|
||||||
require: '^ngOutlet',
|
|
||||||
priority: -1000,
|
|
||||||
link: function(scope, element, attr, ngOutletCtrl) {
|
|
||||||
var promise = $q.when();
|
|
||||||
var outlet = ngOutletCtrl.$$outlet;
|
|
||||||
var currentComponent = outlet.currentController =
|
|
||||||
element.controller(ngOutletCtrl.$$componentName);
|
|
||||||
if (currentComponent.$routerOnActivate) {
|
|
||||||
promise = $q.when(currentComponent.$routerOnActivate(outlet.currentInstruction,
|
|
||||||
outlet.previousInstruction));
|
|
||||||
}
|
|
||||||
promise.then(outlet.deferredActivation.resolve, outlet.deferredActivation.reject);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name ngLink
|
* @name ngLink
|
||||||
* @description
|
* @description
|
||||||
@ -231,8 +225,8 @@ function routerTriggerDirective($q) {
|
|||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* angular.module('myApp', ['ngComponentRouter'])
|
* angular.module('myApp', ['ngComponentRouter'])
|
||||||
* .controller('AppController', ['$rootRouter', function($rootRouter) {
|
* .controller('AppController', ['$router', function($router) {
|
||||||
* $rootRouter.config({ path: '/user/:id', component: 'user' });
|
* $router.config({ path: '/user/:id', component: 'user' });
|
||||||
* this.user = { name: 'Brian', id: 123 };
|
* this.user = { name: 'Brian', id: 123 };
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
@ -243,11 +237,13 @@ function routerTriggerDirective($q) {
|
|||||||
* </div>
|
* </div>
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
function ngLinkDirective($rootRouter, $parse) {
|
function ngLinkDirective($router, $parse) {
|
||||||
|
let rootRouter = $router;
|
||||||
|
|
||||||
return {require: '?^^ngOutlet', restrict: 'A', link: ngLinkDirectiveLinkFn};
|
return {require: '?^^ngOutlet', restrict: 'A', link: ngLinkDirectiveLinkFn};
|
||||||
|
|
||||||
function ngLinkDirectiveLinkFn(scope, element, attrs, ctrl) {
|
function ngLinkDirectiveLinkFn(scope, element, attrs, ctrl) {
|
||||||
let router = (ctrl && ctrl.$$router) || $rootRouter;
|
let router = (ctrl && ctrl.$$router) || rootRouter;
|
||||||
if (!router) {
|
if (!router) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -275,7 +271,7 @@ function ngLinkDirective($rootRouter, $parse) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$rootRouter.navigateByInstruction(instruction);
|
$router.navigateByInstruction(instruction);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -289,14 +285,13 @@ function dashCase(str: string): string {
|
|||||||
* A module for adding new a routing system Angular 1.
|
* A module for adding new a routing system Angular 1.
|
||||||
*/
|
*/
|
||||||
angular.module('ngComponentRouter', [])
|
angular.module('ngComponentRouter', [])
|
||||||
.directive('ngOutlet', ['$animate', '$q', '$rootRouter', ngOutletDirective])
|
.directive('ngOutlet', ngOutletDirective)
|
||||||
.directive('ngOutlet', ['$compile', ngOutletFillContentDirective])
|
.directive('ngOutlet', ngOutletFillContentDirective)
|
||||||
.directive('ngLink', ['$rootRouter', '$parse', ngLinkDirective])
|
.directive('ngLink', ngLinkDirective);
|
||||||
.directive('$router', ['$q', routerTriggerDirective]);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A module for inspecting controller constructors
|
* A module for inspecting controller constructors
|
||||||
*/
|
*/
|
||||||
angular.module('ng')
|
angular.module('ng')
|
||||||
.provider('$$directiveIntrospector', DirectiveIntrospectorProvider)
|
.provider('$$directiveIntrospector', DirectiveIntrospectorProvider)
|
||||||
.config(['$compileProvider', '$$directiveIntrospectorProvider', compilerProviderDecorator]);
|
.config(compilerProviderDecorator);
|
||||||
|
54
modules/angular1_router/src/ng_route_shim.js
vendored
54
modules/angular1_router/src/ng_route_shim.js
vendored
@ -1,4 +1,4 @@
|
|||||||
/** @license Copyright 2014-2016 Google, Inc. http://github.com/angular/angular/LICENSE */
|
/** @license Copyright 2014-2015 Google, Inc. http://github.com/angular/angular/LICENSE */
|
||||||
(function () {
|
(function () {
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
@ -24,12 +24,12 @@
|
|||||||
.directive('a', anchorLinkDirective)
|
.directive('a', anchorLinkDirective)
|
||||||
|
|
||||||
// Connects the legacy $routeProvider config shim to Component Router's config.
|
// Connects the legacy $routeProvider config shim to Component Router's config.
|
||||||
.run(['$route', '$rootRouter', function ($route, $rootRouter) {
|
.run(['$route', '$router', function ($route, $router) {
|
||||||
$route.$$subscribe(function (routeDefinition) {
|
$route.$$subscribe(function (routeDefinition) {
|
||||||
if (!angular.isArray(routeDefinition)) {
|
if (!angular.isArray(routeDefinition)) {
|
||||||
routeDefinition = [routeDefinition];
|
routeDefinition = [routeDefinition];
|
||||||
}
|
}
|
||||||
$rootRouter.config(routeDefinition);
|
$router.config(routeDefinition);
|
||||||
});
|
});
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
@ -116,41 +116,53 @@
|
|||||||
console.warn('Route for "' + path + '" should use "controllerAs".');
|
console.warn('Route for "' + path + '" should use "controllerAs".');
|
||||||
}
|
}
|
||||||
|
|
||||||
var componentName = routeObjToRouteName(routeCopy, path);
|
var directiveName = routeObjToRouteName(routeCopy, path);
|
||||||
|
|
||||||
if (!componentName) {
|
if (!directiveName) {
|
||||||
throw new Error('Could not determine a name for route "' + path + '".');
|
throw new Error('Could not determine a name for route "' + path + '".');
|
||||||
}
|
}
|
||||||
|
|
||||||
routeDefinition.component = componentName;
|
routeDefinition.component = directiveName;
|
||||||
routeDefinition.name = route.name || upperCase(componentName);
|
routeDefinition.name = route.name || upperCase(directiveName);
|
||||||
|
|
||||||
var directiveController = routeCopy.controller;
|
var directiveController = routeCopy.controller;
|
||||||
|
|
||||||
var componentDefinition = {
|
var directiveDefinition = {
|
||||||
|
scope: false,
|
||||||
controller: directiveController,
|
controller: directiveController,
|
||||||
controllerAs: routeCopy.controllerAs
|
controllerAs: routeCopy.controllerAs,
|
||||||
|
templateUrl: routeCopy.templateUrl,
|
||||||
|
template: routeCopy.template
|
||||||
};
|
};
|
||||||
if (routeCopy.templateUrl) componentDefinition.templateUrl = routeCopy.templateUrl;
|
|
||||||
if (routeCopy.template) componentDefinition.template = routeCopy.template;
|
|
||||||
|
|
||||||
|
var directiveFactory = function () {
|
||||||
|
return directiveDefinition;
|
||||||
|
};
|
||||||
|
|
||||||
// if we have route resolve options, prepare a wrapper controller
|
// if we have route resolve options, prepare a wrapper controller
|
||||||
if (directiveController && routeCopy.resolve) {
|
if (directiveController && routeCopy.resolve) {
|
||||||
var originalController = directiveController;
|
var originalController = directiveController;
|
||||||
var resolvedLocals = {};
|
var resolvedLocals = {};
|
||||||
|
|
||||||
componentDefinition.controller = ['$injector', '$scope', function ($injector, $scope) {
|
directiveDefinition.controller = ['$injector', '$scope', function ($injector, $scope) {
|
||||||
var locals = angular.extend({
|
var locals = angular.extend({
|
||||||
$scope: $scope
|
$scope: $scope
|
||||||
}, resolvedLocals);
|
}, resolvedLocals);
|
||||||
|
|
||||||
return $injector.instantiate(originalController, locals);
|
var ctrl = $injector.instantiate(originalController, locals);
|
||||||
|
|
||||||
|
if (routeCopy.controllerAs) {
|
||||||
|
locals.$scope[routeCopy.controllerAs] = ctrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctrl;
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
// we take care of controllerAs in the directive controller wrapper
|
||||||
|
delete directiveDefinition.controllerAs;
|
||||||
|
|
||||||
// we resolve the locals in a canActivate block
|
// we resolve the locals in a canActivate block
|
||||||
componentDefinition.$canActivate = function() {
|
directiveFactory.$canActivate = function() {
|
||||||
var locals = angular.extend({}, routeCopy.resolve);
|
var locals = angular.extend({}, routeCopy.resolve);
|
||||||
|
|
||||||
angular.forEach(locals, function(value, key) {
|
angular.forEach(locals, function(value, key) {
|
||||||
@ -167,7 +179,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// register the dynamically created directive
|
// register the dynamically created directive
|
||||||
$compileProvider.component(componentName, componentDefinition);
|
$compileProvider.directive(directiveName, directiveFactory);
|
||||||
}
|
}
|
||||||
if (subscriptionFn) {
|
if (subscriptionFn) {
|
||||||
subscriptionFn(routeDefinition);
|
subscriptionFn(routeDefinition);
|
||||||
@ -241,12 +253,12 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function $routeParamsFactory($rootRouter, $rootScope) {
|
function $routeParamsFactory($router, $rootScope) {
|
||||||
// the identity of this object cannot change
|
// the identity of this object cannot change
|
||||||
var paramsObj = {};
|
var paramsObj = {};
|
||||||
|
|
||||||
$rootScope.$on('$routeChangeSuccess', function () {
|
$rootScope.$on('$routeChangeSuccess', function () {
|
||||||
var newParams = $rootRouter._currentInstruction && $rootRouter._currentInstruction.component.params;
|
var newParams = $router._currentInstruction && $router._currentInstruction.component.params;
|
||||||
|
|
||||||
angular.forEach(paramsObj, function (val, name) {
|
angular.forEach(paramsObj, function (val, name) {
|
||||||
delete paramsObj[name];
|
delete paramsObj[name];
|
||||||
@ -262,7 +274,7 @@
|
|||||||
/**
|
/**
|
||||||
* Allows normal anchor links to kick off routing.
|
* Allows normal anchor links to kick off routing.
|
||||||
*/
|
*/
|
||||||
function anchorLinkDirective($rootRouter) {
|
function anchorLinkDirective($router) {
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
link: function (scope, element) {
|
link: function (scope, element) {
|
||||||
@ -281,8 +293,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var href = element.attr(hrefAttrName);
|
var href = element.attr(hrefAttrName);
|
||||||
if (href && $rootRouter.recognize(href)) {
|
if (href && $router.recognize(href)) {
|
||||||
$rootRouter.navigateByUrl(href);
|
$router.navigateByUrl(href);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -5,7 +5,7 @@ describe('ngOutlet animations', function () {
|
|||||||
$animate,
|
$animate,
|
||||||
$compile,
|
$compile,
|
||||||
$rootScope,
|
$rootScope,
|
||||||
$rootRouter,
|
$router,
|
||||||
$compileProvider;
|
$compileProvider;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
@ -17,18 +17,15 @@ describe('ngOutlet animations', function () {
|
|||||||
$compileProvider = _$compileProvider_;
|
$compileProvider = _$compileProvider_;
|
||||||
});
|
});
|
||||||
|
|
||||||
inject(function (_$animate_, _$compile_, _$rootScope_, _$rootRouter_) {
|
inject(function (_$animate_, _$compile_, _$rootScope_, _$router_) {
|
||||||
$animate = _$animate_;
|
$animate = _$animate_;
|
||||||
$compile = _$compile_;
|
$compile = _$compile_;
|
||||||
$rootScope = _$rootScope_;
|
$rootScope = _$rootScope_;
|
||||||
$rootRouter = _$rootRouter_;
|
$router = _$router_;
|
||||||
});
|
});
|
||||||
|
|
||||||
registerComponent('userCmp', {
|
registerComponent('userCmp', {
|
||||||
template: '<div>hello {{userCmp.$routeParams.name}}</div>',
|
template: '<div>hello {{userCmp.$routeParams.name}}</div>'
|
||||||
$routerOnActivate: function(next) {
|
|
||||||
this.$routeParams = next.params;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -41,11 +38,11 @@ describe('ngOutlet animations', function () {
|
|||||||
|
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/user/:name', component: 'userCmp' }
|
{ path: '/user/:name', component: 'userCmp' }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/user/brian');
|
$router.navigateByUrl('/user/brian');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('hello brian');
|
expect(elt.text()).toBe('hello brian');
|
||||||
|
|
||||||
@ -54,7 +51,7 @@ describe('ngOutlet animations', function () {
|
|||||||
expect(item.event).toBe('enter');
|
expect(item.event).toBe('enter');
|
||||||
|
|
||||||
// navigate to pete
|
// navigate to pete
|
||||||
$rootRouter.navigateByUrl('/user/pete');
|
$router.navigateByUrl('/user/pete');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('hello pete');
|
expect(elt.text()).toBe('hello pete');
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ describe('Navigation lifecycle', function () {
|
|||||||
var elt,
|
var elt,
|
||||||
$compile,
|
$compile,
|
||||||
$rootScope,
|
$rootScope,
|
||||||
$rootRouter,
|
$router,
|
||||||
$compileProvider;
|
$compileProvider;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
@ -14,10 +14,10 @@ describe('Navigation lifecycle', function () {
|
|||||||
$compileProvider = _$compileProvider_;
|
$compileProvider = _$compileProvider_;
|
||||||
});
|
});
|
||||||
|
|
||||||
inject(function (_$compile_, _$rootScope_, _$rootRouter_) {
|
inject(function (_$compile_, _$rootScope_, _$router_) {
|
||||||
$compile = _$compile_;
|
$compile = _$compile_;
|
||||||
$rootScope = _$rootScope_;
|
$rootScope = _$rootScope_;
|
||||||
$rootRouter = _$rootRouter_;
|
$router = _$router_;
|
||||||
});
|
});
|
||||||
|
|
||||||
registerComponent('oneCmp', {
|
registerComponent('oneCmp', {
|
||||||
@ -38,12 +38,12 @@ describe('Navigation lifecycle', function () {
|
|||||||
$routerOnActivate: spy
|
$routerOnActivate: spy
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/a', component: 'activateCmp' }
|
{ path: '/a', component: 'activateCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<div>outer { <div ng-outlet></div> }</div>');
|
compile('<div>outer { <div ng-outlet></div> }</div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/a');
|
$router.navigateByUrl('/a');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled();
|
||||||
@ -56,12 +56,12 @@ describe('Navigation lifecycle', function () {
|
|||||||
$routerOnActivate: spy
|
$routerOnActivate: spy
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/user/:name', component: 'userCmp' }
|
{ path: '/user/:name', component: 'userCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/user/brian');
|
$router.navigateByUrl('/user/brian');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalledWith(instructionFor('userCmp'), undefined);
|
expect(spy).toHaveBeenCalledWith(instructionFor('userCmp'), undefined);
|
||||||
@ -75,15 +75,15 @@ describe('Navigation lifecycle', function () {
|
|||||||
$routerOnActivate: spy
|
$routerOnActivate: spy
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/user/:name', component: 'oneCmp' },
|
{ path: '/user/:name', component: 'oneCmp' },
|
||||||
{ path: '/post/:id', component: 'activateCmp' }
|
{ path: '/post/:id', component: 'activateCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/user/brian');
|
$router.navigateByUrl('/user/brian');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
$rootRouter.navigateByUrl('/post/123');
|
$router.navigateByUrl('/post/123');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(spy).toHaveBeenCalledWith(instructionFor('activateCmp'),
|
expect(spy).toHaveBeenCalledWith(instructionFor('activateCmp'),
|
||||||
instructionFor('oneCmp'));
|
instructionFor('oneCmp'));
|
||||||
@ -98,12 +98,12 @@ describe('Navigation lifecycle', function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/user', component: 'userCmp' }
|
{ path: '/user', component: 'userCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/user');
|
$router.navigateByUrl('/user');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(injectedScope).toBeDefined();
|
expect(injectedScope).toBeDefined();
|
||||||
@ -116,15 +116,15 @@ describe('Navigation lifecycle', function () {
|
|||||||
$routerOnDeactivate: spy
|
$routerOnDeactivate: spy
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/a', component: 'deactivateCmp' },
|
{ path: '/a', component: 'deactivateCmp' },
|
||||||
{ path: '/b', component: 'oneCmp' }
|
{ path: '/b', component: 'oneCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/a');
|
$router.navigateByUrl('/a');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
$rootRouter.navigateByUrl('/b');
|
$router.navigateByUrl('/b');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@ -136,15 +136,15 @@ describe('Navigation lifecycle', function () {
|
|||||||
$routerOnDeactivate: spy
|
$routerOnDeactivate: spy
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/user/:name', component: 'deactivateCmp' },
|
{ path: '/user/:name', component: 'deactivateCmp' },
|
||||||
{ path: '/post/:id', component: 'oneCmp' }
|
{ path: '/post/:id', component: 'oneCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/user/brian');
|
$router.navigateByUrl('/user/brian');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
$rootRouter.navigateByUrl('/post/123');
|
$router.navigateByUrl('/post/123');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(spy).toHaveBeenCalledWith(instructionFor('oneCmp'),
|
expect(spy).toHaveBeenCalledWith(instructionFor('oneCmp'),
|
||||||
instructionFor('deactivateCmp'));
|
instructionFor('deactivateCmp'));
|
||||||
@ -166,15 +166,15 @@ describe('Navigation lifecycle', function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/a', component: 'deactivateCmp' },
|
{ path: '/a', component: 'deactivateCmp' },
|
||||||
{ path: '/b', component: 'activateCmp' }
|
{ path: '/b', component: 'activateCmp' }
|
||||||
]);
|
]);
|
||||||
compile('outer { <div ng-outlet></div> }');
|
compile('outer { <div ng-outlet></div> }');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/a');
|
$router.navigateByUrl('/a');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
$rootRouter.navigateByUrl('/b');
|
$router.navigateByUrl('/b');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(log).toEqual(['deactivate', 'activate']);
|
expect(log).toEqual(['deactivate', 'activate']);
|
||||||
@ -203,19 +203,19 @@ describe('Navigation lifecycle', function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/on-reuse/:number/...', component: 'reuseCmp' },
|
{ path: '/on-reuse/:number/...', component: 'reuseCmp' },
|
||||||
{ path: '/two', component: 'twoCmp', name: 'Two'}
|
{ path: '/two', component: 'twoCmp', name: 'Two'}
|
||||||
]);
|
]);
|
||||||
compile('outer { <div ng-outlet></div> }');
|
compile('outer { <div ng-outlet></div> }');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/on-reuse/1/a');
|
$router.navigateByUrl('/on-reuse/1/a');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(log).toEqual([]);
|
expect(log).toEqual([]);
|
||||||
expect(cmpInstanceCount).toBe(1);
|
expect(cmpInstanceCount).toBe(1);
|
||||||
expect(elt.text()).toBe('outer { reuse {one} }');
|
expect(elt.text()).toBe('outer { reuse {one} }');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/on-reuse/2/b');
|
$router.navigateByUrl('/on-reuse/2/b');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(log).toEqual(['reuse: on-reuse/1 -> on-reuse/2']);
|
expect(log).toEqual(['reuse: on-reuse/1 -> on-reuse/2']);
|
||||||
expect(cmpInstanceCount).toBe(1);
|
expect(cmpInstanceCount).toBe(1);
|
||||||
@ -245,19 +245,19 @@ describe('Navigation lifecycle', function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/never-reuse/:number/...', component: 'reuseCmp' },
|
{ path: '/never-reuse/:number/...', component: 'reuseCmp' },
|
||||||
{ path: '/two', component: 'twoCmp', name: 'Two'}
|
{ path: '/two', component: 'twoCmp', name: 'Two'}
|
||||||
]);
|
]);
|
||||||
compile('outer { <div ng-outlet></div> }');
|
compile('outer { <div ng-outlet></div> }');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/never-reuse/1/a');
|
$router.navigateByUrl('/never-reuse/1/a');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(log).toEqual([]);
|
expect(log).toEqual([]);
|
||||||
expect(cmpInstanceCount).toBe(1);
|
expect(cmpInstanceCount).toBe(1);
|
||||||
expect(elt.text()).toBe('outer { reuse {one} }');
|
expect(elt.text()).toBe('outer { reuse {one} }');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/never-reuse/2/b');
|
$router.navigateByUrl('/never-reuse/2/b');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(log).toEqual([]);
|
expect(log).toEqual([]);
|
||||||
expect(cmpInstanceCount).toBe(2);
|
expect(cmpInstanceCount).toBe(2);
|
||||||
@ -274,12 +274,12 @@ describe('Navigation lifecycle', function () {
|
|||||||
$routerOnActivate: spy
|
$routerOnActivate: spy
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/a', component: 'activateCmp' }
|
{ path: '/a', component: 'activateCmp' }
|
||||||
]);
|
]);
|
||||||
compile('outer { <div ng-outlet></div> }');
|
compile('outer { <div ng-outlet></div> }');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/a');
|
$router.navigateByUrl('/a');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(spy).not.toHaveBeenCalled();
|
expect(spy).not.toHaveBeenCalled();
|
||||||
@ -296,12 +296,12 @@ describe('Navigation lifecycle', function () {
|
|||||||
$routerOnActivate: activateSpy
|
$routerOnActivate: activateSpy
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/a', component: 'activateCmp' }
|
{ path: '/a', component: 'activateCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/a');
|
$router.navigateByUrl('/a');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(canActivateSpy).toHaveBeenCalled();
|
expect(canActivateSpy).toHaveBeenCalled();
|
||||||
@ -320,12 +320,12 @@ describe('Navigation lifecycle', function () {
|
|||||||
$routerOnActivate: spy
|
$routerOnActivate: spy
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/a', component: 'activateCmp' }
|
{ path: '/a', component: 'activateCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/a');
|
$router.navigateByUrl('/a');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled();
|
||||||
@ -341,12 +341,12 @@ describe('Navigation lifecycle', function () {
|
|||||||
|
|
||||||
spy.$inject = ['$nextInstruction', '$http'];
|
spy.$inject = ['$nextInstruction', '$http'];
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/user/:name', component: 'activateCmp' }
|
{ path: '/user/:name', component: 'activateCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/user/brian');
|
$router.navigateByUrl('/user/brian');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled();
|
||||||
@ -364,17 +364,17 @@ describe('Navigation lifecycle', function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/a', component: 'activateCmp' },
|
{ path: '/a', component: 'activateCmp' },
|
||||||
{ path: '/b', component: 'oneCmp' }
|
{ path: '/b', component: 'oneCmp' }
|
||||||
]);
|
]);
|
||||||
compile('outer { <div ng-outlet></div> }');
|
compile('outer { <div ng-outlet></div> }');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/a');
|
$router.navigateByUrl('/a');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('outer { hi }');
|
expect(elt.text()).toBe('outer { hi }');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/b');
|
$router.navigateByUrl('/b');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('outer { hi }');
|
expect(elt.text()).toBe('outer { hi }');
|
||||||
});
|
});
|
||||||
@ -388,17 +388,17 @@ describe('Navigation lifecycle', function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/a', component: 'activateCmp' },
|
{ path: '/a', component: 'activateCmp' },
|
||||||
{ path: '/b', component: 'oneCmp' }
|
{ path: '/b', component: 'oneCmp' }
|
||||||
]);
|
]);
|
||||||
compile('outer { <div ng-outlet></div> }');
|
compile('outer { <div ng-outlet></div> }');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/a');
|
$router.navigateByUrl('/a');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('outer { hi }');
|
expect(elt.text()).toBe('outer { hi }');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/b');
|
$router.navigateByUrl('/b');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('outer { one }');
|
expect(elt.text()).toBe('outer { one }');
|
||||||
});
|
});
|
||||||
@ -414,12 +414,12 @@ describe('Navigation lifecycle', function () {
|
|||||||
$routerOnActivate: spy
|
$routerOnActivate: spy
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/a', component: 'activateCmp' }
|
{ path: '/a', component: 'activateCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/a');
|
$router.navigateByUrl('/a');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled();
|
||||||
@ -433,15 +433,15 @@ describe('Navigation lifecycle', function () {
|
|||||||
$routerCanDeactivate: spy
|
$routerCanDeactivate: spy
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/user/:name', component: 'deactivateCmp' },
|
{ path: '/user/:name', component: 'deactivateCmp' },
|
||||||
{ path: '/post/:id', component: 'oneCmp' }
|
{ path: '/post/:id', component: 'oneCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/user/brian');
|
$router.navigateByUrl('/user/brian');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
$rootRouter.navigateByUrl('/post/123');
|
$router.navigateByUrl('/post/123');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(spy).toHaveBeenCalledWith(instructionFor('oneCmp'),
|
expect(spy).toHaveBeenCalledWith(instructionFor('oneCmp'),
|
||||||
instructionFor('deactivateCmp'));
|
instructionFor('deactivateCmp'));
|
||||||
|
@ -5,7 +5,7 @@ describe('navigation', function () {
|
|||||||
var elt,
|
var elt,
|
||||||
$compile,
|
$compile,
|
||||||
$rootScope,
|
$rootScope,
|
||||||
$rootRouter,
|
$router,
|
||||||
$compileProvider;
|
$compileProvider;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
@ -15,79 +15,49 @@ describe('navigation', function () {
|
|||||||
$compileProvider = _$compileProvider_;
|
$compileProvider = _$compileProvider_;
|
||||||
});
|
});
|
||||||
|
|
||||||
inject(function (_$compile_, _$rootScope_, _$rootRouter_) {
|
inject(function (_$compile_, _$rootScope_, _$router_) {
|
||||||
$compile = _$compile_;
|
$compile = _$compile_;
|
||||||
$rootScope = _$rootScope_;
|
$rootScope = _$rootScope_;
|
||||||
$rootRouter = _$rootRouter_;
|
$router = _$router_;
|
||||||
});
|
});
|
||||||
|
|
||||||
registerDirective('userCmp', {
|
registerComponent('userCmp', {
|
||||||
template: '<div>hello {{userCmp.$routeParams.name}}</div>',
|
template: '<div>hello {{userCmp.$routeParams.name}}</div>'
|
||||||
$routerOnActivate: function(next) {
|
|
||||||
this.$routeParams = next.params;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
registerDirective('oneCmp', {
|
registerComponent('oneCmp', {
|
||||||
template: '<div>{{oneCmp.number}}</div>',
|
template: '<div>{{oneCmp.number}}</div>',
|
||||||
controller: function () {this.number = 'one'}
|
controller: function () {this.number = 'one'}
|
||||||
});
|
});
|
||||||
registerDirective('twoCmp', {
|
registerComponent('twoCmp', {
|
||||||
template: '<div>{{twoCmp.number}}</div>',
|
template: '<div>{{twoCmp.number}}</div>',
|
||||||
controller: function () {this.number = 'two'}
|
controller: function () {this.number = 'two'}
|
||||||
});
|
});
|
||||||
registerComponent('threeCmp', {
|
|
||||||
template: '<div>{{$ctrl.number}}</div>',
|
|
||||||
controller: function () {this.number = 'three'}
|
|
||||||
});
|
|
||||||
registerComponent('getParams', {
|
|
||||||
template: '<div>{{$ctrl.params.x}}</div>',
|
|
||||||
controller: function () {
|
|
||||||
this.$routerOnActivate = function(next) {
|
|
||||||
this.params = next.params;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work in a simple case', function () {
|
it('should work in a simple case', function () {
|
||||||
compile('<ng-outlet></ng-outlet>');
|
compile('<ng-outlet></ng-outlet>');
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/', component: 'oneCmp' }
|
{ path: '/', component: 'oneCmp' }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/');
|
$router.navigateByUrl('/');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(elt.text()).toBe('one');
|
expect(elt.text()).toBe('one');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should work with components created by the `mod.component()` helper', function () {
|
|
||||||
compile('<ng-outlet></ng-outlet>');
|
|
||||||
|
|
||||||
$rootRouter.config([
|
|
||||||
{ path: '/', component: 'threeCmp' }
|
|
||||||
]);
|
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/');
|
|
||||||
$rootScope.$digest();
|
|
||||||
|
|
||||||
expect(elt.text()).toBe('three');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should navigate between components with different parameters', function () {
|
it('should navigate between components with different parameters', function () {
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/user/:name', component: 'userCmp' }
|
{ path: '/user/:name', component: 'userCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<ng-outlet></ng-outlet>');
|
compile('<ng-outlet></ng-outlet>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/user/brian');
|
$router.navigateByUrl('/user/brian');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('hello brian');
|
expect(elt.text()).toBe('hello brian');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/user/igor');
|
$router.navigateByUrl('/user/igor');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('hello igor');
|
expect(elt.text()).toBe('hello igor');
|
||||||
});
|
});
|
||||||
@ -98,7 +68,7 @@ describe('navigation', function () {
|
|||||||
function ParentController() {
|
function ParentController() {
|
||||||
instanceCount += 1;
|
instanceCount += 1;
|
||||||
}
|
}
|
||||||
registerDirective('parentCmp', {
|
registerComponent('parentCmp', {
|
||||||
template: 'parent { <ng-outlet></ng-outlet> }',
|
template: 'parent { <ng-outlet></ng-outlet> }',
|
||||||
$routeConfig: [
|
$routeConfig: [
|
||||||
{ path: '/user/:name', component: 'userCmp' }
|
{ path: '/user/:name', component: 'userCmp' }
|
||||||
@ -106,17 +76,17 @@ describe('navigation', function () {
|
|||||||
controller: ParentController
|
controller: ParentController
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/parent/...', component: 'parentCmp' }
|
{ path: '/parent/...', component: 'parentCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<ng-outlet></ng-outlet>');
|
compile('<ng-outlet></ng-outlet>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/parent/user/brian');
|
$router.navigateByUrl('/parent/user/brian');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(instanceCount).toBe(1);
|
expect(instanceCount).toBe(1);
|
||||||
expect(elt.text()).toBe('parent { hello brian }');
|
expect(elt.text()).toBe('parent { hello brian }');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/parent/user/igor');
|
$router.navigateByUrl('/parent/user/igor');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(instanceCount).toBe(1);
|
expect(instanceCount).toBe(1);
|
||||||
expect(elt.text()).toBe('parent { hello igor }');
|
expect(elt.text()).toBe('parent { hello igor }');
|
||||||
@ -124,25 +94,6 @@ describe('navigation', function () {
|
|||||||
|
|
||||||
|
|
||||||
it('should work with nested outlets', function () {
|
it('should work with nested outlets', function () {
|
||||||
registerDirective('childCmp', {
|
|
||||||
template: '<div>inner { <div ng-outlet></div> }</div>',
|
|
||||||
$routeConfig: [
|
|
||||||
{ path: '/b', component: 'oneCmp' }
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootRouter.config([
|
|
||||||
{ path: '/a/...', component: 'childCmp' }
|
|
||||||
]);
|
|
||||||
compile('<div>outer { <div ng-outlet></div> }</div>');
|
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/a/b');
|
|
||||||
$rootScope.$digest();
|
|
||||||
|
|
||||||
expect(elt.text()).toBe('outer { inner { one } }');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work when parent route has empty path', inject(function ($location) {
|
|
||||||
registerComponent('childCmp', {
|
registerComponent('childCmp', {
|
||||||
template: '<div>inner { <div ng-outlet></div> }</div>',
|
template: '<div>inner { <div ng-outlet></div> }</div>',
|
||||||
$routeConfig: [
|
$routeConfig: [
|
||||||
@ -150,77 +101,61 @@ describe('navigation', function () {
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/...', component: 'childCmp' }
|
{ path: '/a/...', component: 'childCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<div>outer { <div ng-outlet></div> }</div>');
|
compile('<div>outer { <div ng-outlet></div> }</div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/b');
|
$router.navigateByUrl('/a/b');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(elt.text()).toBe('outer { inner { one } }');
|
expect(elt.text()).toBe('outer { inner { one } }');
|
||||||
expect($location.path()).toBe('/b');
|
});
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should work with recursive nested outlets', function () {
|
it('should work with recursive nested outlets', function () {
|
||||||
registerDirective('recurCmp', {
|
registerComponent('recurCmp', {
|
||||||
template: '<div>recur { <div ng-outlet></div> }</div>',
|
template: '<div>recur { <div ng-outlet></div> }</div>',
|
||||||
$routeConfig: [
|
$routeConfig: [
|
||||||
{ path: '/recur', component: 'recurCmp' },
|
{ path: '/recur', component: 'recurCmp' },
|
||||||
{ path: '/end', component: 'oneCmp' }
|
{ path: '/end', component: 'oneCmp' }
|
||||||
]});
|
]});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/recur', component: 'recurCmp' },
|
{ path: '/recur', component: 'recurCmp' },
|
||||||
{ path: '/', component: 'oneCmp' }
|
{ path: '/', component: 'oneCmp' }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
compile('<div>root { <div ng-outlet></div> }</div>');
|
compile('<div>root { <div ng-outlet></div> }</div>');
|
||||||
$rootRouter.navigateByUrl('/recur/recur/end');
|
$router.navigateByUrl('/recur/recur/end');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('root { one }');
|
expect(elt.text()).toBe('root { one }');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should change location path', inject(function ($location) {
|
it('should change location path', inject(function ($location) {
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/user', component: 'userCmp' }
|
{ path: '/user', component: 'userCmp' }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/user');
|
$router.navigateByUrl('/user');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect($location.path()).toBe('/user');
|
expect($location.path()).toBe('/user');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
it('should pass through query terms to the location', inject(function ($location) {
|
|
||||||
$rootRouter.config([
|
|
||||||
{ path: '/user', component: 'userCmp' }
|
|
||||||
]);
|
|
||||||
|
|
||||||
compile('<div ng-outlet></div>');
|
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/user?x=y');
|
|
||||||
$rootScope.$digest();
|
|
||||||
|
|
||||||
expect($location.path()).toBe('/user');
|
|
||||||
expect($location.search()).toEqual({ x: 'y'});
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should change location to the canonical route', inject(function ($location) {
|
it('should change location to the canonical route', inject(function ($location) {
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/', redirectTo: ['/User'] },
|
{ path: '/', redirectTo: ['/User'] },
|
||||||
{ path: '/user', component: 'userCmp', name: 'User' }
|
{ path: '/user', component: 'userCmp', name: 'User' }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/');
|
$router.navigateByUrl('/');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect($location.path()).toBe('/user');
|
expect($location.path()).toBe('/user');
|
||||||
@ -228,7 +163,7 @@ describe('navigation', function () {
|
|||||||
|
|
||||||
|
|
||||||
it('should change location to the canonical route with nested components', inject(function ($location) {
|
it('should change location to the canonical route with nested components', inject(function ($location) {
|
||||||
registerDirective('childRouter', {
|
registerComponent('childRouter', {
|
||||||
template: '<div>inner { <div ng-outlet></div> }</div>',
|
template: '<div>inner { <div ng-outlet></div> }</div>',
|
||||||
$routeConfig: [
|
$routeConfig: [
|
||||||
{ path: '/new-child', component: 'oneCmp', name: 'NewChild'},
|
{ path: '/new-child', component: 'oneCmp', name: 'NewChild'},
|
||||||
@ -236,7 +171,7 @@ describe('navigation', function () {
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/old-parent/old-child', redirectTo: ['/NewParent', 'NewChild'] },
|
{ path: '/old-parent/old-child', redirectTo: ['/NewParent', 'NewChild'] },
|
||||||
{ path: '/old-parent/old-child-two', redirectTo: ['/NewParent', 'NewChildTwo'] },
|
{ path: '/old-parent/old-child-two', redirectTo: ['/NewParent', 'NewChildTwo'] },
|
||||||
{ path: '/new-parent/...', component: 'childRouter', name: 'NewParent' }
|
{ path: '/new-parent/...', component: 'childRouter', name: 'NewParent' }
|
||||||
@ -244,13 +179,13 @@ describe('navigation', function () {
|
|||||||
|
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/old-parent/old-child');
|
$router.navigateByUrl('/old-parent/old-child');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect($location.path()).toBe('/new-parent/new-child');
|
expect($location.path()).toBe('/new-parent/new-child');
|
||||||
expect(elt.text()).toBe('inner { one }');
|
expect(elt.text()).toBe('inner { one }');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/old-parent/old-child-two');
|
$router.navigateByUrl('/old-parent/old-child-two');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect($location.path()).toBe('/new-parent/new-child-two');
|
expect($location.path()).toBe('/new-parent/new-child-two');
|
||||||
@ -259,7 +194,7 @@ describe('navigation', function () {
|
|||||||
|
|
||||||
|
|
||||||
it('should navigate when the location path changes', inject(function ($location) {
|
it('should navigate when the location path changes', inject(function ($location) {
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/one', component: 'oneCmp' }
|
{ path: '/one', component: 'oneCmp' }
|
||||||
]);
|
]);
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
@ -271,88 +206,57 @@ describe('navigation', function () {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
it('should navigate when the location query changes', inject(function ($location) {
|
it('should expose a "navigating" property on $router', inject(function ($q) {
|
||||||
$rootRouter.config([
|
|
||||||
{ path: '/get/params', component: 'getParams' }
|
|
||||||
]);
|
|
||||||
compile('<div ng-outlet></div>');
|
|
||||||
|
|
||||||
$location.url('/get/params?x=y');
|
|
||||||
$rootScope.$digest();
|
|
||||||
|
|
||||||
expect(elt.text()).toBe('y');
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should expose a "navigating" property on $rootRouter', inject(function ($q) {
|
|
||||||
var defer;
|
var defer;
|
||||||
registerDirective('pendingActivate', {
|
registerComponent('pendingActivate', {
|
||||||
$canActivate: function () {
|
$canActivate: function () {
|
||||||
defer = $q.defer();
|
defer = $q.defer();
|
||||||
return defer.promise;
|
return defer.promise;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/pending-activate', component: 'pendingActivate' }
|
{ path: '/pending-activate', component: 'pendingActivate' }
|
||||||
]);
|
]);
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/pending-activate');
|
$router.navigateByUrl('/pending-activate');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect($rootRouter.navigating).toBe(true);
|
expect($router.navigating).toBe(true);
|
||||||
defer.resolve();
|
defer.resolve();
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect($rootRouter.navigating).toBe(false);
|
expect($router.navigating).toBe(false);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function registerDirective(name, options) {
|
function registerComponent(name, options) {
|
||||||
|
var controller = options.controller || function () {};
|
||||||
|
|
||||||
|
['$routerOnActivate', '$routerOnDeactivate', '$routerOnReuse', '$routerCanReuse', '$routerCanDeactivate'].forEach(function (hookName) {
|
||||||
|
if (options[hookName]) {
|
||||||
|
controller.prototype[hookName] = options[hookName];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function factory() {
|
function factory() {
|
||||||
return {
|
return {
|
||||||
template: options.template || '',
|
template: options.template || '',
|
||||||
controllerAs: name,
|
controllerAs: name,
|
||||||
controller: getController(options)
|
controller: controller
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
applyStaticProperties(factory, options);
|
|
||||||
|
if (options.$canActivate) {
|
||||||
|
factory.$canActivate = options.$canActivate;
|
||||||
|
}
|
||||||
|
if (options.$routeConfig) {
|
||||||
|
factory.$routeConfig = options.$routeConfig;
|
||||||
|
}
|
||||||
|
|
||||||
$compileProvider.directive(name, factory);
|
$compileProvider.directive(name, factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerComponent(name, options) {
|
|
||||||
|
|
||||||
var definition = {
|
|
||||||
template: options.template || '',
|
|
||||||
controller: getController(options),
|
|
||||||
}
|
|
||||||
applyStaticProperties(definition, options);
|
|
||||||
$compileProvider.component(name, definition);
|
|
||||||
}
|
|
||||||
|
|
||||||
function compile(template) {
|
function compile(template) {
|
||||||
elt = $compile('<div>' + template + '</div>')($rootScope);
|
elt = $compile('<div>' + template + '</div>')($rootScope);
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
return elt;
|
return elt;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getController(options) {
|
|
||||||
var controller = options.controller || function () {};
|
|
||||||
[
|
|
||||||
'$routerOnActivate', '$routerOnDeactivate',
|
|
||||||
'$routerOnReuse', '$routerCanReuse',
|
|
||||||
'$routerCanDeactivate'
|
|
||||||
].forEach(function (hookName) {
|
|
||||||
if (options[hookName]) {
|
|
||||||
controller.prototype[hookName] = options[hookName];
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
return controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
function applyStaticProperties(target, options) {
|
|
||||||
['$canActivate', '$routeConfig'].forEach(function(property) {
|
|
||||||
if (options[property]) {
|
|
||||||
target[property] = options[property];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ describe('router', function () {
|
|||||||
var elt,
|
var elt,
|
||||||
$compile,
|
$compile,
|
||||||
$rootScope,
|
$rootScope,
|
||||||
$rootRouter,
|
$router,
|
||||||
$compileProvider;
|
$compileProvider;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
@ -18,10 +18,10 @@ describe('router', function () {
|
|||||||
$compileProvider = _$compileProvider_;
|
$compileProvider = _$compileProvider_;
|
||||||
});
|
});
|
||||||
|
|
||||||
inject(function (_$compile_, _$rootScope_, _$rootRouter_) {
|
inject(function (_$compile_, _$rootScope_, _$router_) {
|
||||||
$compile = _$compile_;
|
$compile = _$compile_;
|
||||||
$rootScope = _$rootScope_;
|
$rootScope = _$rootScope_;
|
||||||
$rootRouter = _$rootRouter_;
|
$router = _$router_;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -44,137 +44,36 @@ describe('router', function () {
|
|||||||
expect(elt.text()).toBe('Home');
|
expect(elt.text()).toBe('Home');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should bind the component to the current router', inject(function($location) {
|
function registerComponent(name, options) {
|
||||||
var router;
|
var controller = options.controller || function () {};
|
||||||
registerComponent('homeCmp', {
|
|
||||||
bindings: { $router: '=' },
|
|
||||||
controller: function($scope, $element) {
|
|
||||||
this.$routerOnActivate = function() {
|
|
||||||
router = this.$router;
|
|
||||||
};
|
|
||||||
},
|
|
||||||
template: 'Home'
|
|
||||||
});
|
|
||||||
|
|
||||||
registerComponent('app', {
|
['$onActivate', '$onDeactivate', '$onReuse', '$canReuse', '$canDeactivate'].forEach(function (hookName) {
|
||||||
template: '<div ng-outlet></div>',
|
if (options[hookName]) {
|
||||||
$routeConfig: [
|
controller.prototype[hookName] = options[hookName];
|
||||||
{ path: '/', component: 'homeCmp' }
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
compile('<app></app>');
|
|
||||||
|
|
||||||
$location.path('/');
|
|
||||||
$rootScope.$digest();
|
|
||||||
var homeElement = elt.find('home-cmp');
|
|
||||||
expect(homeElement.text()).toBe('Home');
|
|
||||||
expect(homeElement.isolateScope().$ctrl.$router).toBeDefined();
|
|
||||||
expect(router).toBeDefined();
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should work when an async route is provided route data', inject(function($location, $q) {
|
|
||||||
registerDirective('homeCmp', {
|
|
||||||
template: 'Home ({{homeCmp.isAdmin}})',
|
|
||||||
$routerOnActivate: function(next, prev) {
|
|
||||||
this.isAdmin = next.routeData.data.isAdmin;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
registerDirective('app', {
|
|
||||||
template: '<div ng-outlet></div>',
|
|
||||||
$routeConfig: [
|
|
||||||
{ path: '/', loader: function() { return $q.when('homeCmp'); }, data: { isAdmin: true } }
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
compile('<app></app>');
|
|
||||||
|
|
||||||
$location.path('/');
|
|
||||||
$rootScope.$digest();
|
|
||||||
expect(elt.text()).toBe('Home (true)');
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should work with a templateUrl component', inject(function($location, $httpBackend) {
|
|
||||||
var $routerOnActivate = jasmine.createSpy('$routerOnActivate');
|
|
||||||
$httpBackend.expectGET('homeCmp.html').respond('Home');
|
|
||||||
registerComponent('homeCmp', {
|
|
||||||
templateUrl: 'homeCmp.html',
|
|
||||||
$routerOnActivate: $routerOnActivate
|
|
||||||
});
|
|
||||||
|
|
||||||
registerComponent('app', {
|
|
||||||
template: '<div ng-outlet></div>',
|
|
||||||
$routeConfig: [
|
|
||||||
{ path: '/', component: 'homeCmp' }
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
compile('<app></app>');
|
|
||||||
|
|
||||||
$location.path('/');
|
|
||||||
$rootScope.$digest();
|
|
||||||
$httpBackend.flush();
|
|
||||||
var homeElement = elt.find('home-cmp');
|
|
||||||
expect(homeElement.text()).toBe('Home');
|
|
||||||
expect($routerOnActivate).toHaveBeenCalled();
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
function registerDirective(name, options) {
|
|
||||||
function factory() {
|
function factory() {
|
||||||
return {
|
return {
|
||||||
template: options.template || '',
|
template: options.template || '',
|
||||||
controllerAs: name,
|
controllerAs: name,
|
||||||
controller: getController(options)
|
controller: controller
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
applyStaticProperties(factory, options);
|
|
||||||
|
if (options.$canActivate) {
|
||||||
|
factory.$canActivate = options.$canActivate;
|
||||||
|
}
|
||||||
|
if (options.$routeConfig) {
|
||||||
|
factory.$routeConfig = options.$routeConfig;
|
||||||
|
}
|
||||||
|
|
||||||
$compileProvider.directive(name, factory);
|
$compileProvider.directive(name, factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerComponent(name, options) {
|
|
||||||
|
|
||||||
var definition = {
|
|
||||||
bindings: options.bindings,
|
|
||||||
controller: getController(options),
|
|
||||||
};
|
|
||||||
if (options.template) {
|
|
||||||
definition.template = options.template;
|
|
||||||
}
|
|
||||||
if (options.templateUrl) {
|
|
||||||
definition.templateUrl = options.templateUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
applyStaticProperties(definition, options);
|
|
||||||
$compileProvider.component(name, definition);
|
|
||||||
}
|
|
||||||
|
|
||||||
function compile(template) {
|
function compile(template) {
|
||||||
elt = $compile('<div>' + template + '</div>')($rootScope);
|
elt = $compile('<div>' + template + '</div>')($rootScope);
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
return elt;
|
return elt;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getController(options) {
|
|
||||||
var controller = options.controller || function () {};
|
|
||||||
[
|
|
||||||
'$routerOnActivate', '$routerOnDeactivate',
|
|
||||||
'$routerOnReuse', '$routerCanReuse',
|
|
||||||
'$routerCanDeactivate'
|
|
||||||
].forEach(function (hookName) {
|
|
||||||
if (options[hookName]) {
|
|
||||||
controller.prototype[hookName] = options[hookName];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
function applyStaticProperties(target, options) {
|
|
||||||
['$canActivate', '$routeConfig'].forEach(function(property) {
|
|
||||||
if (options[property]) {
|
|
||||||
target[property] = options[property];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
@ -5,7 +5,7 @@ describe('ngRoute shim', function () {
|
|||||||
var elt,
|
var elt,
|
||||||
$compile,
|
$compile,
|
||||||
$rootScope,
|
$rootScope,
|
||||||
$rootRouter,
|
$router,
|
||||||
$compileProvider,
|
$compileProvider,
|
||||||
$routeProvider;
|
$routeProvider;
|
||||||
|
|
||||||
@ -18,10 +18,10 @@ describe('ngRoute shim', function () {
|
|||||||
$routeProvider = _$routeProvider_;
|
$routeProvider = _$routeProvider_;
|
||||||
});
|
});
|
||||||
|
|
||||||
inject(function (_$compile_, _$rootScope_, _$rootRouter_) {
|
inject(function (_$compile_, _$rootScope_, _$router_) {
|
||||||
$compile = _$compile_;
|
$compile = _$compile_;
|
||||||
$rootScope = _$rootScope_;
|
$rootScope = _$rootScope_;
|
||||||
$rootRouter = _$rootRouter_;
|
$router = _$router_;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ describe('ngRoute shim', function () {
|
|||||||
|
|
||||||
compile('<ng-outlet></ng-outlet>');
|
compile('<ng-outlet></ng-outlet>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/');
|
$router.navigateByUrl('/');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(elt.text()).toBe('one');
|
expect(elt.text()).toBe('one');
|
||||||
@ -55,7 +55,7 @@ describe('ngRoute shim', function () {
|
|||||||
|
|
||||||
compile('root {<ng-outlet></ng-outlet>}');
|
compile('root {<ng-outlet></ng-outlet>}');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/');
|
$router.navigateByUrl('/');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('root {one}');
|
expect(elt.text()).toBe('root {one}');
|
||||||
}));
|
}));
|
||||||
@ -76,7 +76,7 @@ describe('ngRoute shim', function () {
|
|||||||
|
|
||||||
compile('<ng-outlet></ng-outlet>');
|
compile('<ng-outlet></ng-outlet>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/');
|
$router.navigateByUrl('/');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(elt.text()).toBe('value: 42');
|
expect(elt.text()).toBe('value: 42');
|
||||||
@ -94,11 +94,11 @@ describe('ngRoute shim', function () {
|
|||||||
|
|
||||||
compile('<ng-outlet></ng-outlet>');
|
compile('<ng-outlet></ng-outlet>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/user/brian');
|
$router.navigateByUrl('/user/brian');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('hello brian');
|
expect(elt.text()).toBe('hello brian');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/user/igor');
|
$router.navigateByUrl('/user/igor');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('hello igor');
|
expect(elt.text()).toBe('hello igor');
|
||||||
});
|
});
|
||||||
@ -115,7 +115,7 @@ describe('ngRoute shim', function () {
|
|||||||
|
|
||||||
compile('<ng-outlet></ng-outlet>');
|
compile('<ng-outlet></ng-outlet>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/home/foo/bar/123');
|
$router.navigateByUrl('/home/foo/bar/123');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('rest: foo/bar/123');
|
expect(elt.text()).toBe('rest: foo/bar/123');
|
||||||
});
|
});
|
||||||
@ -129,7 +129,7 @@ describe('ngRoute shim', function () {
|
|||||||
|
|
||||||
compile('root {<ng-outlet></ng-outlet>}');
|
compile('root {<ng-outlet></ng-outlet>}');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/home/test');
|
$router.navigateByUrl('/home/test');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('root {}');
|
expect(elt.text()).toBe('root {}');
|
||||||
expect(console.warn)
|
expect(console.warn)
|
||||||
@ -150,7 +150,7 @@ describe('ngRoute shim', function () {
|
|||||||
|
|
||||||
compile('root {<ng-outlet></ng-outlet>}');
|
compile('root {<ng-outlet></ng-outlet>}');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/');
|
$router.navigateByUrl('/');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('root {welcome home!}');
|
expect(elt.text()).toBe('root {welcome home!}');
|
||||||
expect($location.path()).toBe('/home');
|
expect($location.path()).toBe('/home');
|
||||||
@ -169,7 +169,7 @@ describe('ngRoute shim', function () {
|
|||||||
|
|
||||||
compile('root {<ng-outlet></ng-outlet>}');
|
compile('root {<ng-outlet></ng-outlet>}');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/somewhere');
|
$router.navigateByUrl('/somewhere');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
expect(elt.text()).toBe('root {welcome home!}');
|
expect(elt.text()).toBe('root {welcome home!}');
|
||||||
expect($location.path()).toBe('/home');
|
expect($location.path()).toBe('/home');
|
||||||
|
30
modules/angular1_router/test/ng_link_spec.js
vendored
30
modules/angular1_router/test/ng_link_spec.js
vendored
@ -5,7 +5,7 @@ describe('ngLink', function () {
|
|||||||
var elt,
|
var elt,
|
||||||
$compile,
|
$compile,
|
||||||
$rootScope,
|
$rootScope,
|
||||||
$rootRouter,
|
$router,
|
||||||
$compileProvider;
|
$compileProvider;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
@ -15,10 +15,10 @@ describe('ngLink', function () {
|
|||||||
$compileProvider = _$compileProvider_;
|
$compileProvider = _$compileProvider_;
|
||||||
});
|
});
|
||||||
|
|
||||||
inject(function (_$compile_, _$rootScope_, _$rootRouter_) {
|
inject(function (_$compile_, _$rootScope_, _$router_) {
|
||||||
$compile = _$compile_;
|
$compile = _$compile_;
|
||||||
$rootScope = _$rootScope_;
|
$rootScope = _$rootScope_;
|
||||||
$rootRouter = _$rootRouter_;
|
$router = _$router_;
|
||||||
});
|
});
|
||||||
|
|
||||||
registerComponent('userCmp', '<div>hello {{userCmp.$routeParams.name}}</div>', function () {});
|
registerComponent('userCmp', '<div>hello {{userCmp.$routeParams.name}}</div>', function () {});
|
||||||
@ -28,26 +28,26 @@ describe('ngLink', function () {
|
|||||||
|
|
||||||
|
|
||||||
it('should allow linking from the parent to the child', function () {
|
it('should allow linking from the parent to the child', function () {
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/a', component: 'oneCmp' },
|
{ path: '/a', component: 'oneCmp' },
|
||||||
{ path: '/b', component: 'twoCmp', name: 'Two' }
|
{ path: '/b', component: 'twoCmp', name: 'Two' }
|
||||||
]);
|
]);
|
||||||
compile('<a ng-link="[\'/Two\']">link</a> | outer { <div ng-outlet></div> }');
|
compile('<a ng-link="[\'/Two\']">link</a> | outer { <div ng-outlet></div> }');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/a');
|
$router.navigateByUrl('/a');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(elt.find('a').attr('href')).toBe('./b');
|
expect(elt.find('a').attr('href')).toBe('./b');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow linking from the child and the parent', function () {
|
it('should allow linking from the child and the parent', function () {
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/a', component: 'oneCmp' },
|
{ path: '/a', component: 'oneCmp' },
|
||||||
{ path: '/b', component: 'twoCmp', name: 'Two' }
|
{ path: '/b', component: 'twoCmp', name: 'Two' }
|
||||||
]);
|
]);
|
||||||
compile('outer { <div ng-outlet></div> }');
|
compile('outer { <div ng-outlet></div> }');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/b');
|
$router.navigateByUrl('/b');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(elt.find('a').attr('href')).toBe('./b');
|
expect(elt.find('a').attr('href')).toBe('./b');
|
||||||
@ -57,13 +57,13 @@ describe('ngLink', function () {
|
|||||||
it('should allow params in routerLink directive', function () {
|
it('should allow params in routerLink directive', function () {
|
||||||
registerComponent('twoLinkCmp', '<div><a ng-link="[\'/Two\', {param: \'lol\'}]">{{twoLinkCmp.number}}</a></div>', function () {this.number = 'two'});
|
registerComponent('twoLinkCmp', '<div><a ng-link="[\'/Two\', {param: \'lol\'}]">{{twoLinkCmp.number}}</a></div>', function () {this.number = 'two'});
|
||||||
|
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/a', component: 'twoLinkCmp' },
|
{ path: '/a', component: 'twoLinkCmp' },
|
||||||
{ path: '/b/:param', component: 'twoCmp', name: 'Two' }
|
{ path: '/b/:param', component: 'twoCmp', name: 'Two' }
|
||||||
]);
|
]);
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/a');
|
$router.navigateByUrl('/a');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(elt.find('a').attr('href')).toBe('./b/lol');
|
expect(elt.find('a').attr('href')).toBe('./b/lol');
|
||||||
@ -72,13 +72,13 @@ describe('ngLink', function () {
|
|||||||
|
|
||||||
it('should update the href of links with bound params', function () {
|
it('should update the href of links with bound params', function () {
|
||||||
registerComponent('twoLinkCmp', '<div><a ng-link="[\'/Two\', {param: twoLinkCmp.number}]">{{twoLinkCmp.number}}</a></div>', function () {this.number = 'param'});
|
registerComponent('twoLinkCmp', '<div><a ng-link="[\'/Two\', {param: twoLinkCmp.number}]">{{twoLinkCmp.number}}</a></div>', function () {this.number = 'param'});
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/a', component: 'twoLinkCmp' },
|
{ path: '/a', component: 'twoLinkCmp' },
|
||||||
{ path: '/b/:param', component: 'twoCmp', name: 'Two' }
|
{ path: '/b/:param', component: 'twoCmp', name: 'Two' }
|
||||||
]);
|
]);
|
||||||
compile('<div ng-outlet></div>');
|
compile('<div ng-outlet></div>');
|
||||||
|
|
||||||
$rootRouter.navigateByUrl('/a');
|
$router.navigateByUrl('/a');
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
||||||
expect(elt.find('a').attr('href')).toBe('./b/param');
|
expect(elt.find('a').attr('href')).toBe('./b/param');
|
||||||
@ -86,7 +86,7 @@ describe('ngLink', function () {
|
|||||||
|
|
||||||
|
|
||||||
it('should navigate on left-mouse click when a link url matches a route', function () {
|
it('should navigate on left-mouse click when a link url matches a route', function () {
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/', component: 'oneCmp' },
|
{ path: '/', component: 'oneCmp' },
|
||||||
{ path: '/two', component: 'twoCmp', name: 'Two'}
|
{ path: '/two', component: 'twoCmp', name: 'Two'}
|
||||||
]);
|
]);
|
||||||
@ -104,8 +104,8 @@ describe('ngLink', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should not navigate on non-left mouse click when a link url matches a route', inject(function ($rootRouter) {
|
it('should not navigate on non-left mouse click when a link url matches a route', inject(function ($router) {
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/', component: 'oneCmp' },
|
{ path: '/', component: 'oneCmp' },
|
||||||
{ path: '/two', component: 'twoCmp', name: 'Two'}
|
{ path: '/two', component: 'twoCmp', name: 'Two'}
|
||||||
]);
|
]);
|
||||||
@ -122,7 +122,7 @@ describe('ngLink', function () {
|
|||||||
|
|
||||||
// See https://github.com/angular/router/issues/206
|
// See https://github.com/angular/router/issues/206
|
||||||
it('should not navigate a link without an href', function () {
|
it('should not navigate a link without an href', function () {
|
||||||
$rootRouter.config([
|
$router.config([
|
||||||
{ path: '/', component: 'oneCmp' },
|
{ path: '/', component: 'oneCmp' },
|
||||||
{ path: '/two', component: 'twoCmp', name: 'Two'}
|
{ path: '/two', component: 'twoCmp', name: 'Two'}
|
||||||
]);
|
]);
|
||||||
|
@ -22,7 +22,7 @@ function provideHelpers(fn, preInject) {
|
|||||||
var elt,
|
var elt,
|
||||||
$compile,
|
$compile,
|
||||||
$rootScope,
|
$rootScope,
|
||||||
$rootRouter,
|
$router,
|
||||||
$templateCache,
|
$templateCache,
|
||||||
$controllerProvider;
|
$controllerProvider;
|
||||||
|
|
||||||
@ -32,10 +32,10 @@ function provideHelpers(fn, preInject) {
|
|||||||
$controllerProvider = _$controllerProvider_;
|
$controllerProvider = _$controllerProvider_;
|
||||||
});
|
});
|
||||||
|
|
||||||
inject(function(_$compile_, _$rootScope_, _$rootRouter_, _$templateCache_) {
|
inject(function(_$compile_, _$rootScope_, _$router_, _$templateCache_) {
|
||||||
$compile = _$compile_;
|
$compile = _$compile_;
|
||||||
$rootScope = _$rootScope_;
|
$rootScope = _$rootScope_;
|
||||||
$rootRouter = _$rootRouter_;
|
$router = _$router_;
|
||||||
$templateCache = _$templateCache_;
|
$templateCache = _$templateCache_;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ function provideHelpers(fn, preInject) {
|
|||||||
|
|
||||||
fn({
|
fn({
|
||||||
registerComponent: registerComponent,
|
registerComponent: registerComponent,
|
||||||
$rootRouter: $rootRouter,
|
$router: $router,
|
||||||
put: put,
|
put: put,
|
||||||
compile: compile
|
compile: compile
|
||||||
})
|
})
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"version": "v4",
|
"version": "v4",
|
||||||
"repo": "DefinitelyTyped/DefinitelyTyped",
|
"repo": "angular/DefinitelyTyped",
|
||||||
"ref": "master",
|
"ref": "master",
|
||||||
"path": "typings",
|
"path": "typings",
|
||||||
"bundle": "typings/tsd.d.ts",
|
"bundle": "typings/tsd.d.ts",
|
||||||
"installed": {
|
"installed": {
|
||||||
"angularjs/angular.d.ts": {
|
"angularjs/angular.d.ts": {
|
||||||
"commit": "6eebd5e90a1cbd6b47b0705ba72dbcd5baf846f3"
|
"commit": "746b9a892629060bc853e792afff536e0ec4655e"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ Bootstrapping
|
|||||||
@cheatsheetIndex 0
|
@cheatsheetIndex 0
|
||||||
@description
|
@description
|
||||||
{@target ts}`import {bootstrap} from 'angular2/platform/browser';`{@endtarget}
|
{@target ts}`import {bootstrap} from 'angular2/platform/browser';`{@endtarget}
|
||||||
{@target js}Available from the `ng.platform.browser` namespace{@endtarget}
|
{@target js}Available from the `ng.platform.browser` namespace.{@endtarget}
|
||||||
{@target dart}`import 'package:angular2/bootstrap.dart';`{@endtarget}
|
{@target dart}`import 'package:angular2/bootstrap.dart';`{@endtarget}
|
||||||
|
|
||||||
@cheatsheetItem
|
@cheatsheetItem
|
||||||
|
@ -4,7 +4,7 @@ Built-in directives
|
|||||||
@description
|
@description
|
||||||
{@target ts}`import {NgIf, ...} from 'angular2/common';`{@endtarget}
|
{@target ts}`import {NgIf, ...} from 'angular2/common';`{@endtarget}
|
||||||
{@target js}Available from the `ng.common` namespace{@endtarget}
|
{@target js}Available from the `ng.common` namespace{@endtarget}
|
||||||
{@target dart}Available using `platform_directives` in pubspec{@endtarget}
|
{@target dart}`import 'package:angular2/common.dart';`{@endtarget}
|
||||||
|
|
||||||
@cheatsheetItem
|
@cheatsheetItem
|
||||||
syntax:
|
syntax:
|
||||||
|
@ -4,7 +4,7 @@ Class decorators
|
|||||||
@description
|
@description
|
||||||
{@target ts}`import {Directive, ...} from 'angular2/core';`{@endtarget}
|
{@target ts}`import {Directive, ...} from 'angular2/core';`{@endtarget}
|
||||||
{@target js}Available from the `ng.core` namespace{@endtarget}
|
{@target js}Available from the `ng.core` namespace{@endtarget}
|
||||||
{@target dart}`import 'package:angular2/angular2.dart';`{@endtarget}
|
{@target dart}`import 'package:angular2/core.dart';`{@endtarget}
|
||||||
|
|
||||||
@cheatsheetItem
|
@cheatsheetItem
|
||||||
syntax(ts):
|
syntax(ts):
|
||||||
|
@ -4,7 +4,7 @@ Dependency injection configuration
|
|||||||
@description
|
@description
|
||||||
{@target ts}`import {provide} from 'angular2/core';`{@endtarget}
|
{@target ts}`import {provide} from 'angular2/core';`{@endtarget}
|
||||||
{@target js}Available from the `ng.core` namespace{@endtarget}
|
{@target js}Available from the `ng.core` namespace{@endtarget}
|
||||||
{@target dart}`import 'package:angular2/angular2.dart';`{@endtarget}
|
{@target dart}`import 'package:angular2/core.dart';`{@endtarget}
|
||||||
|
|
||||||
@cheatsheetItem
|
@cheatsheetItem
|
||||||
syntax(ts dart):
|
syntax(ts dart):
|
||||||
|
@ -4,7 +4,7 @@ Class field decorators for directives and components
|
|||||||
@description
|
@description
|
||||||
{@target ts}`import {Input, ...} from 'angular2/core';`{@endtarget}
|
{@target ts}`import {Input, ...} from 'angular2/core';`{@endtarget}
|
||||||
{@target js}Available from the `ng.core` namespace{@endtarget}
|
{@target js}Available from the `ng.core` namespace{@endtarget}
|
||||||
{@target dart}`import 'package:angular2/angular2.dart';`{@endtarget}
|
{@target dart}`import 'package:angular2/core.dart';`{@endtarget}
|
||||||
|
|
||||||
@cheatsheetItem
|
@cheatsheetItem
|
||||||
syntax(ts dart):
|
syntax(ts dart):
|
||||||
|
@ -4,7 +4,7 @@ Forms
|
|||||||
@description
|
@description
|
||||||
{@target ts}`import {FORM_DIRECTIVES} from 'angular2/common';`{@endtarget}
|
{@target ts}`import {FORM_DIRECTIVES} from 'angular2/common';`{@endtarget}
|
||||||
{@target js}Available from `ng.common.FORM_DIRECTIVES`{@endtarget}
|
{@target js}Available from `ng.common.FORM_DIRECTIVES`{@endtarget}
|
||||||
{@target dart}Available using `platform_directives` in pubspec{@endtarget}
|
{@target dart}`import 'package:angular2/common.dart';`{@endtarget}
|
||||||
|
|
||||||
@cheatsheetItem
|
@cheatsheetItem
|
||||||
syntax:
|
syntax:
|
||||||
|
@ -4,7 +4,7 @@ Routing and navigation
|
|||||||
@description
|
@description
|
||||||
{@target ts}`import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, ...} from 'angular2/router';`{@endtarget}
|
{@target ts}`import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, ...} from 'angular2/router';`{@endtarget}
|
||||||
{@target js}Available from the `ng.router` namespace{@endtarget}
|
{@target js}Available from the `ng.router` namespace{@endtarget}
|
||||||
{@target dart}`import 'package:angular2/angular2.dart';`{@endtarget}
|
{@target dart}`import 'package:angular2/router.dart';`{@endtarget}
|
||||||
|
|
||||||
|
|
||||||
@cheatsheetItem
|
@cheatsheetItem
|
||||||
|
@ -456,7 +456,7 @@ Where
|
|||||||
* `local` is a local identifier for local variables.
|
* `local` is a local identifier for local variables.
|
||||||
* `internal` is an internal variable which the directive exports for binding.
|
* `internal` is an internal variable which the directive exports for binding.
|
||||||
* `key` is an attribute name usually only used to trigger a specific directive.
|
* `key` is an attribute name usually only used to trigger a specific directive.
|
||||||
* `keyExpression` is a property name to which the expression will be bound to.
|
* `keyExpression` is an property name to which the expression will be bound to.
|
||||||
* `varExport` allows exporting of directive internal state as variables for further binding. If no `internal` name
|
* `varExport` allows exporting of directive internal state as variables for further binding. If no `internal` name
|
||||||
is specified, the exporting is to an implicit variable.
|
is specified, the exporting is to an implicit variable.
|
||||||
* `microsyntax` allows you to build a simple microsyntax which can still clearly identify which expressions bind to
|
* `microsyntax` allows you to build a simple microsyntax which can still clearly identify which expressions bind to
|
||||||
|
@ -2,7 +2,7 @@ import {provide} from 'angular2/core';
|
|||||||
import {bootstrap} from 'angular2/bootstrap';
|
import {bootstrap} from 'angular2/bootstrap';
|
||||||
import {UrlResolver} from 'angular2/compiler';
|
import {UrlResolver} from 'angular2/compiler';
|
||||||
|
|
||||||
var MyApp: any;
|
var MyApp;
|
||||||
|
|
||||||
// #docregion url_resolver
|
// #docregion url_resolver
|
||||||
class MyUrlResolver extends UrlResolver {
|
class MyUrlResolver extends UrlResolver {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import {DebugElement} from 'angular2/core';
|
import {DebugElement} from 'angular2/core';
|
||||||
|
|
||||||
var debugElement: DebugElement;
|
var debugElement: DebugElement;
|
||||||
var predicate: any;
|
var predicate;
|
||||||
|
|
||||||
// #docregion scope_all
|
// #docregion scope_all
|
||||||
debugElement.query(predicate);
|
debugElement.query(predicate);
|
||||||
|
@ -2,8 +2,8 @@ import {bootstrap} from 'angular2/bootstrap';
|
|||||||
import {NG_VALIDATORS} from 'angular2/common';
|
import {NG_VALIDATORS} from 'angular2/common';
|
||||||
import {Provider} from 'angular2/core';
|
import {Provider} from 'angular2/core';
|
||||||
|
|
||||||
let MyApp: Function = null;
|
let MyApp = null;
|
||||||
let myValidator: any = null;
|
let myValidator = null;
|
||||||
|
|
||||||
// #docregion ng_validators
|
// #docregion ng_validators
|
||||||
bootstrap(MyApp, [new Provider(NG_VALIDATORS, {useValue: myValidator, multi: true})]);
|
bootstrap(MyApp, [new Provider(NG_VALIDATORS, {useValue: myValidator, multi: true})]);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {Component, provide} from 'angular2/core';
|
import {Component, provide} from 'angular2/core';
|
||||||
import {bootstrap} from 'angular2/bootstrap';
|
import {bootstrap} from 'angular2/bootstrap';
|
||||||
import {Observable, Subscriber} from 'rxjs/Rx';
|
import {Observable} from 'rxjs/Observable';
|
||||||
|
|
||||||
// #docregion AsyncPipe
|
// #docregion AsyncPipe
|
||||||
@Component({
|
@Component({
|
||||||
@ -37,9 +37,8 @@ export class AsyncPipeExample {
|
|||||||
// #docregion AsyncPipeObservable
|
// #docregion AsyncPipeObservable
|
||||||
@Component({selector: "task-cmp", template: "Time: {{ time | async }}"})
|
@Component({selector: "task-cmp", template: "Time: {{ time | async }}"})
|
||||||
class Task {
|
class Task {
|
||||||
time = new Observable<number>((observer: Subscriber<number>) => {
|
time = new Observable<number>(
|
||||||
setInterval(_ => observer.next(new Date().getTime()), 500);
|
observer => { setInterval(_ => observer.next(new Date().getTime()), 500); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import {bootstrap} from 'angular2/bootstrap';
|
|||||||
})
|
})
|
||||||
export class LowerUpperPipeExample {
|
export class LowerUpperPipeExample {
|
||||||
value: string;
|
value: string;
|
||||||
change(value: string) { this.value = value; }
|
change(value) { this.value = value; }
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {Component, Attribute, Directive, Pipe} from 'angular2/core';
|
import {Component, Attribute, Directive, Pipe} from 'angular2/core';
|
||||||
|
|
||||||
var CustomDirective: Function;
|
var CustomDirective;
|
||||||
|
|
||||||
// #docregion component
|
// #docregion component
|
||||||
@Component({selector: 'greet', template: 'Hello {{name}}!', directives: [CustomDirective]})
|
@Component({selector: 'greet', template: 'Hello {{name}}!', directives: [CustomDirective]})
|
||||||
@ -20,7 +20,7 @@ class Page {
|
|||||||
// #docregion attributeMetadata
|
// #docregion attributeMetadata
|
||||||
@Directive({selector: 'input'})
|
@Directive({selector: 'input'})
|
||||||
class InputAttrDirective {
|
class InputAttrDirective {
|
||||||
constructor(@Attribute('type') type: string) {
|
constructor(@Attribute('type') type) {
|
||||||
// type would be 'text' in this example
|
// type would be 'text' in this example
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,6 +38,6 @@ class InputDirective {
|
|||||||
// #docregion pipe
|
// #docregion pipe
|
||||||
@Pipe({name: 'lowercase'})
|
@Pipe({name: 'lowercase'})
|
||||||
class Lowercase {
|
class Lowercase {
|
||||||
transform(v: string, args: any[]) { return v.toLowerCase(); }
|
transform(v, args) { return v.toLowerCase(); }
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// #docregion enableProdMode
|
// #docregion enableProdMode
|
||||||
import {enableProdMode} from 'angular2/core';
|
import {enableProdMode} from 'angular2/core';
|
||||||
import {bootstrap} from 'angular2/bootstrap';
|
import {bootstrap} from 'angular2/bootstrap';
|
||||||
import {MyComponent} from './my_component';
|
import {MyComponent} from 'my_component';
|
||||||
|
|
||||||
enableProdMode();
|
enableProdMode();
|
||||||
bootstrap(MyComponent);
|
bootstrap(MyComponent);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docregion Observable
|
// #docregion Observable
|
||||||
import {Observable, Subscriber} from 'rxjs/Rx';
|
import {Observable} from 'rxjs/Observable';
|
||||||
var obs = new Observable<number>((obs: Subscriber<number>) => {
|
var obs = new Observable<number>(obs => {
|
||||||
var i = 0;
|
var i = 0;
|
||||||
setInterval(_ => { obs.next(++i); }, 1000);
|
setInterval(_ => { obs.next(++i); }, 1000);
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// #docregion Observable
|
// #docregion Observable
|
||||||
import {Observable, Subscriber} from 'rxjs/Rx';
|
import {Observable} from 'rxjs/Observable';
|
||||||
import 'rxjs/add/operator/map';
|
import 'rxjs/add/operator/map';
|
||||||
|
|
||||||
var obs = new Observable<number>((obs: Subscriber<any>) => {
|
var obs = new Observable(obs => {
|
||||||
var i = 0;
|
var i = 0;
|
||||||
setInterval(_ => obs.next(++i), 1000);
|
setInterval(_ => obs.next(++i), 1000);
|
||||||
});
|
});
|
||||||
obs.map((i: number) => `${i} seconds elapsed`).subscribe(msg => console.log(msg));
|
obs.map(i => `${i} seconds elapsed`).subscribe(msg => console.log(msg));
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// #docregion Observable
|
// #docregion Observable
|
||||||
import {Observable, Subscriber} from 'rxjs/Rx';
|
import {Observable} from 'rxjs/Observable';
|
||||||
import {map} from 'rxjs/operator/map';
|
import {map} from 'rxjs/operator/map';
|
||||||
|
|
||||||
var obs = new Observable<number>((sub: Subscriber<number>) => {
|
var obs = new Observable(obs => {
|
||||||
var i = 0;
|
var i = 0;
|
||||||
setInterval(_ => sub.next(++i), 1000);
|
setInterval(_ => obs.next(++i), 1000);
|
||||||
});
|
});
|
||||||
map.call(obs, (i: number) => `${i} seconds elapsed`).subscribe((msg: string) => console.log(msg));
|
map.call(obs, i => `${i} seconds elapsed`).subscribe(msg => console.log(msg));
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
|
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
|
||||||
|
import {Promise} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
function waitForElement(selector: string) {
|
function waitForElement(selector) {
|
||||||
var EC = (<any>protractor).ExpectedConditions;
|
var EC = (<any>protractor).ExpectedConditions;
|
||||||
// Waits for the element with id 'abc' to be present on the dom.
|
// Waits for the element with id 'abc' to be present on the dom.
|
||||||
browser.wait(EC.presenceOf($(selector)), 20000);
|
browser.wait(EC.presenceOf($(selector)), 20000);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
|
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
|
||||||
|
import {Promise} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
function waitForElement(selector: string) {
|
function waitForElement(selector) {
|
||||||
var EC = (<any>protractor).ExpectedConditions;
|
var EC = (<any>protractor).ExpectedConditions;
|
||||||
// Waits for the element with id 'abc' to be present on the dom.
|
// Waits for the element with id 'abc' to be present on the dom.
|
||||||
browser.wait(EC.presenceOf($(selector)), 20000);
|
browser.wait(EC.presenceOf($(selector)), 20000);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
|
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
|
||||||
|
import {Promise} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
function waitForElement(selector: string) {
|
function waitForElement(selector) {
|
||||||
var EC = (<any>protractor).ExpectedConditions;
|
var EC = (<any>protractor).ExpectedConditions;
|
||||||
// Waits for the element with id 'abc' to be present on the dom.
|
// Waits for the element with id 'abc' to be present on the dom.
|
||||||
browser.wait(EC.presenceOf($(selector)), 20000);
|
browser.wait(EC.presenceOf($(selector)), 20000);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
|
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
|
||||||
|
import {Promise} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
function waitForElement(selector: string) {
|
function waitForElement(selector) {
|
||||||
var EC = (<any>protractor).ExpectedConditions;
|
var EC = (<any>protractor).ExpectedConditions;
|
||||||
// Waits for the element with id 'abc' to be present on the dom.
|
// Waits for the element with id 'abc' to be present on the dom.
|
||||||
browser.wait(EC.presenceOf($(selector)), 20000);
|
browser.wait(EC.presenceOf($(selector)), 20000);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
|
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
|
||||||
|
import {Promise} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
function waitForElement(selector: string) {
|
function waitForElement(selector) {
|
||||||
var EC = (<any>protractor).ExpectedConditions;
|
var EC = (<any>protractor).ExpectedConditions;
|
||||||
// Waits for the element with id 'abc' to be present on the dom.
|
// Waits for the element with id 'abc' to be present on the dom.
|
||||||
browser.wait(EC.presenceOf($(selector)), 20000);
|
browser.wait(EC.presenceOf($(selector)), 20000);
|
||||||
|
@ -73,7 +73,7 @@ describe('some component', () => {
|
|||||||
// #docregion beforeEachProviders
|
// #docregion beforeEachProviders
|
||||||
describe('some component', () => {
|
describe('some component', () => {
|
||||||
beforeEachProviders(() => [provide(MyService, {useClass: MyMockService})]);
|
beforeEachProviders(() => [provide(MyService, {useClass: MyMockService})]);
|
||||||
it('uses MyService', inject([MyService], (service: MyMockService) => {
|
it('uses MyService', inject([MyService], (service) => {
|
||||||
// service is an instance of MyMockService.
|
// service is an instance of MyMockService.
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
@ -81,7 +81,7 @@ describe('some component', () => {
|
|||||||
|
|
||||||
// #docregion afterEach
|
// #docregion afterEach
|
||||||
describe('some component', () => {
|
describe('some component', () => {
|
||||||
afterEach((done: Function) => { db.reset().then((_: any) => done()); });
|
afterEach((done) => { db.reset().then((_) => done()); });
|
||||||
it('uses the db', () => {
|
it('uses the db', () => {
|
||||||
// This test can leave the database in a dirty state.
|
// This test can leave the database in a dirty state.
|
||||||
// The afterEach will ensure it gets reset.
|
// The afterEach will ensure it gets reset.
|
||||||
|
@ -141,7 +141,6 @@ export {URLSearchParams} from './src/http/url_search_params';
|
|||||||
* // Send a response to the request
|
* // Send a response to the request
|
||||||
* connection.mockRespond(response);
|
* connection.mockRespond(response);
|
||||||
* });
|
* });
|
||||||
* }
|
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* http.get('people.json').observer({
|
* http.get('people.json').observer({
|
||||||
@ -157,8 +156,7 @@ export const HTTP_PROVIDERS: any[] = [
|
|||||||
// issue: https://github.com/angular/angular/issues/3183
|
// issue: https://github.com/angular/angular/issues/3183
|
||||||
provide(Http,
|
provide(Http,
|
||||||
{
|
{
|
||||||
useFactory: (xhrBackend: XHRBackend, requestOptions: RequestOptions) =>
|
useFactory: (xhrBackend, requestOptions) => new Http(xhrBackend, requestOptions),
|
||||||
new Http(xhrBackend, requestOptions),
|
|
||||||
deps: [XHRBackend, RequestOptions]
|
deps: [XHRBackend, RequestOptions]
|
||||||
}),
|
}),
|
||||||
BrowserXhr,
|
BrowserXhr,
|
||||||
@ -270,7 +268,6 @@ export const HTTP_BINDINGS = HTTP_PROVIDERS;
|
|||||||
* // Send a response to the request
|
* // Send a response to the request
|
||||||
* connection.mockRespond(response);
|
* connection.mockRespond(response);
|
||||||
* });
|
* });
|
||||||
* }
|
|
||||||
* });
|
* });
|
||||||
|
|
||||||
* jsonp.get('people.json').observer({
|
* jsonp.get('people.json').observer({
|
||||||
@ -286,8 +283,7 @@ export const JSONP_PROVIDERS: any[] = [
|
|||||||
// issue: https://github.com/angular/angular/issues/3183
|
// issue: https://github.com/angular/angular/issues/3183
|
||||||
provide(Jsonp,
|
provide(Jsonp,
|
||||||
{
|
{
|
||||||
useFactory: (jsonpBackend: JSONPBackend, requestOptions: RequestOptions) =>
|
useFactory: (jsonpBackend, requestOptions) => new Jsonp(jsonpBackend, requestOptions),
|
||||||
new Jsonp(jsonpBackend, requestOptions),
|
|
||||||
deps: [JSONPBackend, RequestOptions]
|
deps: [JSONPBackend, RequestOptions]
|
||||||
}),
|
}),
|
||||||
BrowserJsonp,
|
BrowserJsonp,
|
||||||
|
36
modules/angular2/manual_typings/globals-es6.d.ts
vendored
Normal file
36
modules/angular2/manual_typings/globals-es6.d.ts
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Declarations angular depends on for compilation to ES6.
|
||||||
|
* This file is also used to propagate our transitive typings
|
||||||
|
* to users.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// <reference path="../typings/zone/zone.d.ts"/>
|
||||||
|
/// <reference path="../typings/hammerjs/hammerjs.d.ts"/>
|
||||||
|
|
||||||
|
// TODO: ideally the node.d.ts reference should be scoped only for files that need and not to all
|
||||||
|
// the code including client code
|
||||||
|
/// <reference path="../typings/node/node.d.ts" />
|
||||||
|
|
||||||
|
declare var assert: any;
|
||||||
|
|
||||||
|
|
||||||
|
interface BrowserNodeGlobal {
|
||||||
|
Object: typeof Object;
|
||||||
|
Array: typeof Array;
|
||||||
|
Map: typeof Map;
|
||||||
|
Set: typeof Set;
|
||||||
|
Date: typeof Date;
|
||||||
|
RegExp: typeof RegExp;
|
||||||
|
JSON: typeof JSON;
|
||||||
|
Math: typeof Math;
|
||||||
|
assert(condition: any): void;
|
||||||
|
Reflect: any;
|
||||||
|
zone: Zone;
|
||||||
|
getAngularTestability: Function;
|
||||||
|
getAllAngularTestabilities: Function;
|
||||||
|
frameworkStabilizers: Array<Function>;
|
||||||
|
setTimeout: Function;
|
||||||
|
clearTimeout: Function;
|
||||||
|
setInterval: Function;
|
||||||
|
clearInterval: Function;
|
||||||
|
}
|
55
modules/angular2/manual_typings/globals.d.ts
vendored
55
modules/angular2/manual_typings/globals.d.ts
vendored
@ -1,52 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Subset of es6-shim typings.
|
* Declarations angular depends on for compilation to ES6.
|
||||||
* Angular should not require use of ES6 runtime but some API usages are already present.
|
* This file is also used to propagate our transitive typings
|
||||||
* See https://github.com/angular/angular/issues/5242
|
* to users.
|
||||||
* TODO(alexeagle): remove methods below which may not be present in targeted browser
|
|
||||||
*/
|
*/
|
||||||
|
/// <reference path="../typings/es6-shim/es6-shim.d.ts"/>
|
||||||
declare type PromiseConstructor = typeof Promise;
|
/// <reference path="./globals-es6.d.ts"/>
|
||||||
|
|
||||||
interface String {
|
|
||||||
/**
|
|
||||||
* Returns true if the sequence of elements of searchString converted to a String is the
|
|
||||||
* same as the corresponding elements of this object (converted to a String) starting at
|
|
||||||
* position. Otherwise returns false.
|
|
||||||
*/
|
|
||||||
startsWith(searchString: string, position?: number): boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the sequence of elements of searchString converted to a String is the
|
|
||||||
* same as the corresponding elements of this object (converted to a String) starting at
|
|
||||||
* endPosition – length(this). Otherwise returns false.
|
|
||||||
*/
|
|
||||||
endsWith(searchString: string, endPosition?: number): boolean;
|
|
||||||
}
|
|
||||||
interface Array<T> {
|
|
||||||
/**
|
|
||||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
|
||||||
* otherwise.
|
|
||||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
|
||||||
* order, until it finds one where predicate returns true. If such an element is found, find
|
|
||||||
* immediately returns that element value. Otherwise, find returns undefined.
|
|
||||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
|
||||||
* predicate. If it is not provided, undefined is used instead.
|
|
||||||
*/
|
|
||||||
find(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): T;
|
|
||||||
/**
|
|
||||||
* Returns the this object after filling the section identified by start and end with value
|
|
||||||
* @param value value to fill array section with
|
|
||||||
* @param start index to start filling the array at. If start is negative, it is treated as
|
|
||||||
* length+start where length is the length of the array.
|
|
||||||
* @param end index to stop filling the array at. If end is negative, it is treated as
|
|
||||||
* length+end.
|
|
||||||
*/
|
|
||||||
fill(value: T, start?: number, end?: number): T[];
|
|
||||||
}
|
|
||||||
interface NumberConstructor {
|
|
||||||
/**
|
|
||||||
* Returns true if the value passed is an integer, false otherwise.
|
|
||||||
* @param number A numeric value.
|
|
||||||
*/
|
|
||||||
isInteger(number: number): boolean;
|
|
||||||
}
|
|
||||||
|
@ -13,6 +13,7 @@ export {
|
|||||||
} from 'angular2/src/platform/browser_common';
|
} from 'angular2/src/platform/browser_common';
|
||||||
|
|
||||||
import {Type, isPresent, CONST_EXPR} from 'angular2/src/facade/lang';
|
import {Type, isPresent, CONST_EXPR} from 'angular2/src/facade/lang';
|
||||||
|
import {Promise} from 'angular2/src/facade/promise';
|
||||||
import {
|
import {
|
||||||
BROWSER_PROVIDERS,
|
BROWSER_PROVIDERS,
|
||||||
BROWSER_APP_COMMON_PROVIDERS
|
BROWSER_APP_COMMON_PROVIDERS
|
||||||
|
@ -12,6 +12,7 @@ export {
|
|||||||
} from 'angular2/src/platform/browser_common';
|
} from 'angular2/src/platform/browser_common';
|
||||||
|
|
||||||
import {Type, isPresent} from 'angular2/src/facade/lang';
|
import {Type, isPresent} from 'angular2/src/facade/lang';
|
||||||
|
import {Promise} from 'angular2/src/facade/promise';
|
||||||
import {
|
import {
|
||||||
BROWSER_PROVIDERS,
|
BROWSER_PROVIDERS,
|
||||||
BROWSER_APP_COMMON_PROVIDERS
|
BROWSER_APP_COMMON_PROVIDERS
|
||||||
|
@ -18,12 +18,12 @@ dependencies:
|
|||||||
logging: '>=0.9.0 <0.12.0'
|
logging: '>=0.9.0 <0.12.0'
|
||||||
observe: '^0.13.1'
|
observe: '^0.13.1'
|
||||||
protobuf: '^0.5.0'
|
protobuf: '^0.5.0'
|
||||||
|
quiver: '^0.21.4'
|
||||||
source_span: '^1.0.0'
|
source_span: '^1.0.0'
|
||||||
stack_trace: '^1.1.1'
|
stack_trace: '^1.1.1'
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
code_transformers: '>=0.2.9+4 <0.4.0'
|
code_transformers: '>=0.2.9+4 <0.4.0'
|
||||||
guinness: '^0.1.18'
|
guinness: '^0.1.18'
|
||||||
quiver: '^0.21.4'
|
|
||||||
test: '^0.12.6'
|
test: '^0.12.6'
|
||||||
transformers:
|
transformers:
|
||||||
- angular2
|
- angular2
|
||||||
|
@ -52,7 +52,7 @@ export class Animation {
|
|||||||
this.startTime = DateWrapper.toMillis(DateWrapper.now());
|
this.startTime = DateWrapper.toMillis(DateWrapper.now());
|
||||||
this._stringPrefix = DOM.getAnimationPrefix();
|
this._stringPrefix = DOM.getAnimationPrefix();
|
||||||
this.setup();
|
this.setup();
|
||||||
this.wait((timestamp: any) => this.start());
|
this.wait(timestamp => this.start());
|
||||||
}
|
}
|
||||||
|
|
||||||
wait(callback: Function) {
|
wait(callback: Function) {
|
||||||
@ -97,7 +97,7 @@ export class Animation {
|
|||||||
* @param styles
|
* @param styles
|
||||||
*/
|
*/
|
||||||
applyStyles(styles: {[key: string]: any}): void {
|
applyStyles(styles: {[key: string]: any}): void {
|
||||||
StringMapWrapper.forEach(styles, (value: any, key: string) => {
|
StringMapWrapper.forEach(styles, (value, key) => {
|
||||||
var dashCaseKey = camelCaseToDashCase(key);
|
var dashCaseKey = camelCaseToDashCase(key);
|
||||||
if (isPresent(DOM.getStyle(this.element, dashCaseKey))) {
|
if (isPresent(DOM.getStyle(this.element, dashCaseKey))) {
|
||||||
DOM.setStyle(this.element, dashCaseKey, value.toString());
|
DOM.setStyle(this.element, dashCaseKey, value.toString());
|
||||||
|
@ -17,7 +17,7 @@ export class BrowserDetails {
|
|||||||
DOM.setAttribute(div, 'style', `position: absolute; top: -9999px; left: -9999px; width: 1px;
|
DOM.setAttribute(div, 'style', `position: absolute; top: -9999px; left: -9999px; width: 1px;
|
||||||
height: 1px; transition: all 1ms linear 1ms;`);
|
height: 1px; transition: all 1ms linear 1ms;`);
|
||||||
// Firefox requires that we wait for 2 frames for some reason
|
// Firefox requires that we wait for 2 frames for some reason
|
||||||
this.raf((timestamp: any) => {
|
this.raf(timestamp => {
|
||||||
DOM.on(div, 'transitionend', (event: any) => {
|
DOM.on(div, 'transitionend', (event: any) => {
|
||||||
var elapsed = Math.round(event.elapsedTime * 1000);
|
var elapsed = Math.round(event.elapsedTime * 1000);
|
||||||
this.elapsedTimeIncludesDelay = elapsed == 2;
|
this.elapsedTimeIncludesDelay = elapsed == 2;
|
||||||
@ -37,8 +37,7 @@ class RafQueue {
|
|||||||
currentFrameId: number;
|
currentFrameId: number;
|
||||||
constructor(public callback: Function, public frames: number) { this._raf(); }
|
constructor(public callback: Function, public frames: number) { this._raf(); }
|
||||||
private _raf() {
|
private _raf() {
|
||||||
this.currentFrameId =
|
this.currentFrameId = DOM.requestAnimationFrame(timestamp => this._nextFrame(timestamp));
|
||||||
DOM.requestAnimationFrame((timestamp: number) => this._nextFrame(timestamp));
|
|
||||||
}
|
}
|
||||||
private _nextFrame(timestamp: number) {
|
private _nextFrame(timestamp: number) {
|
||||||
this.frames--;
|
this.frames--;
|
||||||
|
@ -10,10 +10,6 @@ import {
|
|||||||
TrackByFn
|
TrackByFn
|
||||||
} from 'angular2/core';
|
} from 'angular2/core';
|
||||||
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||||
import {
|
|
||||||
DefaultIterableDiffer,
|
|
||||||
CollectionChangeRecord
|
|
||||||
} from "../../core/change_detection/differs/default_iterable_differ";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `NgFor` directive instantiates a template once per item from an iterable. The context for
|
* The `NgFor` directive instantiates a template once per item from an iterable. The context for
|
||||||
@ -96,19 +92,19 @@ export class NgFor implements DoCheck {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _applyChanges(changes: DefaultIterableDiffer) {
|
private _applyChanges(changes) {
|
||||||
// TODO(rado): check if change detection can produce a change record that is
|
// TODO(rado): check if change detection can produce a change record that is
|
||||||
// easier to consume than current.
|
// easier to consume than current.
|
||||||
var recordViewTuples: RecordViewTuple[] = [];
|
var recordViewTuples = [];
|
||||||
changes.forEachRemovedItem((removedRecord: CollectionChangeRecord) =>
|
changes.forEachRemovedItem((removedRecord) =>
|
||||||
recordViewTuples.push(new RecordViewTuple(removedRecord, null)));
|
recordViewTuples.push(new RecordViewTuple(removedRecord, null)));
|
||||||
|
|
||||||
changes.forEachMovedItem((movedRecord: CollectionChangeRecord) =>
|
changes.forEachMovedItem((movedRecord) =>
|
||||||
recordViewTuples.push(new RecordViewTuple(movedRecord, null)));
|
recordViewTuples.push(new RecordViewTuple(movedRecord, null)));
|
||||||
|
|
||||||
var insertTuples = this._bulkRemove(recordViewTuples);
|
var insertTuples = this._bulkRemove(recordViewTuples);
|
||||||
|
|
||||||
changes.forEachAddedItem((addedRecord: CollectionChangeRecord) =>
|
changes.forEachAddedItem((addedRecord) =>
|
||||||
insertTuples.push(new RecordViewTuple(addedRecord, null)));
|
insertTuples.push(new RecordViewTuple(addedRecord, null)));
|
||||||
|
|
||||||
this._bulkInsert(insertTuples);
|
this._bulkInsert(insertTuples);
|
||||||
@ -121,14 +117,9 @@ export class NgFor implements DoCheck {
|
|||||||
var viewRef = <EmbeddedViewRef>this._viewContainer.get(i);
|
var viewRef = <EmbeddedViewRef>this._viewContainer.get(i);
|
||||||
viewRef.setLocal('last', i === ilen - 1);
|
viewRef.setLocal('last', i === ilen - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
changes.forEachIdentityChange((record) => {
|
|
||||||
var viewRef = <EmbeddedViewRef>this._viewContainer.get(record.currentIndex);
|
|
||||||
viewRef.setLocal('\$implicit', record.item);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _perViewChange(view: EmbeddedViewRef, record: CollectionChangeRecord) {
|
private _perViewChange(view, record) {
|
||||||
view.setLocal('\$implicit', record.item);
|
view.setLocal('\$implicit', record.item);
|
||||||
view.setLocal('index', record.currentIndex);
|
view.setLocal('index', record.currentIndex);
|
||||||
view.setLocal('even', (record.currentIndex % 2 == 0));
|
view.setLocal('even', (record.currentIndex % 2 == 0));
|
||||||
@ -136,9 +127,8 @@ export class NgFor implements DoCheck {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _bulkRemove(tuples: RecordViewTuple[]): RecordViewTuple[] {
|
private _bulkRemove(tuples: RecordViewTuple[]): RecordViewTuple[] {
|
||||||
tuples.sort((a: RecordViewTuple, b: RecordViewTuple) =>
|
tuples.sort((a, b) => a.record.previousIndex - b.record.previousIndex);
|
||||||
a.record.previousIndex - b.record.previousIndex);
|
var movedTuples = [];
|
||||||
var movedTuples: RecordViewTuple[] = [];
|
|
||||||
for (var i = tuples.length - 1; i >= 0; i--) {
|
for (var i = tuples.length - 1; i >= 0; i--) {
|
||||||
var tuple = tuples[i];
|
var tuple = tuples[i];
|
||||||
// separate moved views from removed views.
|
// separate moved views from removed views.
|
||||||
@ -170,7 +160,7 @@ export class NgFor implements DoCheck {
|
|||||||
class RecordViewTuple {
|
class RecordViewTuple {
|
||||||
view: EmbeddedViewRef;
|
view: EmbeddedViewRef;
|
||||||
record: any;
|
record: any;
|
||||||
constructor(record: any, view: EmbeddedViewRef) {
|
constructor(record, view) {
|
||||||
this.record = record;
|
this.record = record;
|
||||||
this.view = view;
|
this.view = view;
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ export class NgIf {
|
|||||||
|
|
||||||
constructor(private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef) {}
|
constructor(private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef) {}
|
||||||
|
|
||||||
set ngIf(newCondition: any /* boolean */) {
|
set ngIf(newCondition /* boolean */) {
|
||||||
if (newCondition && (isBlank(this._prevCondition) || !this._prevCondition)) {
|
if (newCondition && (isBlank(this._prevCondition) || !this._prevCondition)) {
|
||||||
this._prevCondition = true;
|
this._prevCondition = true;
|
||||||
this._viewContainer.createEmbeddedView(this._templateRef);
|
this._viewContainer.createEmbeddedView(this._templateRef);
|
||||||
|
@ -7,7 +7,6 @@ import {
|
|||||||
Renderer
|
Renderer
|
||||||
} from 'angular2/core';
|
} from 'angular2/core';
|
||||||
import {isPresent, isBlank, print} from 'angular2/src/facade/lang';
|
import {isPresent, isBlank, print} from 'angular2/src/facade/lang';
|
||||||
import {KVChangeRecord} from "../../core/change_detection/differs/default_keyvalue_differ";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `NgStyle` directive changes styles based on a result of expression evaluation.
|
* The `NgStyle` directive changes styles based on a result of expression evaluation.
|
||||||
@ -63,14 +62,14 @@ import {KVChangeRecord} from "../../core/change_detection/differs/default_keyval
|
|||||||
@Directive({selector: '[ngStyle]', inputs: ['rawStyle: ngStyle']})
|
@Directive({selector: '[ngStyle]', inputs: ['rawStyle: ngStyle']})
|
||||||
export class NgStyle implements DoCheck {
|
export class NgStyle implements DoCheck {
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_rawStyle: {[key: string]: string};
|
_rawStyle;
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_differ: KeyValueDiffer;
|
_differ: KeyValueDiffer;
|
||||||
|
|
||||||
constructor(private _differs: KeyValueDiffers, private _ngEl: ElementRef,
|
constructor(private _differs: KeyValueDiffers, private _ngEl: ElementRef,
|
||||||
private _renderer: Renderer) {}
|
private _renderer: Renderer) {}
|
||||||
|
|
||||||
set rawStyle(v: {[key: string]: string}) {
|
set rawStyle(v) {
|
||||||
this._rawStyle = v;
|
this._rawStyle = v;
|
||||||
if (isBlank(this._differ) && isPresent(v)) {
|
if (isBlank(this._differ) && isPresent(v)) {
|
||||||
this._differ = this._differs.find(this._rawStyle).create(null);
|
this._differ = this._differs.find(this._rawStyle).create(null);
|
||||||
@ -87,11 +86,9 @@ export class NgStyle implements DoCheck {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _applyChanges(changes: any): void {
|
private _applyChanges(changes: any): void {
|
||||||
changes.forEachAddedItem(
|
changes.forEachAddedItem((record) => { this._setStyle(record.key, record.currentValue); });
|
||||||
(record: KVChangeRecord) => { this._setStyle(record.key, record.currentValue); });
|
changes.forEachChangedItem((record) => { this._setStyle(record.key, record.currentValue); });
|
||||||
changes.forEachChangedItem(
|
changes.forEachRemovedItem((record) => { this._setStyle(record.key, null); });
|
||||||
(record: KVChangeRecord) => { this._setStyle(record.key, record.currentValue); });
|
|
||||||
changes.forEachRemovedItem((record: KVChangeRecord) => { this._setStyle(record.key, null); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setStyle(name: string, val: string): void {
|
private _setStyle(name: string, val: string): void {
|
||||||
|
@ -76,7 +76,7 @@ export class NgSwitch {
|
|||||||
private _valueViews = new Map<any, SwitchView[]>();
|
private _valueViews = new Map<any, SwitchView[]>();
|
||||||
private _activeViews: SwitchView[] = [];
|
private _activeViews: SwitchView[] = [];
|
||||||
|
|
||||||
set ngSwitch(value: any) {
|
set ngSwitch(value) {
|
||||||
// Empty the currently active ViewContainers
|
// Empty the currently active ViewContainers
|
||||||
this._emptyAllActiveViews();
|
this._emptyAllActiveViews();
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ export class NgSwitch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_onWhenValueChanged(oldWhen: any, newWhen: any, view: SwitchView): void {
|
_onWhenValueChanged(oldWhen, newWhen, view: SwitchView): void {
|
||||||
this._deregisterView(oldWhen, view);
|
this._deregisterView(oldWhen, view);
|
||||||
this._registerView(newWhen, view);
|
this._registerView(newWhen, view);
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ export class NgSwitch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_registerView(value: any, view: SwitchView): void {
|
_registerView(value, view: SwitchView): void {
|
||||||
var views = this._valueViews.get(value);
|
var views = this._valueViews.get(value);
|
||||||
if (isBlank(views)) {
|
if (isBlank(views)) {
|
||||||
views = [];
|
views = [];
|
||||||
@ -147,7 +147,7 @@ export class NgSwitch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_deregisterView(value: any, view: SwitchView): void {
|
_deregisterView(value, view: SwitchView): void {
|
||||||
// `_WHEN_DEFAULT` is used a marker for non-registered whens
|
// `_WHEN_DEFAULT` is used a marker for non-registered whens
|
||||||
if (value === _WHEN_DEFAULT) return;
|
if (value === _WHEN_DEFAULT) return;
|
||||||
var views = this._valueViews.get(value);
|
var views = this._valueViews.get(value);
|
||||||
@ -182,7 +182,7 @@ export class NgSwitchWhen {
|
|||||||
this._view = new SwitchView(viewContainer, templateRef);
|
this._view = new SwitchView(viewContainer, templateRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
set ngSwitchWhen(value: any) {
|
set ngSwitchWhen(value) {
|
||||||
this._switch._onWhenValueChanged(this._value, value, this._view);
|
this._switch._onWhenValueChanged(this._value, value, this._view);
|
||||||
this._value = value;
|
this._value = value;
|
||||||
}
|
}
|
||||||
|
@ -31,34 +31,12 @@ export {
|
|||||||
NgSelectOption,
|
NgSelectOption,
|
||||||
SelectControlValueAccessor
|
SelectControlValueAccessor
|
||||||
} from './forms/directives/select_control_value_accessor';
|
} from './forms/directives/select_control_value_accessor';
|
||||||
export {FORM_DIRECTIVES, RadioButtonState} from './forms/directives';
|
export {FORM_DIRECTIVES} from './forms/directives';
|
||||||
export {NG_VALIDATORS, NG_ASYNC_VALIDATORS, Validators} from './forms/validators';
|
export {NG_VALIDATORS, NG_ASYNC_VALIDATORS, Validators} from './forms/validators';
|
||||||
export {
|
export {
|
||||||
RequiredValidator,
|
RequiredValidator,
|
||||||
MinLengthValidator,
|
MinLengthValidator,
|
||||||
MaxLengthValidator,
|
MaxLengthValidator,
|
||||||
PatternValidator,
|
|
||||||
Validator
|
Validator
|
||||||
} from './forms/directives/validators';
|
} from './forms/directives/validators';
|
||||||
export {FormBuilder} from './forms/form_builder';
|
export {FormBuilder, FORM_PROVIDERS, FORM_BINDINGS} from './forms/form_builder';
|
||||||
import {FormBuilder} from './forms/form_builder';
|
|
||||||
import {RadioControlRegistry} from './forms/directives/radio_control_value_accessor';
|
|
||||||
import {Type, CONST_EXPR} from 'angular2/src/facade/lang';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shorthand set of providers used for building Angular forms.
|
|
||||||
*
|
|
||||||
* ### Example
|
|
||||||
*
|
|
||||||
* ```typescript
|
|
||||||
* bootstrap(MyApp, [FORM_PROVIDERS]);
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export const FORM_PROVIDERS: Type[] = CONST_EXPR([FormBuilder, RadioControlRegistry]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See {@link FORM_PROVIDERS} instead.
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export const FORM_BINDINGS = FORM_PROVIDERS;
|
|
@ -8,18 +8,12 @@ import {NgForm} from './directives/ng_form';
|
|||||||
import {DefaultValueAccessor} from './directives/default_value_accessor';
|
import {DefaultValueAccessor} from './directives/default_value_accessor';
|
||||||
import {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';
|
import {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';
|
||||||
import {NumberValueAccessor} from './directives/number_value_accessor';
|
import {NumberValueAccessor} from './directives/number_value_accessor';
|
||||||
import {RadioControlValueAccessor} from './directives/radio_control_value_accessor';
|
|
||||||
import {NgControlStatus} from './directives/ng_control_status';
|
import {NgControlStatus} from './directives/ng_control_status';
|
||||||
import {
|
import {
|
||||||
SelectControlValueAccessor,
|
SelectControlValueAccessor,
|
||||||
NgSelectOption
|
NgSelectOption
|
||||||
} from './directives/select_control_value_accessor';
|
} from './directives/select_control_value_accessor';
|
||||||
import {
|
import {RequiredValidator, MinLengthValidator, MaxLengthValidator} from './directives/validators';
|
||||||
RequiredValidator,
|
|
||||||
MinLengthValidator,
|
|
||||||
MaxLengthValidator,
|
|
||||||
PatternValidator
|
|
||||||
} from './directives/validators';
|
|
||||||
|
|
||||||
export {NgControlName} from './directives/ng_control_name';
|
export {NgControlName} from './directives/ng_control_name';
|
||||||
export {NgFormControl} from './directives/ng_form_control';
|
export {NgFormControl} from './directives/ng_form_control';
|
||||||
@ -29,22 +23,13 @@ export {NgFormModel} from './directives/ng_form_model';
|
|||||||
export {NgForm} from './directives/ng_form';
|
export {NgForm} from './directives/ng_form';
|
||||||
export {DefaultValueAccessor} from './directives/default_value_accessor';
|
export {DefaultValueAccessor} from './directives/default_value_accessor';
|
||||||
export {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';
|
export {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';
|
||||||
export {
|
|
||||||
RadioControlValueAccessor,
|
|
||||||
RadioButtonState
|
|
||||||
} from './directives/radio_control_value_accessor';
|
|
||||||
export {NumberValueAccessor} from './directives/number_value_accessor';
|
export {NumberValueAccessor} from './directives/number_value_accessor';
|
||||||
export {NgControlStatus} from './directives/ng_control_status';
|
export {NgControlStatus} from './directives/ng_control_status';
|
||||||
export {
|
export {
|
||||||
SelectControlValueAccessor,
|
SelectControlValueAccessor,
|
||||||
NgSelectOption
|
NgSelectOption
|
||||||
} from './directives/select_control_value_accessor';
|
} from './directives/select_control_value_accessor';
|
||||||
export {
|
export {RequiredValidator, MinLengthValidator, MaxLengthValidator} from './directives/validators';
|
||||||
RequiredValidator,
|
|
||||||
MinLengthValidator,
|
|
||||||
MaxLengthValidator,
|
|
||||||
PatternValidator
|
|
||||||
} from './directives/validators';
|
|
||||||
export {NgControl} from './directives/ng_control';
|
export {NgControl} from './directives/ng_control';
|
||||||
export {ControlValueAccessor} from './directives/control_value_accessor';
|
export {ControlValueAccessor} from './directives/control_value_accessor';
|
||||||
|
|
||||||
@ -78,11 +63,9 @@ export const FORM_DIRECTIVES: Type[] = CONST_EXPR([
|
|||||||
NumberValueAccessor,
|
NumberValueAccessor,
|
||||||
CheckboxControlValueAccessor,
|
CheckboxControlValueAccessor,
|
||||||
SelectControlValueAccessor,
|
SelectControlValueAccessor,
|
||||||
RadioControlValueAccessor,
|
|
||||||
NgControlStatus,
|
NgControlStatus,
|
||||||
|
|
||||||
RequiredValidator,
|
RequiredValidator,
|
||||||
MinLengthValidator,
|
MinLengthValidator,
|
||||||
MaxLengthValidator,
|
MaxLengthValidator
|
||||||
PatternValidator
|
|
||||||
]);
|
]);
|
||||||
|
@ -18,10 +18,10 @@ const CHECKBOX_VALUE_ACCESSOR = CONST_EXPR(new Provider(
|
|||||||
selector:
|
selector:
|
||||||
'input[type=checkbox][ngControl],input[type=checkbox][ngFormControl],input[type=checkbox][ngModel]',
|
'input[type=checkbox][ngControl],input[type=checkbox][ngFormControl],input[type=checkbox][ngModel]',
|
||||||
host: {'(change)': 'onChange($event.target.checked)', '(blur)': 'onTouched()'},
|
host: {'(change)': 'onChange($event.target.checked)', '(blur)': 'onTouched()'},
|
||||||
providers: [CHECKBOX_VALUE_ACCESSOR]
|
bindings: [CHECKBOX_VALUE_ACCESSOR]
|
||||||
})
|
})
|
||||||
export class CheckboxControlValueAccessor implements ControlValueAccessor {
|
export class CheckboxControlValueAccessor implements ControlValueAccessor {
|
||||||
onChange = (_: any) => {};
|
onChange = (_) => {};
|
||||||
onTouched = () => {};
|
onTouched = () => {};
|
||||||
|
|
||||||
constructor(private _renderer: Renderer, private _elementRef: ElementRef) {}
|
constructor(private _renderer: Renderer, private _elementRef: ElementRef) {}
|
||||||
|
@ -24,7 +24,7 @@ const DEFAULT_VALUE_ACCESSOR = CONST_EXPR(new Provider(
|
|||||||
bindings: [DEFAULT_VALUE_ACCESSOR]
|
bindings: [DEFAULT_VALUE_ACCESSOR]
|
||||||
})
|
})
|
||||||
export class DefaultValueAccessor implements ControlValueAccessor {
|
export class DefaultValueAccessor implements ControlValueAccessor {
|
||||||
onChange = (_: any) => {};
|
onChange = (_) => {};
|
||||||
onTouched = () => {};
|
onTouched = () => {};
|
||||||
|
|
||||||
constructor(private _renderer: Renderer, private _elementRef: ElementRef) {}
|
constructor(private _renderer: Renderer, private _elementRef: ElementRef) {}
|
||||||
|
@ -1,14 +1,9 @@
|
|||||||
import {Validator} from './validators';
|
import {Validator} from './validators';
|
||||||
import {Control} from "../model";
|
|
||||||
|
|
||||||
export type ctrlFunc = ((c: Control) => {
|
export function normalizeValidator(validator: Function | Validator): Function {
|
||||||
[key: string]: any
|
|
||||||
});
|
|
||||||
|
|
||||||
export function normalizeValidator(validator: (ctrlFunc | Validator)): ctrlFunc {
|
|
||||||
if ((<Validator>validator).validate !== undefined) {
|
if ((<Validator>validator).validate !== undefined) {
|
||||||
return (c: Control) => (<Validator>validator).validate(c);
|
return (c) => (<Validator>validator).validate(c);
|
||||||
} else {
|
} else {
|
||||||
return <ctrlFunc>validator;
|
return <Function>validator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ const NUMBER_VALUE_ACCESSOR = CONST_EXPR(new Provider(
|
|||||||
bindings: [NUMBER_VALUE_ACCESSOR]
|
bindings: [NUMBER_VALUE_ACCESSOR]
|
||||||
})
|
})
|
||||||
export class NumberValueAccessor implements ControlValueAccessor {
|
export class NumberValueAccessor implements ControlValueAccessor {
|
||||||
onChange = (_: any) => {};
|
onChange = (_) => {};
|
||||||
onTouched = () => {};
|
onTouched = () => {};
|
||||||
|
|
||||||
constructor(private _renderer: Renderer, private _elementRef: ElementRef) {}
|
constructor(private _renderer: Renderer, private _elementRef: ElementRef) {}
|
||||||
|
@ -1,126 +0,0 @@
|
|||||||
import {
|
|
||||||
Directive,
|
|
||||||
ElementRef,
|
|
||||||
Renderer,
|
|
||||||
Self,
|
|
||||||
forwardRef,
|
|
||||||
Provider,
|
|
||||||
Attribute,
|
|
||||||
Input,
|
|
||||||
OnInit,
|
|
||||||
OnDestroy,
|
|
||||||
Injector,
|
|
||||||
Injectable
|
|
||||||
} from 'angular2/core';
|
|
||||||
import {
|
|
||||||
NG_VALUE_ACCESSOR,
|
|
||||||
ControlValueAccessor
|
|
||||||
} from 'angular2/src/common/forms/directives/control_value_accessor';
|
|
||||||
import {NgControl} from 'angular2/src/common/forms/directives/ng_control';
|
|
||||||
import {CONST_EXPR, looseIdentical, isPresent} from 'angular2/src/facade/lang';
|
|
||||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
|
||||||
|
|
||||||
const RADIO_VALUE_ACCESSOR = CONST_EXPR(new Provider(
|
|
||||||
NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => RadioControlValueAccessor), multi: true}));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal class used by Angular to uncheck radio buttons with the matching name.
|
|
||||||
*/
|
|
||||||
@Injectable()
|
|
||||||
export class RadioControlRegistry {
|
|
||||||
private _accessors: any[] = [];
|
|
||||||
|
|
||||||
add(control: NgControl, accessor: RadioControlValueAccessor) {
|
|
||||||
this._accessors.push([control, accessor]);
|
|
||||||
}
|
|
||||||
|
|
||||||
remove(accessor: RadioControlValueAccessor) {
|
|
||||||
var indexToRemove = -1;
|
|
||||||
for (var i = 0; i < this._accessors.length; ++i) {
|
|
||||||
if (this._accessors[i][1] === accessor) {
|
|
||||||
indexToRemove = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ListWrapper.removeAt(this._accessors, indexToRemove);
|
|
||||||
}
|
|
||||||
|
|
||||||
select(accessor: RadioControlValueAccessor) {
|
|
||||||
this._accessors.forEach((c) => {
|
|
||||||
if (c[0].control.root === accessor._control.control.root && c[1] !== accessor) {
|
|
||||||
c[1].fireUncheck();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The value provided by the forms API for radio buttons.
|
|
||||||
*/
|
|
||||||
export class RadioButtonState {
|
|
||||||
constructor(public checked: boolean, public value: string) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The accessor for writing a radio control value and listening to changes that is used by the
|
|
||||||
* {@link NgModel}, {@link NgFormControl}, and {@link NgControlName} directives.
|
|
||||||
*
|
|
||||||
* ### Example
|
|
||||||
* ```
|
|
||||||
* @Component({
|
|
||||||
* template: `
|
|
||||||
* <input type="radio" name="food" [(ngModel)]="foodChicken">
|
|
||||||
* <input type="radio" name="food" [(ngModel)]="foodFish">
|
|
||||||
* `
|
|
||||||
* })
|
|
||||||
* class FoodCmp {
|
|
||||||
* foodChicken = new RadioButtonState(true, "chicken");
|
|
||||||
* foodFish = new RadioButtonState(false, "fish");
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
@Directive({
|
|
||||||
selector:
|
|
||||||
'input[type=radio][ngControl],input[type=radio][ngFormControl],input[type=radio][ngModel]',
|
|
||||||
host: {'(change)': 'onChange()', '(blur)': 'onTouched()'},
|
|
||||||
providers: [RADIO_VALUE_ACCESSOR]
|
|
||||||
})
|
|
||||||
export class RadioControlValueAccessor implements ControlValueAccessor,
|
|
||||||
OnDestroy, OnInit {
|
|
||||||
_state: RadioButtonState;
|
|
||||||
_control: NgControl;
|
|
||||||
@Input() name: string;
|
|
||||||
_fn: Function;
|
|
||||||
onChange = () => {};
|
|
||||||
onTouched = () => {};
|
|
||||||
|
|
||||||
constructor(private _renderer: Renderer, private _elementRef: ElementRef,
|
|
||||||
private _registry: RadioControlRegistry, private _injector: Injector) {}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
this._control = this._injector.get(NgControl);
|
|
||||||
this._registry.add(this._control, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy(): void { this._registry.remove(this); }
|
|
||||||
|
|
||||||
writeValue(value: any): void {
|
|
||||||
this._state = value;
|
|
||||||
if (isPresent(value) && value.checked) {
|
|
||||||
this._renderer.setElementProperty(this._elementRef.nativeElement, 'checked', true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registerOnChange(fn: (_: any) => {}): void {
|
|
||||||
this._fn = fn;
|
|
||||||
this.onChange = () => {
|
|
||||||
fn(new RadioButtonState(true, this._state.value));
|
|
||||||
this._registry.select(this);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fireUncheck(): void { this._fn(new RadioButtonState(false, this._state.value)); }
|
|
||||||
|
|
||||||
registerOnTouched(fn: () => {}): void { this.onTouched = fn; }
|
|
||||||
}
|
|
@ -41,7 +41,7 @@ export class NgSelectOption {
|
|||||||
})
|
})
|
||||||
export class SelectControlValueAccessor implements ControlValueAccessor {
|
export class SelectControlValueAccessor implements ControlValueAccessor {
|
||||||
value: string;
|
value: string;
|
||||||
onChange = (_: any) => {};
|
onChange = (_) => {};
|
||||||
onTouched = () => {};
|
onTouched = () => {};
|
||||||
|
|
||||||
constructor(private _renderer: Renderer, private _elementRef: ElementRef,
|
constructor(private _renderer: Renderer, private _elementRef: ElementRef,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {isBlank, isPresent, looseIdentical, hasConstructor} from 'angular2/src/facade/lang';
|
import {isBlank, isPresent, looseIdentical} from 'angular2/src/facade/lang';
|
||||||
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
||||||
|
|
||||||
import {ControlContainer} from './control_container';
|
import {ControlContainer} from './control_container';
|
||||||
@ -13,7 +13,6 @@ import {DefaultValueAccessor} from './default_value_accessor';
|
|||||||
import {NumberValueAccessor} from './number_value_accessor';
|
import {NumberValueAccessor} from './number_value_accessor';
|
||||||
import {CheckboxControlValueAccessor} from './checkbox_value_accessor';
|
import {CheckboxControlValueAccessor} from './checkbox_value_accessor';
|
||||||
import {SelectControlValueAccessor} from './select_control_value_accessor';
|
import {SelectControlValueAccessor} from './select_control_value_accessor';
|
||||||
import {RadioControlValueAccessor} from './radio_control_value_accessor';
|
|
||||||
import {normalizeValidator} from './normalize_validator';
|
import {normalizeValidator} from './normalize_validator';
|
||||||
|
|
||||||
|
|
||||||
@ -32,14 +31,14 @@ export function setUpControl(control: Control, dir: NgControl): void {
|
|||||||
dir.valueAccessor.writeValue(control.value);
|
dir.valueAccessor.writeValue(control.value);
|
||||||
|
|
||||||
// view -> model
|
// view -> model
|
||||||
dir.valueAccessor.registerOnChange((newValue: any) => {
|
dir.valueAccessor.registerOnChange(newValue => {
|
||||||
dir.viewToModelUpdate(newValue);
|
dir.viewToModelUpdate(newValue);
|
||||||
control.updateValue(newValue, {emitModelToViewChange: false});
|
control.updateValue(newValue, {emitModelToViewChange: false});
|
||||||
control.markAsDirty();
|
control.markAsDirty();
|
||||||
});
|
});
|
||||||
|
|
||||||
// model -> view
|
// model -> view
|
||||||
control.registerOnChange((newValue: any) => dir.valueAccessor.writeValue(newValue));
|
control.registerOnChange(newValue => dir.valueAccessor.writeValue(newValue));
|
||||||
|
|
||||||
// touched
|
// touched
|
||||||
dir.valueAccessor.registerOnTouched(() => control.markAsTouched());
|
dir.valueAccessor.registerOnTouched(() => control.markAsTouched());
|
||||||
@ -78,17 +77,15 @@ export function selectValueAccessor(dir: NgControl,
|
|||||||
valueAccessors: ControlValueAccessor[]): ControlValueAccessor {
|
valueAccessors: ControlValueAccessor[]): ControlValueAccessor {
|
||||||
if (isBlank(valueAccessors)) return null;
|
if (isBlank(valueAccessors)) return null;
|
||||||
|
|
||||||
var defaultAccessor: ControlValueAccessor;
|
var defaultAccessor;
|
||||||
var builtinAccessor: ControlValueAccessor;
|
var builtinAccessor;
|
||||||
var customAccessor: ControlValueAccessor;
|
var customAccessor;
|
||||||
valueAccessors.forEach((v: ControlValueAccessor) => {
|
valueAccessors.forEach(v => {
|
||||||
if (hasConstructor(v, DefaultValueAccessor)) {
|
if (v instanceof DefaultValueAccessor) {
|
||||||
defaultAccessor = v;
|
defaultAccessor = v;
|
||||||
|
|
||||||
} else if (hasConstructor(v, CheckboxControlValueAccessor) ||
|
} else if (v instanceof CheckboxControlValueAccessor || v instanceof NumberValueAccessor ||
|
||||||
hasConstructor(v, NumberValueAccessor) ||
|
v instanceof SelectControlValueAccessor) {
|
||||||
hasConstructor(v, SelectControlValueAccessor) ||
|
|
||||||
hasConstructor(v, RadioControlValueAccessor)) {
|
|
||||||
if (isPresent(builtinAccessor))
|
if (isPresent(builtinAccessor))
|
||||||
_throwError(dir, "More than one built-in value accessor matches");
|
_throwError(dir, "More than one built-in value accessor matches");
|
||||||
builtinAccessor = v;
|
builtinAccessor = v;
|
||||||
|
@ -100,32 +100,3 @@ export class MaxLengthValidator implements Validator {
|
|||||||
|
|
||||||
validate(c: Control): {[key: string]: any} { return this._validator(c); }
|
validate(c: Control): {[key: string]: any} { return this._validator(c); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Directive that adds the `pattern` validator to any controls marked with the
|
|
||||||
* `pattern` attribute, via the {@link NG_VALIDATORS} binding. Uses attribute value
|
|
||||||
* as the regex to validate Control value against. Follows pattern attribute
|
|
||||||
* semantics; i.e. regex must match entire Control value.
|
|
||||||
*
|
|
||||||
* ### Example
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* <input [ngControl]="fullName" pattern="[a-zA-Z ]*">
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
const PATTERN_VALIDATOR = CONST_EXPR(
|
|
||||||
new Provider(NG_VALIDATORS, {useExisting: forwardRef(() => PatternValidator), multi: true}));
|
|
||||||
@Directive({
|
|
||||||
selector: '[pattern][ngControl],[pattern][ngFormControl],[pattern][ngModel]',
|
|
||||||
providers: [PATTERN_VALIDATOR]
|
|
||||||
})
|
|
||||||
export class PatternValidator implements Validator {
|
|
||||||
private _validator: Function;
|
|
||||||
|
|
||||||
constructor(@Attribute("pattern") pattern: string) {
|
|
||||||
this._validator = Validators.pattern(pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
validate(c: Control): {[key: string]: any} { return this._validator(c); }
|
|
||||||
}
|
|
||||||
|
@ -80,10 +80,9 @@ export class FormBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_reduceControls(controlsConfig: {[k: string]:
|
_reduceControls(controlsConfig: any): {[key: string]: modelModule.AbstractControl} {
|
||||||
any}): {[key: string]: modelModule.AbstractControl} {
|
|
||||||
var controls: {[key: string]: modelModule.AbstractControl} = {};
|
var controls: {[key: string]: modelModule.AbstractControl} = {};
|
||||||
StringMapWrapper.forEach(controlsConfig, (controlConfig: any, controlName: string) => {
|
StringMapWrapper.forEach(controlsConfig, (controlConfig, controlName) => {
|
||||||
controls[controlName] = this._createControl(controlConfig);
|
controls[controlName] = this._createControl(controlConfig);
|
||||||
});
|
});
|
||||||
return controls;
|
return controls;
|
||||||
@ -107,3 +106,21 @@ export class FormBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shorthand set of providers used for building Angular forms.
|
||||||
|
*
|
||||||
|
* ### Example
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* bootstrap(MyApp, [FORM_PROVIDERS]);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export const FORM_PROVIDERS: Type[] = CONST_EXPR([FormBuilder]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See {@link FORM_PROVIDERS} instead.
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
export const FORM_BINDINGS = FORM_PROVIDERS;
|
||||||
|
@ -62,7 +62,7 @@ export abstract class AbstractControl {
|
|||||||
private _pristine: boolean = true;
|
private _pristine: boolean = true;
|
||||||
private _touched: boolean = false;
|
private _touched: boolean = false;
|
||||||
private _parent: ControlGroup | ControlArray;
|
private _parent: ControlGroup | ControlArray;
|
||||||
private _asyncValidationSubscription: any;
|
private _asyncValidationSubscription;
|
||||||
|
|
||||||
constructor(public validator: Function, public asyncValidator: Function) {}
|
constructor(public validator: Function, public asyncValidator: Function) {}
|
||||||
|
|
||||||
@ -208,16 +208,6 @@ export abstract class AbstractControl {
|
|||||||
return isPresent(this.getError(errorCode, path));
|
return isPresent(this.getError(errorCode, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
get root(): AbstractControl {
|
|
||||||
let x: AbstractControl = this;
|
|
||||||
|
|
||||||
while (isPresent(x._parent)) {
|
|
||||||
x = x._parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_updateControlsErrors(): void {
|
_updateControlsErrors(): void {
|
||||||
this._status = this._calculateStatus();
|
this._status = this._calculateStatus();
|
||||||
@ -379,8 +369,7 @@ export class ControlGroup extends AbstractControl {
|
|||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_setParentForControls() {
|
_setParentForControls() {
|
||||||
StringMapWrapper.forEach(
|
StringMapWrapper.forEach(this.controls, (control, name) => { control.setParent(this); });
|
||||||
this.controls, (control: AbstractControl, name: string) => { control.setParent(this); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
@ -389,7 +378,7 @@ export class ControlGroup extends AbstractControl {
|
|||||||
/** @internal */
|
/** @internal */
|
||||||
_anyControlsHaveStatus(status: string): boolean {
|
_anyControlsHaveStatus(status: string): boolean {
|
||||||
var res = false;
|
var res = false;
|
||||||
StringMapWrapper.forEach(this.controls, (control: AbstractControl, name: string) => {
|
StringMapWrapper.forEach(this.controls, (control, name) => {
|
||||||
res = res || (this.contains(name) && control.status == status);
|
res = res || (this.contains(name) && control.status == status);
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
@ -397,8 +386,7 @@ export class ControlGroup extends AbstractControl {
|
|||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_reduceValue() {
|
_reduceValue() {
|
||||||
return this._reduceChildren(
|
return this._reduceChildren({}, (acc, control, name) => {
|
||||||
{}, (acc: {[k: string]: AbstractControl}, control: AbstractControl, name: string) => {
|
|
||||||
acc[name] = control.value;
|
acc[name] = control.value;
|
||||||
return acc;
|
return acc;
|
||||||
});
|
});
|
||||||
@ -407,7 +395,7 @@ export class ControlGroup extends AbstractControl {
|
|||||||
/** @internal */
|
/** @internal */
|
||||||
_reduceChildren(initValue: any, fn: Function) {
|
_reduceChildren(initValue: any, fn: Function) {
|
||||||
var res = initValue;
|
var res = initValue;
|
||||||
StringMapWrapper.forEach(this.controls, (control: AbstractControl, name: string) => {
|
StringMapWrapper.forEach(this.controls, (control, name) => {
|
||||||
if (this._included(name)) {
|
if (this._included(name)) {
|
||||||
res = fn(res, control, name);
|
res = fn(res, control, name);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {isBlank, isPresent, CONST_EXPR, isString} from 'angular2/src/facade/lang';
|
import {isBlank, isPresent, CONST_EXPR} from 'angular2/src/facade/lang';
|
||||||
import {PromiseWrapper} from 'angular2/src/facade/promise';
|
import {PromiseWrapper} from 'angular2/src/facade/promise';
|
||||||
import {ObservableWrapper} from 'angular2/src/facade/async';
|
import {ObservableWrapper} from 'angular2/src/facade/async';
|
||||||
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
@ -44,9 +44,7 @@ export class Validators {
|
|||||||
* Validator that requires controls to have a non-empty value.
|
* Validator that requires controls to have a non-empty value.
|
||||||
*/
|
*/
|
||||||
static required(control: modelModule.Control): {[key: string]: boolean} {
|
static required(control: modelModule.Control): {[key: string]: boolean} {
|
||||||
return isBlank(control.value) || (isString(control.value) && control.value == "") ?
|
return isBlank(control.value) || control.value == "" ? {"required": true} : null;
|
||||||
{"required": true} :
|
|
||||||
null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,19 +73,6 @@ export class Validators {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Validator that requires a control to match a regex to its value.
|
|
||||||
*/
|
|
||||||
static pattern(pattern: string): Function {
|
|
||||||
return (control: modelModule.Control): {[key: string]: any} => {
|
|
||||||
if (isPresent(Validators.required(control))) return null;
|
|
||||||
let regex = new RegExp(`^${pattern}$`);
|
|
||||||
let v: string = control.value;
|
|
||||||
return regex.test(v) ? null :
|
|
||||||
{"pattern": {"requiredPattern": `^${pattern}$`, "actualValue": v}};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No-op validator.
|
* No-op validator.
|
||||||
*/
|
*/
|
||||||
|
@ -3,6 +3,14 @@
|
|||||||
* @description
|
* @description
|
||||||
* This module provides a set of common Pipes.
|
* This module provides a set of common Pipes.
|
||||||
*/
|
*/
|
||||||
|
import {AsyncPipe} from './pipes/async_pipe';
|
||||||
|
import {UpperCasePipe} from './pipes/uppercase_pipe';
|
||||||
|
import {LowerCasePipe} from './pipes/lowercase_pipe';
|
||||||
|
import {JsonPipe} from './pipes/json_pipe';
|
||||||
|
import {SlicePipe} from './pipes/slice_pipe';
|
||||||
|
import {DatePipe} from './pipes/date_pipe';
|
||||||
|
import {DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe';
|
||||||
|
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
export {AsyncPipe} from './pipes/async_pipe';
|
export {AsyncPipe} from './pipes/async_pipe';
|
||||||
export {DatePipe} from './pipes/date_pipe';
|
export {DatePipe} from './pipes/date_pipe';
|
||||||
@ -11,7 +19,22 @@ export {SlicePipe} from './pipes/slice_pipe';
|
|||||||
export {LowerCasePipe} from './pipes/lowercase_pipe';
|
export {LowerCasePipe} from './pipes/lowercase_pipe';
|
||||||
export {NumberPipe, DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe';
|
export {NumberPipe, DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe';
|
||||||
export {UpperCasePipe} from './pipes/uppercase_pipe';
|
export {UpperCasePipe} from './pipes/uppercase_pipe';
|
||||||
export {ReplacePipe} from './pipes/replace_pipe';
|
|
||||||
export {I18nPluralPipe} from './pipes/i18n_plural_pipe';
|
/**
|
||||||
export {I18nSelectPipe} from './pipes/i18n_select_pipe';
|
* A collection of Angular core pipes that are likely to be used in each and every
|
||||||
export {COMMON_PIPES} from './pipes/common_pipes';
|
* 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,
|
||||||
|
LowerCasePipe,
|
||||||
|
JsonPipe,
|
||||||
|
SlicePipe,
|
||||||
|
DecimalPipe,
|
||||||
|
PercentPipe,
|
||||||
|
CurrencyPipe,
|
||||||
|
DatePipe
|
||||||
|
]);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {isBlank, isPresent, isPromise, CONST} from 'angular2/src/facade/lang';
|
import {isBlank, isPresent, isPromise, CONST} from 'angular2/src/facade/lang';
|
||||||
import {ObservableWrapper, Observable, EventEmitter} from 'angular2/src/facade/async';
|
import {Promise, ObservableWrapper, Observable, EventEmitter} from 'angular2/src/facade/async';
|
||||||
import {
|
import {
|
||||||
Pipe,
|
Pipe,
|
||||||
Injectable,
|
Injectable,
|
||||||
@ -33,7 +33,7 @@ class PromiseStrategy {
|
|||||||
|
|
||||||
var _promiseStrategy = new PromiseStrategy();
|
var _promiseStrategy = new PromiseStrategy();
|
||||||
var _observableStrategy = new ObservableStrategy();
|
var _observableStrategy = new ObservableStrategy();
|
||||||
var __unused: Promise<any>; // avoid unused import when Promise union types are erased
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `async` pipe subscribes to an Observable or Promise and returns the latest value it has
|
* The `async` pipe subscribes to an Observable or Promise and returns the latest value it has
|
||||||
@ -81,7 +81,6 @@ export class AsyncPipe implements PipeTransform, OnDestroy {
|
|||||||
if (isPresent(obj)) {
|
if (isPresent(obj)) {
|
||||||
this._subscribe(obj);
|
this._subscribe(obj);
|
||||||
}
|
}
|
||||||
this._latestReturnedValue = this._latestValue;
|
|
||||||
return this._latestValue;
|
return this._latestValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,8 +101,8 @@ export class AsyncPipe implements PipeTransform, OnDestroy {
|
|||||||
_subscribe(obj: Observable<any>| Promise<any>| EventEmitter<any>): void {
|
_subscribe(obj: Observable<any>| Promise<any>| EventEmitter<any>): void {
|
||||||
this._obj = obj;
|
this._obj = obj;
|
||||||
this._strategy = this._selectStrategy(obj);
|
this._strategy = this._selectStrategy(obj);
|
||||||
this._subscription = this._strategy.createSubscription(
|
this._subscription =
|
||||||
obj, (value: Object) => this._updateLatestValue(obj, value));
|
this._strategy.createSubscription(obj, value => this._updateLatestValue(obj, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
|
@ -10,9 +10,6 @@ import {JsonPipe} from './json_pipe';
|
|||||||
import {SlicePipe} from './slice_pipe';
|
import {SlicePipe} from './slice_pipe';
|
||||||
import {DatePipe} from './date_pipe';
|
import {DatePipe} from './date_pipe';
|
||||||
import {DecimalPipe, PercentPipe, CurrencyPipe} from './number_pipe';
|
import {DecimalPipe, PercentPipe, CurrencyPipe} from './number_pipe';
|
||||||
import {ReplacePipe} from './replace_pipe';
|
|
||||||
import {I18nPluralPipe} from './i18n_plural_pipe';
|
|
||||||
import {I18nSelectPipe} from './i18n_select_pipe';
|
|
||||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,8 +28,5 @@ export const COMMON_PIPES = CONST_EXPR([
|
|||||||
DecimalPipe,
|
DecimalPipe,
|
||||||
PercentPipe,
|
PercentPipe,
|
||||||
CurrencyPipe,
|
CurrencyPipe,
|
||||||
DatePipe,
|
DatePipe
|
||||||
ReplacePipe,
|
|
||||||
I18nPluralPipe,
|
|
||||||
I18nSelectPipe
|
|
||||||
]);
|
]);
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
import {
|
|
||||||
CONST,
|
|
||||||
isStringMap,
|
|
||||||
StringWrapper,
|
|
||||||
isPresent,
|
|
||||||
RegExpWrapper
|
|
||||||
} from 'angular2/src/facade/lang';
|
|
||||||
import {Injectable, PipeTransform, Pipe} from 'angular2/core';
|
|
||||||
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
|
||||||
|
|
||||||
var interpolationExp: RegExp = RegExpWrapper.create('#');
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Maps a value to a string that pluralizes the value properly.
|
|
||||||
*
|
|
||||||
* ## Usage
|
|
||||||
*
|
|
||||||
* expression | i18nPlural:mapping
|
|
||||||
*
|
|
||||||
* where `expression` is a number and `mapping` is an object that indicates the proper text for
|
|
||||||
* when the `expression` evaluates to 0, 1, or some other number. You can interpolate the actual
|
|
||||||
* value into the text using the `#` sign.
|
|
||||||
*
|
|
||||||
* ## Example
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* <div>
|
|
||||||
* {{ messages.length | i18nPlural: messageMapping }}
|
|
||||||
* </div>
|
|
||||||
*
|
|
||||||
* class MyApp {
|
|
||||||
* messages: any[];
|
|
||||||
* messageMapping: any = {
|
|
||||||
* '=0': 'No messages.',
|
|
||||||
* '=1': 'One message.',
|
|
||||||
* 'other': '# messages.'
|
|
||||||
* }
|
|
||||||
* ...
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@CONST()
|
|
||||||
@Pipe({name: 'i18nPlural', pure: true})
|
|
||||||
@Injectable()
|
|
||||||
export class I18nPluralPipe implements PipeTransform {
|
|
||||||
transform(value: number, args: any[] = null): string {
|
|
||||||
var key: string;
|
|
||||||
var valueStr: string;
|
|
||||||
var pluralMap: {[count: string]: string} = args[0];
|
|
||||||
|
|
||||||
if (!isStringMap(pluralMap)) {
|
|
||||||
throw new InvalidPipeArgumentException(I18nPluralPipe, pluralMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
key = value === 0 || value === 1 ? `=${value}` : 'other';
|
|
||||||
valueStr = isPresent(value) ? value.toString() : '';
|
|
||||||
|
|
||||||
return StringWrapper.replaceAll(pluralMap[key], interpolationExp, valueStr);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
import {CONST, isStringMap} from 'angular2/src/facade/lang';
|
|
||||||
import {StringMapWrapper} from 'angular2/src/facade/collection';
|
|
||||||
import {Injectable, PipeTransform, Pipe} from 'angular2/core';
|
|
||||||
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Generic selector that displays the string that matches the current value.
|
|
||||||
*
|
|
||||||
* ## Usage
|
|
||||||
*
|
|
||||||
* expression | i18nSelect:mapping
|
|
||||||
*
|
|
||||||
* where `mapping` is an object that indicates the text that should be displayed
|
|
||||||
* for different values of the provided `expression`.
|
|
||||||
*
|
|
||||||
* ## Example
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* <div>
|
|
||||||
* {{ gender | i18nSelect: inviteMap }}
|
|
||||||
* </div>
|
|
||||||
*
|
|
||||||
* class MyApp {
|
|
||||||
* gender: string = 'male';
|
|
||||||
* inviteMap: any = {
|
|
||||||
* 'male': 'Invite her.',
|
|
||||||
* 'female': 'Invite him.',
|
|
||||||
* 'other': 'Invite them.'
|
|
||||||
* }
|
|
||||||
* ...
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
@CONST()
|
|
||||||
@Pipe({name: 'i18nSelect', pure: true})
|
|
||||||
@Injectable()
|
|
||||||
export class I18nSelectPipe implements PipeTransform {
|
|
||||||
transform(value: string, args: any[] = null): string {
|
|
||||||
var mapping: {[key: string]: string} = args[0];
|
|
||||||
if (!isStringMap(mapping)) {
|
|
||||||
throw new InvalidPipeArgumentException(I18nSelectPipe, mapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
return StringMapWrapper.contains(mapping, value) ? mapping[value] : mapping['other'];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
import {
|
|
||||||
isBlank,
|
|
||||||
isString,
|
|
||||||
isNumber,
|
|
||||||
isFunction,
|
|
||||||
RegExpWrapper,
|
|
||||||
StringWrapper
|
|
||||||
} from 'angular2/src/facade/lang';
|
|
||||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
|
||||||
import {Injectable, PipeTransform, Pipe} from 'angular2/core';
|
|
||||||
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new String with some or all of the matches of a pattern replaced by
|
|
||||||
* a replacement.
|
|
||||||
*
|
|
||||||
* The pattern to be matched is specified by the 'pattern' parameter.
|
|
||||||
*
|
|
||||||
* The replacement to be set is specified by the 'replacement' parameter.
|
|
||||||
*
|
|
||||||
* An optional 'flags' parameter can be set.
|
|
||||||
*
|
|
||||||
* ### Usage
|
|
||||||
*
|
|
||||||
* expression | replace:pattern:replacement
|
|
||||||
*
|
|
||||||
* All behavior is based on the expected behavior of the JavaScript API
|
|
||||||
* String.prototype.replace() function.
|
|
||||||
*
|
|
||||||
* Where the input expression is a [String] or [Number] (to be treated as a string),
|
|
||||||
* the `pattern` is a [String] or [RegExp],
|
|
||||||
* the 'replacement' is a [String] or [Function].
|
|
||||||
*
|
|
||||||
* --Note--: The 'pattern' parameter will be converted to a RegExp instance. Make sure to escape the
|
|
||||||
* string properly if you are matching for regular expression special characters like parenthesis,
|
|
||||||
* brackets etc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Pipe({name: 'replace'})
|
|
||||||
@Injectable()
|
|
||||||
export class ReplacePipe implements PipeTransform {
|
|
||||||
transform(value: any, args: any[]): any {
|
|
||||||
if (isBlank(args) || args.length !== 2) {
|
|
||||||
throw new BaseException('ReplacePipe requires two arguments');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isBlank(value)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._supportedInput(value)) {
|
|
||||||
throw new InvalidPipeArgumentException(ReplacePipe, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
var input = value.toString();
|
|
||||||
var pattern = args[0];
|
|
||||||
var replacement = args[1];
|
|
||||||
|
|
||||||
|
|
||||||
if (!this._supportedPattern(pattern)) {
|
|
||||||
throw new InvalidPipeArgumentException(ReplacePipe, pattern);
|
|
||||||
}
|
|
||||||
if (!this._supportedReplacement(replacement)) {
|
|
||||||
throw new InvalidPipeArgumentException(ReplacePipe, replacement);
|
|
||||||
}
|
|
||||||
// template fails with literal RegExp e.g /pattern/igm
|
|
||||||
// var rgx = pattern instanceof RegExp ? pattern : RegExpWrapper.create(pattern);
|
|
||||||
|
|
||||||
if (isFunction(replacement)) {
|
|
||||||
var rgxPattern = isString(pattern) ? RegExpWrapper.create(pattern) : pattern;
|
|
||||||
|
|
||||||
return StringWrapper.replaceAllMapped(input, rgxPattern, replacement);
|
|
||||||
}
|
|
||||||
if (pattern instanceof RegExp) {
|
|
||||||
// use the replaceAll variant
|
|
||||||
return StringWrapper.replaceAll(input, pattern, replacement);
|
|
||||||
}
|
|
||||||
|
|
||||||
return StringWrapper.replace(input, pattern, replacement);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _supportedInput(input: any): boolean { return isString(input) || isNumber(input); }
|
|
||||||
|
|
||||||
private _supportedPattern(pattern: any): boolean {
|
|
||||||
return isString(pattern) || pattern instanceof RegExp;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _supportedReplacement(replacement: any): boolean {
|
|
||||||
return isString(replacement) || isFunction(replacement);
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,10 +2,8 @@ import {
|
|||||||
isPresent,
|
isPresent,
|
||||||
isBlank,
|
isBlank,
|
||||||
normalizeBool,
|
normalizeBool,
|
||||||
normalizeBlank,
|
|
||||||
serializeEnum,
|
serializeEnum,
|
||||||
Type,
|
Type,
|
||||||
isString,
|
|
||||||
RegExpWrapper,
|
RegExpWrapper,
|
||||||
StringWrapper
|
StringWrapper
|
||||||
} from 'angular2/src/facade/lang';
|
} from 'angular2/src/facade/lang';
|
||||||
@ -24,17 +22,7 @@ import {LifecycleHooks, LIFECYCLE_HOOKS_VALUES} from 'angular2/src/core/linker/i
|
|||||||
// group 2: "event" from "(event)"
|
// group 2: "event" from "(event)"
|
||||||
var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g;
|
var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g;
|
||||||
|
|
||||||
export abstract class CompileMetadataWithIdentifier {
|
export abstract class CompileMetadataWithType {
|
||||||
static fromJson(data: {[key: string]: any}): CompileMetadataWithIdentifier {
|
|
||||||
return _COMPILE_METADATA_FROM_JSON[data['class']](data);
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract toJson(): {[key: string]: any};
|
|
||||||
|
|
||||||
get identifier(): CompileIdentifierMetadata { return unimplemented(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class CompileMetadataWithType extends CompileMetadataWithIdentifier {
|
|
||||||
static fromJson(data: {[key: string]: any}): CompileMetadataWithType {
|
static fromJson(data: {[key: string]: any}): CompileMetadataWithType {
|
||||||
return _COMPILE_METADATA_FROM_JSON[data['class']](data);
|
return _COMPILE_METADATA_FROM_JSON[data['class']](data);
|
||||||
}
|
}
|
||||||
@ -42,273 +30,35 @@ export abstract class CompileMetadataWithType extends CompileMetadataWithIdentif
|
|||||||
abstract toJson(): {[key: string]: any};
|
abstract toJson(): {[key: string]: any};
|
||||||
|
|
||||||
get type(): CompileTypeMetadata { return unimplemented(); }
|
get type(): CompileTypeMetadata { return unimplemented(); }
|
||||||
|
|
||||||
get identifier(): CompileIdentifierMetadata { return unimplemented(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CompileIdentifierMetadata implements CompileMetadataWithIdentifier {
|
|
||||||
runtime: any;
|
|
||||||
name: string;
|
|
||||||
prefix: string;
|
|
||||||
moduleUrl: string;
|
|
||||||
constConstructor: boolean;
|
|
||||||
constructor({runtime, name, moduleUrl, prefix, constConstructor}: {
|
|
||||||
runtime?: any,
|
|
||||||
name?: string,
|
|
||||||
moduleUrl?: string,
|
|
||||||
prefix?: string,
|
|
||||||
constConstructor?: boolean
|
|
||||||
} = {}) {
|
|
||||||
this.runtime = runtime;
|
|
||||||
this.name = name;
|
|
||||||
this.prefix = prefix;
|
|
||||||
this.moduleUrl = moduleUrl;
|
|
||||||
this.constConstructor = constConstructor;
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromJson(data: {[key: string]: any}): CompileIdentifierMetadata {
|
|
||||||
return new CompileIdentifierMetadata({
|
|
||||||
name: data['name'],
|
|
||||||
prefix: data['prefix'],
|
|
||||||
moduleUrl: data['moduleUrl'],
|
|
||||||
constConstructor: data['constConstructor']
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
toJson(): {[key: string]: any} {
|
|
||||||
return {
|
|
||||||
// Note: Runtime type can't be serialized...
|
|
||||||
'class': 'Identifier',
|
|
||||||
'name': this.name,
|
|
||||||
'moduleUrl': this.moduleUrl,
|
|
||||||
'prefix': this.prefix,
|
|
||||||
'constConstructor': this.constConstructor
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
get identifier(): CompileIdentifierMetadata { return this; }
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CompileDiDependencyMetadata {
|
|
||||||
isAttribute: boolean;
|
|
||||||
isSelf: boolean;
|
|
||||||
isHost: boolean;
|
|
||||||
isSkipSelf: boolean;
|
|
||||||
isOptional: boolean;
|
|
||||||
query: CompileQueryMetadata;
|
|
||||||
viewQuery: CompileQueryMetadata;
|
|
||||||
token: CompileIdentifierMetadata | string;
|
|
||||||
|
|
||||||
constructor({isAttribute, isSelf, isHost, isSkipSelf, isOptional, query, viewQuery, token}: {
|
|
||||||
isAttribute?: boolean,
|
|
||||||
isSelf?: boolean,
|
|
||||||
isHost?: boolean,
|
|
||||||
isSkipSelf?: boolean,
|
|
||||||
isOptional?: boolean,
|
|
||||||
query?: CompileQueryMetadata,
|
|
||||||
viewQuery?: CompileQueryMetadata,
|
|
||||||
token?: CompileIdentifierMetadata | string
|
|
||||||
} = {}) {
|
|
||||||
this.isAttribute = normalizeBool(isAttribute);
|
|
||||||
this.isSelf = normalizeBool(isSelf);
|
|
||||||
this.isHost = normalizeBool(isHost);
|
|
||||||
this.isSkipSelf = normalizeBool(isSkipSelf);
|
|
||||||
this.isOptional = normalizeBool(isOptional);
|
|
||||||
this.query = query;
|
|
||||||
this.viewQuery = viewQuery;
|
|
||||||
this.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromJson(data: {[key: string]: any}): CompileDiDependencyMetadata {
|
|
||||||
return new CompileDiDependencyMetadata({
|
|
||||||
token: objFromJson(data['token'], CompileIdentifierMetadata.fromJson),
|
|
||||||
query: objFromJson(data['query'], CompileQueryMetadata.fromJson),
|
|
||||||
viewQuery: objFromJson(data['viewQuery'], CompileQueryMetadata.fromJson),
|
|
||||||
isAttribute: data['isAttribute'],
|
|
||||||
isSelf: data['isSelf'],
|
|
||||||
isHost: data['isHost'],
|
|
||||||
isSkipSelf: data['isSkipSelf'],
|
|
||||||
isOptional: data['isOptional']
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
toJson(): {[key: string]: any} {
|
|
||||||
return {
|
|
||||||
// Note: Runtime type can't be serialized...
|
|
||||||
'token': objToJson(this.token),
|
|
||||||
'query': objToJson(this.query),
|
|
||||||
'viewQuery': objToJson(this.viewQuery),
|
|
||||||
'isAttribute': this.isAttribute,
|
|
||||||
'isSelf': this.isSelf,
|
|
||||||
'isHost': this.isHost,
|
|
||||||
'isSkipSelf': this.isSkipSelf,
|
|
||||||
'isOptional': this.isOptional
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CompileProviderMetadata {
|
|
||||||
token: CompileIdentifierMetadata | string;
|
|
||||||
useClass: CompileTypeMetadata;
|
|
||||||
useValue: any;
|
|
||||||
useExisting: CompileIdentifierMetadata | string;
|
|
||||||
useFactory: CompileFactoryMetadata;
|
|
||||||
deps: CompileDiDependencyMetadata[];
|
|
||||||
multi: boolean;
|
|
||||||
|
|
||||||
constructor({token, useClass, useValue, useExisting, useFactory, deps, multi}: {
|
|
||||||
token?: CompileIdentifierMetadata | string,
|
|
||||||
useClass?: CompileTypeMetadata,
|
|
||||||
useValue?: any,
|
|
||||||
useExisting?: CompileIdentifierMetadata | string,
|
|
||||||
useFactory?: CompileFactoryMetadata,
|
|
||||||
deps?: CompileDiDependencyMetadata[],
|
|
||||||
multi?: boolean
|
|
||||||
}) {
|
|
||||||
this.token = token;
|
|
||||||
this.useClass = useClass;
|
|
||||||
this.useValue = useValue;
|
|
||||||
this.useExisting = useExisting;
|
|
||||||
this.useFactory = useFactory;
|
|
||||||
this.deps = deps;
|
|
||||||
this.multi = multi;
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromJson(data: {[key: string]: any}): CompileProviderMetadata {
|
|
||||||
return new CompileProviderMetadata({
|
|
||||||
token: objFromJson(data['token'], CompileIdentifierMetadata.fromJson),
|
|
||||||
useClass: objFromJson(data['useClass'], CompileTypeMetadata.fromJson)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
toJson(): {[key: string]: any} {
|
|
||||||
return {
|
|
||||||
// Note: Runtime type can't be serialized...
|
|
||||||
'token': objToJson(this.token),
|
|
||||||
'useClass': objToJson(this.useClass)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CompileFactoryMetadata implements CompileIdentifierMetadata {
|
|
||||||
runtime: Function;
|
|
||||||
name: string;
|
|
||||||
prefix: string;
|
|
||||||
moduleUrl: string;
|
|
||||||
constConstructor: boolean;
|
|
||||||
diDeps: CompileDiDependencyMetadata[];
|
|
||||||
|
|
||||||
constructor({runtime, name, moduleUrl, constConstructor, diDeps}: {
|
|
||||||
runtime?: Function,
|
|
||||||
name?: string,
|
|
||||||
moduleUrl?: string,
|
|
||||||
constConstructor?: boolean,
|
|
||||||
diDeps?: CompileDiDependencyMetadata[]
|
|
||||||
}) {
|
|
||||||
this.runtime = runtime;
|
|
||||||
this.name = name;
|
|
||||||
this.moduleUrl = moduleUrl;
|
|
||||||
this.diDeps = diDeps;
|
|
||||||
this.constConstructor = constConstructor;
|
|
||||||
}
|
|
||||||
|
|
||||||
get identifier(): CompileIdentifierMetadata { return this; }
|
|
||||||
|
|
||||||
toJson() { return null; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadata regarding compilation of a type.
|
* Metadata regarding compilation of a type.
|
||||||
*/
|
*/
|
||||||
export class CompileTypeMetadata implements CompileIdentifierMetadata, CompileMetadataWithType {
|
export class CompileTypeMetadata {
|
||||||
runtime: Type;
|
runtime: Type;
|
||||||
name: string;
|
name: string;
|
||||||
prefix: string;
|
|
||||||
moduleUrl: string;
|
moduleUrl: string;
|
||||||
isHost: boolean;
|
isHost: boolean;
|
||||||
constConstructor: boolean;
|
constructor({runtime, name, moduleUrl, isHost}:
|
||||||
diDeps: CompileDiDependencyMetadata[];
|
{runtime?: Type, name?: string, moduleUrl?: string, isHost?: boolean} = {}) {
|
||||||
|
|
||||||
constructor({runtime, name, moduleUrl, prefix, isHost, constConstructor, diDeps}: {
|
|
||||||
runtime?: Type,
|
|
||||||
name?: string,
|
|
||||||
moduleUrl?: string,
|
|
||||||
prefix?: string,
|
|
||||||
isHost?: boolean,
|
|
||||||
constConstructor?: boolean,
|
|
||||||
diDeps?: CompileDiDependencyMetadata[]
|
|
||||||
} = {}) {
|
|
||||||
this.runtime = runtime;
|
this.runtime = runtime;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.moduleUrl = moduleUrl;
|
this.moduleUrl = moduleUrl;
|
||||||
this.prefix = prefix;
|
|
||||||
this.isHost = normalizeBool(isHost);
|
this.isHost = normalizeBool(isHost);
|
||||||
this.constConstructor = constConstructor;
|
|
||||||
this.diDeps = normalizeBlank(diDeps);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(data: {[key: string]: any}): CompileTypeMetadata {
|
static fromJson(data: {[key: string]: any}): CompileTypeMetadata {
|
||||||
return new CompileTypeMetadata({
|
return new CompileTypeMetadata(
|
||||||
name: data['name'],
|
{name: data['name'], moduleUrl: data['moduleUrl'], isHost: data['isHost']});
|
||||||
moduleUrl: data['moduleUrl'],
|
|
||||||
prefix: data['prefix'],
|
|
||||||
isHost: data['isHost'],
|
|
||||||
constConstructor: data['constConstructor'],
|
|
||||||
diDeps: arrayFromJson(data['diDeps'], CompileDiDependencyMetadata.fromJson)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get identifier(): CompileIdentifierMetadata { return this; }
|
|
||||||
get type(): CompileTypeMetadata { return this; }
|
|
||||||
|
|
||||||
toJson(): {[key: string]: any} {
|
toJson(): {[key: string]: any} {
|
||||||
return {
|
return {
|
||||||
// Note: Runtime type can't be serialized...
|
// Note: Runtime type can't be serialized...
|
||||||
'class': 'Type',
|
|
||||||
'name': this.name,
|
'name': this.name,
|
||||||
'moduleUrl': this.moduleUrl,
|
'moduleUrl': this.moduleUrl,
|
||||||
'prefix': this.prefix,
|
'isHost': this.isHost
|
||||||
'isHost': this.isHost,
|
|
||||||
'constConstructor': this.constConstructor,
|
|
||||||
'diDeps': arrayToJson(this.diDeps)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CompileQueryMetadata {
|
|
||||||
selectors: Array<CompileIdentifierMetadata | string>;
|
|
||||||
descendants: boolean;
|
|
||||||
first: boolean;
|
|
||||||
propertyName: string;
|
|
||||||
|
|
||||||
constructor({selectors, descendants, first, propertyName}: {
|
|
||||||
selectors?: Array<CompileIdentifierMetadata | string>,
|
|
||||||
descendants?: boolean,
|
|
||||||
first?: boolean,
|
|
||||||
propertyName?: string
|
|
||||||
} = {}) {
|
|
||||||
this.selectors = selectors;
|
|
||||||
this.descendants = descendants;
|
|
||||||
this.first = normalizeBool(first);
|
|
||||||
this.propertyName = propertyName;
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromJson(data: {[key: string]: any}): CompileQueryMetadata {
|
|
||||||
return new CompileQueryMetadata({
|
|
||||||
selectors: arrayFromJson(data['selectors'], CompileIdentifierMetadata.fromJson),
|
|
||||||
descendants: data['descendants'],
|
|
||||||
first: data['first'],
|
|
||||||
propertyName: data['propertyName']
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
toJson(): {[key: string]: any} {
|
|
||||||
return {
|
|
||||||
// Note: Runtime type can't be serialized...
|
|
||||||
'selectors': arrayToJson(this.selectors),
|
|
||||||
'descendants': this.descendants,
|
|
||||||
'first': this.first,
|
|
||||||
'propertyName': this.propertyName
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -370,8 +120,7 @@ export class CompileTemplateMetadata {
|
|||||||
*/
|
*/
|
||||||
export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||||
static create({type, isComponent, dynamicLoadable, selector, exportAs, changeDetection, inputs,
|
static create({type, isComponent, dynamicLoadable, selector, exportAs, changeDetection, inputs,
|
||||||
outputs, host, lifecycleHooks, providers, viewProviders, queries, viewQueries,
|
outputs, host, lifecycleHooks, template}: {
|
||||||
template}: {
|
|
||||||
type?: CompileTypeMetadata,
|
type?: CompileTypeMetadata,
|
||||||
isComponent?: boolean,
|
isComponent?: boolean,
|
||||||
dynamicLoadable?: boolean,
|
dynamicLoadable?: boolean,
|
||||||
@ -382,10 +131,6 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
|||||||
outputs?: string[],
|
outputs?: string[],
|
||||||
host?: {[key: string]: string},
|
host?: {[key: string]: string},
|
||||||
lifecycleHooks?: LifecycleHooks[],
|
lifecycleHooks?: LifecycleHooks[],
|
||||||
providers?: Array<CompileProviderMetadata | CompileTypeMetadata | any[]>,
|
|
||||||
viewProviders?: Array<CompileProviderMetadata | CompileTypeMetadata | any[]>,
|
|
||||||
queries?: CompileQueryMetadata[],
|
|
||||||
viewQueries?: CompileQueryMetadata[],
|
|
||||||
template?: CompileTemplateMetadata
|
template?: CompileTemplateMetadata
|
||||||
} = {}): CompileDirectiveMetadata {
|
} = {}): CompileDirectiveMetadata {
|
||||||
var hostListeners: {[key: string]: string} = {};
|
var hostListeners: {[key: string]: string} = {};
|
||||||
@ -435,13 +180,10 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
|||||||
hostProperties: hostProperties,
|
hostProperties: hostProperties,
|
||||||
hostAttributes: hostAttributes,
|
hostAttributes: hostAttributes,
|
||||||
lifecycleHooks: isPresent(lifecycleHooks) ? lifecycleHooks : [],
|
lifecycleHooks: isPresent(lifecycleHooks) ? lifecycleHooks : [],
|
||||||
providers: providers,
|
|
||||||
viewProviders: viewProviders,
|
|
||||||
queries: queries,
|
|
||||||
viewQueries: viewQueries,
|
|
||||||
template: template
|
template: template
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
type: CompileTypeMetadata;
|
type: CompileTypeMetadata;
|
||||||
isComponent: boolean;
|
isComponent: boolean;
|
||||||
dynamicLoadable: boolean;
|
dynamicLoadable: boolean;
|
||||||
@ -454,14 +196,9 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
|||||||
hostProperties: {[key: string]: string};
|
hostProperties: {[key: string]: string};
|
||||||
hostAttributes: {[key: string]: string};
|
hostAttributes: {[key: string]: string};
|
||||||
lifecycleHooks: LifecycleHooks[];
|
lifecycleHooks: LifecycleHooks[];
|
||||||
providers: Array<CompileProviderMetadata | CompileTypeMetadata | any[]>;
|
|
||||||
viewProviders: Array<CompileProviderMetadata | CompileTypeMetadata | any[]>;
|
|
||||||
queries: CompileQueryMetadata[];
|
|
||||||
viewQueries: CompileQueryMetadata[];
|
|
||||||
template: CompileTemplateMetadata;
|
template: CompileTemplateMetadata;
|
||||||
constructor({type, isComponent, dynamicLoadable, selector, exportAs, changeDetection, inputs,
|
constructor({type, isComponent, dynamicLoadable, selector, exportAs, changeDetection, inputs,
|
||||||
outputs, hostListeners, hostProperties, hostAttributes, lifecycleHooks, providers,
|
outputs, hostListeners, hostProperties, hostAttributes, lifecycleHooks, template}: {
|
||||||
viewProviders, queries, viewQueries, template}: {
|
|
||||||
type?: CompileTypeMetadata,
|
type?: CompileTypeMetadata,
|
||||||
isComponent?: boolean,
|
isComponent?: boolean,
|
||||||
dynamicLoadable?: boolean,
|
dynamicLoadable?: boolean,
|
||||||
@ -474,10 +211,6 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
|||||||
hostProperties?: {[key: string]: string},
|
hostProperties?: {[key: string]: string},
|
||||||
hostAttributes?: {[key: string]: string},
|
hostAttributes?: {[key: string]: string},
|
||||||
lifecycleHooks?: LifecycleHooks[],
|
lifecycleHooks?: LifecycleHooks[],
|
||||||
providers?: Array<CompileProviderMetadata | CompileTypeMetadata | any[]>,
|
|
||||||
viewProviders?: Array<CompileProviderMetadata | CompileTypeMetadata | any[]>,
|
|
||||||
queries?: CompileQueryMetadata[],
|
|
||||||
viewQueries?: CompileQueryMetadata[],
|
|
||||||
template?: CompileTemplateMetadata
|
template?: CompileTemplateMetadata
|
||||||
} = {}) {
|
} = {}) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@ -492,15 +225,9 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
|||||||
this.hostProperties = hostProperties;
|
this.hostProperties = hostProperties;
|
||||||
this.hostAttributes = hostAttributes;
|
this.hostAttributes = hostAttributes;
|
||||||
this.lifecycleHooks = lifecycleHooks;
|
this.lifecycleHooks = lifecycleHooks;
|
||||||
this.providers = normalizeBlank(providers);
|
|
||||||
this.viewProviders = normalizeBlank(viewProviders);
|
|
||||||
this.queries = queries;
|
|
||||||
this.viewQueries = viewQueries;
|
|
||||||
this.template = template;
|
this.template = template;
|
||||||
}
|
}
|
||||||
|
|
||||||
get identifier(): CompileIdentifierMetadata { return this.type; }
|
|
||||||
|
|
||||||
static fromJson(data: {[key: string]: any}): CompileDirectiveMetadata {
|
static fromJson(data: {[key: string]: any}): CompileDirectiveMetadata {
|
||||||
return new CompileDirectiveMetadata({
|
return new CompileDirectiveMetadata({
|
||||||
isComponent: data['isComponent'],
|
isComponent: data['isComponent'],
|
||||||
@ -519,8 +246,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
|||||||
lifecycleHooks:
|
lifecycleHooks:
|
||||||
(<any[]>data['lifecycleHooks']).map(hookValue => LIFECYCLE_HOOKS_VALUES[hookValue]),
|
(<any[]>data['lifecycleHooks']).map(hookValue => LIFECYCLE_HOOKS_VALUES[hookValue]),
|
||||||
template: isPresent(data['template']) ? CompileTemplateMetadata.fromJson(data['template']) :
|
template: isPresent(data['template']) ? CompileTemplateMetadata.fromJson(data['template']) :
|
||||||
data['template'],
|
data['template']
|
||||||
providers: arrayFromJson(data['providers'], CompileProviderMetadata.fromJson)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,8 +266,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
|||||||
'hostProperties': this.hostProperties,
|
'hostProperties': this.hostProperties,
|
||||||
'hostAttributes': this.hostAttributes,
|
'hostAttributes': this.hostAttributes,
|
||||||
'lifecycleHooks': this.lifecycleHooks.map(hook => serializeEnum(hook)),
|
'lifecycleHooks': this.lifecycleHooks.map(hook => serializeEnum(hook)),
|
||||||
'template': isPresent(this.template) ? this.template.toJson() : this.template,
|
'template': isPresent(this.template) ? this.template.toJson() : this.template
|
||||||
'providers': arrayToJson(this.providers)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -568,11 +293,7 @@ export function createHostComponentMeta(componentType: CompileTypeMetadata,
|
|||||||
lifecycleHooks: [],
|
lifecycleHooks: [],
|
||||||
isComponent: true,
|
isComponent: true,
|
||||||
dynamicLoadable: false,
|
dynamicLoadable: false,
|
||||||
selector: '*',
|
selector: '*'
|
||||||
providers: [],
|
|
||||||
viewProviders: [],
|
|
||||||
queries: [],
|
|
||||||
viewQueries: []
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,7 +308,6 @@ export class CompilePipeMetadata implements CompileMetadataWithType {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
this.pure = normalizeBool(pure);
|
this.pure = normalizeBool(pure);
|
||||||
}
|
}
|
||||||
get identifier(): CompileIdentifierMetadata { return this.type; }
|
|
||||||
|
|
||||||
static fromJson(data: {[key: string]: any}): CompilePipeMetadata {
|
static fromJson(data: {[key: string]: any}): CompilePipeMetadata {
|
||||||
return new CompilePipeMetadata({
|
return new CompilePipeMetadata({
|
||||||
@ -609,23 +329,5 @@ export class CompilePipeMetadata implements CompileMetadataWithType {
|
|||||||
|
|
||||||
var _COMPILE_METADATA_FROM_JSON = {
|
var _COMPILE_METADATA_FROM_JSON = {
|
||||||
'Directive': CompileDirectiveMetadata.fromJson,
|
'Directive': CompileDirectiveMetadata.fromJson,
|
||||||
'Pipe': CompilePipeMetadata.fromJson,
|
'Pipe': CompilePipeMetadata.fromJson
|
||||||
'Type': CompileTypeMetadata.fromJson,
|
|
||||||
'Identifier': CompileIdentifierMetadata.fromJson
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function arrayFromJson(obj: any[], fn: (a: {[key: string]: any}) => any): any {
|
|
||||||
return isBlank(obj) ? null : obj.map(o => objFromJson(o, fn));
|
|
||||||
}
|
|
||||||
|
|
||||||
function arrayToJson(obj: any[]): string | {[key: string]: any} {
|
|
||||||
return isBlank(obj) ? null : obj.map(objToJson);
|
|
||||||
}
|
|
||||||
|
|
||||||
function objFromJson(obj: any, fn: (a: {[key: string]: any}) => any): any {
|
|
||||||
return (isString(obj) || isBlank(obj)) ? obj : fn(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
function objToJson(obj: any): string | {[key: string]: any} {
|
|
||||||
return (isString(obj) || isBlank(obj)) ? obj : obj.toJson();
|
|
||||||
}
|
|
@ -16,7 +16,7 @@ import {HtmlAst, HtmlAttrAst, HtmlTextAst, HtmlElementAst} from './html_ast';
|
|||||||
import {Injectable} from 'angular2/src/core/di';
|
import {Injectable} from 'angular2/src/core/di';
|
||||||
import {HtmlToken, HtmlTokenType, tokenizeHtml} from './html_lexer';
|
import {HtmlToken, HtmlTokenType, tokenizeHtml} from './html_lexer';
|
||||||
import {ParseError, ParseLocation, ParseSourceSpan} from './parse_util';
|
import {ParseError, ParseLocation, ParseSourceSpan} from './parse_util';
|
||||||
import {HtmlTagDefinition, getHtmlTagDefinition, getNsPrefix, mergeNsAndName} from './html_tags';
|
import {HtmlTagDefinition, getHtmlTagDefinition, getNsPrefix} from './html_tags';
|
||||||
|
|
||||||
export class HtmlTreeError extends ParseError {
|
export class HtmlTreeError extends ParseError {
|
||||||
static create(elementName: string, location: ParseLocation, msg: string): HtmlTreeError {
|
static create(elementName: string, location: ParseLocation, msg: string): HtmlTreeError {
|
||||||
@ -238,6 +238,10 @@ class TreeBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mergeNsAndName(prefix: string, localName: string): string {
|
||||||
|
return isPresent(prefix) ? `@${prefix}:${localName}` : localName;
|
||||||
|
}
|
||||||
|
|
||||||
function getElementFullName(prefix: string, localName: string,
|
function getElementFullName(prefix: string, localName: string,
|
||||||
parentElement: HtmlElementAst): string {
|
parentElement: HtmlElementAst): string {
|
||||||
if (isBlank(prefix)) {
|
if (isBlank(prefix)) {
|
||||||
|
@ -420,7 +420,3 @@ export function splitNsName(elementName: string): string[] {
|
|||||||
export function getNsPrefix(elementName: string): string {
|
export function getNsPrefix(elementName: string): string {
|
||||||
return splitNsName(elementName)[0];
|
return splitNsName(elementName)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mergeNsAndName(prefix: string, localName: string): string {
|
|
||||||
return isPresent(prefix) ? `@${prefix}:${localName}` : localName;
|
|
||||||
}
|
|
||||||
|
@ -4,6 +4,7 @@ import {TemplateCompiler} from './template_compiler';
|
|||||||
|
|
||||||
import {Injectable} from 'angular2/src/core/di';
|
import {Injectable} from 'angular2/src/core/di';
|
||||||
import {Type} from 'angular2/src/facade/lang';
|
import {Type} from 'angular2/src/facade/lang';
|
||||||
|
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
export abstract class RuntimeCompiler extends Compiler {
|
export abstract class RuntimeCompiler extends Compiler {
|
||||||
abstract compileInHost(componentType: Type): Promise<HostViewFactoryRef>;
|
abstract compileInHost(componentType: Type): Promise<HostViewFactoryRef>;
|
||||||
|
@ -3,7 +3,7 @@ import {SourceModule, SourceExpression, moduleRef} from './source_module';
|
|||||||
import {ViewEncapsulation} from 'angular2/src/core/metadata/view';
|
import {ViewEncapsulation} from 'angular2/src/core/metadata/view';
|
||||||
import {XHR} from 'angular2/src/compiler/xhr';
|
import {XHR} from 'angular2/src/compiler/xhr';
|
||||||
import {IS_DART, StringWrapper, isBlank} from 'angular2/src/facade/lang';
|
import {IS_DART, StringWrapper, isBlank} from 'angular2/src/facade/lang';
|
||||||
import {PromiseWrapper} from 'angular2/src/facade/async';
|
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
||||||
import {ShadowCss} from 'angular2/src/compiler/shadow_css';
|
import {ShadowCss} from 'angular2/src/compiler/shadow_css';
|
||||||
import {UrlResolver} from 'angular2/src/compiler/url_resolver';
|
import {UrlResolver} from 'angular2/src/compiler/url_resolver';
|
||||||
import {extractStyleUrls} from './style_url_resolver';
|
import {extractStyleUrls} from './style_url_resolver';
|
||||||
|
@ -14,7 +14,7 @@ import {
|
|||||||
MapWrapper,
|
MapWrapper,
|
||||||
StringMapWrapper
|
StringMapWrapper
|
||||||
} from 'angular2/src/facade/collection';
|
} from 'angular2/src/facade/collection';
|
||||||
import {PromiseWrapper} from 'angular2/src/facade/async';
|
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
||||||
import {
|
import {
|
||||||
createHostComponentMeta,
|
createHostComponentMeta,
|
||||||
CompileDirectiveMetadata,
|
CompileDirectiveMetadata,
|
||||||
@ -109,7 +109,6 @@ export class TemplateCompiler {
|
|||||||
hostProperties: directive.hostProperties,
|
hostProperties: directive.hostProperties,
|
||||||
hostAttributes: directive.hostAttributes,
|
hostAttributes: directive.hostAttributes,
|
||||||
lifecycleHooks: directive.lifecycleHooks,
|
lifecycleHooks: directive.lifecycleHooks,
|
||||||
providers: directive.providers,
|
|
||||||
template: normalizedTemplate
|
template: normalizedTemplate
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
} from './directive_metadata';
|
} from './directive_metadata';
|
||||||
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||||
import {PromiseWrapper} from 'angular2/src/facade/async';
|
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
import {XHR} from 'angular2/src/compiler/xhr';
|
import {XHR} from 'angular2/src/compiler/xhr';
|
||||||
import {UrlResolver} from 'angular2/src/compiler/url_resolver';
|
import {UrlResolver} from 'angular2/src/compiler/url_resolver';
|
||||||
|
@ -7,10 +7,11 @@ import {Parser, AST, ASTWithSource} from 'angular2/src/core/change_detection/cha
|
|||||||
import {TemplateBinding} from 'angular2/src/core/change_detection/parser/ast';
|
import {TemplateBinding} from 'angular2/src/core/change_detection/parser/ast';
|
||||||
import {CompileDirectiveMetadata, CompilePipeMetadata} from './directive_metadata';
|
import {CompileDirectiveMetadata, CompilePipeMetadata} from './directive_metadata';
|
||||||
import {HtmlParser} from './html_parser';
|
import {HtmlParser} from './html_parser';
|
||||||
import {splitNsName, mergeNsAndName} from './html_tags';
|
import {splitNsName} from './html_tags';
|
||||||
import {ParseSourceSpan, ParseError, ParseLocation} from './parse_util';
|
import {ParseSourceSpan, ParseError, ParseLocation} from './parse_util';
|
||||||
import {RecursiveAstVisitor, BindingPipe} from 'angular2/src/core/change_detection/parser/ast';
|
import {RecursiveAstVisitor, BindingPipe} from 'angular2/src/core/change_detection/parser/ast';
|
||||||
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ElementAst,
|
ElementAst,
|
||||||
BoundElementPropertyAst,
|
BoundElementPropertyAst,
|
||||||
@ -432,9 +433,8 @@ class TemplateParseVisitor implements HtmlAstVisitor {
|
|||||||
var parts = splitAtColon(name, [null, name]);
|
var parts = splitAtColon(name, [null, name]);
|
||||||
var target = parts[0];
|
var target = parts[0];
|
||||||
var eventName = parts[1];
|
var eventName = parts[1];
|
||||||
var ast = this._parseAction(expression, sourceSpan);
|
targetEvents.push(new BoundEventAst(eventName, target,
|
||||||
targetMatchableAttrs.push([name, ast.source]);
|
this._parseAction(expression, sourceSpan), sourceSpan));
|
||||||
targetEvents.push(new BoundEventAst(eventName, target, ast, sourceSpan));
|
|
||||||
// Don't detect directives for event names for now,
|
// Don't detect directives for event names for now,
|
||||||
// so don't add the event name to the matchableAttrs
|
// so don't add the event name to the matchableAttrs
|
||||||
}
|
}
|
||||||
@ -583,12 +583,6 @@ class TemplateParseVisitor implements HtmlAstVisitor {
|
|||||||
} else {
|
} else {
|
||||||
if (parts[0] == ATTRIBUTE_PREFIX) {
|
if (parts[0] == ATTRIBUTE_PREFIX) {
|
||||||
boundPropertyName = parts[1];
|
boundPropertyName = parts[1];
|
||||||
let nsSeparatorIdx = boundPropertyName.indexOf(':');
|
|
||||||
if (nsSeparatorIdx > -1) {
|
|
||||||
let ns = boundPropertyName.substring(0, nsSeparatorIdx);
|
|
||||||
let name = boundPropertyName.substring(nsSeparatorIdx + 1);
|
|
||||||
boundPropertyName = mergeNsAndName(ns, name);
|
|
||||||
}
|
|
||||||
bindingType = PropertyBindingType.Attribute;
|
bindingType = PropertyBindingType.Attribute;
|
||||||
} else if (parts[0] == CLASS_PREFIX) {
|
} else if (parts[0] == CLASS_PREFIX) {
|
||||||
boundPropertyName = parts[1];
|
boundPropertyName = parts[1];
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import {Promise} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
// TODO: vsavkin rename it into TemplateLoader
|
// TODO: vsavkin rename it into TemplateLoader
|
||||||
/**
|
/**
|
||||||
* An interface for retrieving documents by URL that the compiler uses
|
* An interface for retrieving documents by URL that the compiler uses
|
||||||
|
@ -2,7 +2,7 @@ import {XHR} from 'angular2/src/compiler/xhr';
|
|||||||
import {ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {isBlank, isPresent, normalizeBlank} from 'angular2/src/facade/lang';
|
import {isBlank, isPresent, normalizeBlank} from 'angular2/src/facade/lang';
|
||||||
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
||||||
import {PromiseCompleter, PromiseWrapper} from 'angular2/src/facade/async';
|
import {PromiseCompleter, PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mock implementation of {@link XHR} that allows outgoing requests to be mocked
|
* A mock implementation of {@link XHR} that allows outgoing requests to be mocked
|
||||||
|
@ -15,7 +15,12 @@ import {
|
|||||||
PLATFORM_INITIALIZER,
|
PLATFORM_INITIALIZER,
|
||||||
APP_INITIALIZER
|
APP_INITIALIZER
|
||||||
} from './application_tokens';
|
} from './application_tokens';
|
||||||
import {PromiseWrapper, PromiseCompleter, ObservableWrapper} from 'angular2/src/facade/async';
|
import {
|
||||||
|
Promise,
|
||||||
|
PromiseWrapper,
|
||||||
|
PromiseCompleter,
|
||||||
|
ObservableWrapper
|
||||||
|
} from 'angular2/src/facade/async';
|
||||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {TestabilityRegistry, Testability} from 'angular2/src/core/testability/testability';
|
import {TestabilityRegistry, Testability} from 'angular2/src/core/testability/testability';
|
||||||
import {
|
import {
|
||||||
@ -250,7 +255,7 @@ export class PlatformRef_ extends PlatformRef {
|
|||||||
provide(ApplicationRef, {useFactory: (): ApplicationRef => app, deps: []})
|
provide(ApplicationRef, {useFactory: (): ApplicationRef => app, deps: []})
|
||||||
]);
|
]);
|
||||||
|
|
||||||
var exceptionHandler: Function;
|
var exceptionHandler;
|
||||||
try {
|
try {
|
||||||
injector = this.injector.resolveAndCreateChild(providers);
|
injector = this.injector.resolveAndCreateChild(providers);
|
||||||
exceptionHandler = injector.get(ExceptionHandler);
|
exceptionHandler = injector.get(ExceptionHandler);
|
||||||
@ -427,7 +432,7 @@ export class ApplicationRef_ extends ApplicationRef {
|
|||||||
try {
|
try {
|
||||||
var injector: Injector = this._injector.resolveAndCreateChild(componentProviders);
|
var injector: Injector = this._injector.resolveAndCreateChild(componentProviders);
|
||||||
var compRefToken: Promise<ComponentRef> = injector.get(APP_COMPONENT_REF_PROMISE);
|
var compRefToken: Promise<ComponentRef> = injector.get(APP_COMPONENT_REF_PROMISE);
|
||||||
var tick = (componentRef: ComponentRef) => {
|
var tick = (componentRef) => {
|
||||||
this._loadComponent(componentRef);
|
this._loadComponent(componentRef);
|
||||||
completer.resolve(componentRef);
|
completer.resolve(componentRef);
|
||||||
};
|
};
|
||||||
@ -451,32 +456,32 @@ export class ApplicationRef_ extends ApplicationRef {
|
|||||||
});
|
});
|
||||||
return completer.promise.then(_ => {
|
return completer.promise.then(_ => {
|
||||||
let c = this._injector.get(Console);
|
let c = this._injector.get(Console);
|
||||||
if (assertionsEnabled()) {
|
let modeDescription =
|
||||||
c.log(
|
assertionsEnabled() ?
|
||||||
"Angular 2 is running in the development mode. Call enableProdMode() to enable the production mode.");
|
"in the development mode. Call enableProdMode() to enable the production mode." :
|
||||||
}
|
"in the production mode. Call enableDevMode() to enable the development mode.";
|
||||||
|
c.log(`Angular 2 is running ${modeDescription}`);
|
||||||
return _;
|
return _;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_loadComponent(componentRef: ComponentRef): void {
|
_loadComponent(ref): void {
|
||||||
var appChangeDetector =
|
var appChangeDetector = (<ElementRef_>ref.location).internalElement.parentView.changeDetector;
|
||||||
(<ElementRef_>componentRef.location).internalElement.parentView.changeDetector;
|
|
||||||
this._changeDetectorRefs.push(appChangeDetector.ref);
|
this._changeDetectorRefs.push(appChangeDetector.ref);
|
||||||
this.tick();
|
this.tick();
|
||||||
this._rootComponents.push(componentRef);
|
this._rootComponents.push(ref);
|
||||||
this._bootstrapListeners.forEach((listener) => listener(componentRef));
|
this._bootstrapListeners.forEach((listener) => listener(ref));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_unloadComponent(componentRef: ComponentRef): void {
|
_unloadComponent(ref): void {
|
||||||
if (!ListWrapper.contains(this._rootComponents, componentRef)) {
|
if (!ListWrapper.contains(this._rootComponents, ref)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.unregisterChangeDetector(
|
this.unregisterChangeDetector(
|
||||||
(<ElementRef_>componentRef.location).internalElement.parentView.changeDetector.ref);
|
(<ElementRef_>ref.location).internalElement.parentView.changeDetector.ref);
|
||||||
ListWrapper.remove(this._rootComponents, componentRef);
|
ListWrapper.remove(this._rootComponents, ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
get injector(): Injector { return this._injector; }
|
get injector(): Injector { return this._injector; }
|
||||||
|
@ -16,6 +16,7 @@ import {BindingTarget} from './binding_record';
|
|||||||
import {Locals} from './parser/locals';
|
import {Locals} from './parser/locals';
|
||||||
import {ChangeDetectionStrategy, ChangeDetectorState} from './constants';
|
import {ChangeDetectionStrategy, ChangeDetectorState} from './constants';
|
||||||
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
|
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
|
||||||
|
import {isObservable} from './observable_facade';
|
||||||
import {ObservableWrapper} from 'angular2/src/facade/async';
|
import {ObservableWrapper} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
var _scope_check: WtfScopeFn = wtfCreateScope(`ChangeDetector#check(ascii id, bool throwOnChange)`);
|
var _scope_check: WtfScopeFn = wtfCreateScope(`ChangeDetector#check(ascii id, bool throwOnChange)`);
|
||||||
@ -41,6 +42,10 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
|||||||
propertyBindingIndex: number;
|
propertyBindingIndex: number;
|
||||||
outputSubscriptions: any[];
|
outputSubscriptions: any[];
|
||||||
|
|
||||||
|
// This is an experimental feature. Works only in Dart.
|
||||||
|
subscriptions: any[];
|
||||||
|
streams: any[];
|
||||||
|
|
||||||
dispatcher: ChangeDispatcher;
|
dispatcher: ChangeDispatcher;
|
||||||
|
|
||||||
|
|
||||||
@ -68,7 +73,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
|||||||
|
|
||||||
handleEvent(eventName: string, elIndex: number, event: any): boolean {
|
handleEvent(eventName: string, elIndex: number, event: any): boolean {
|
||||||
if (!this.hydrated()) {
|
if (!this.hydrated()) {
|
||||||
this.throwDehydratedError(`${this.id} -> ${eventName}`);
|
this.throwDehydratedError();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
var locals = new Map<string, any>();
|
var locals = new Map<string, any>();
|
||||||
@ -125,7 +130,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
|||||||
// facilitate error reporting.
|
// facilitate error reporting.
|
||||||
detectChangesInRecords(throwOnChange: boolean): void {
|
detectChangesInRecords(throwOnChange: boolean): void {
|
||||||
if (!this.hydrated()) {
|
if (!this.hydrated()) {
|
||||||
this.throwDehydratedError(this.id);
|
this.throwDehydratedError();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
this.detectChangesInRecordsInternal(throwOnChange);
|
this.detectChangesInRecordsInternal(throwOnChange);
|
||||||
@ -153,6 +158,10 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
|||||||
this.mode = ChangeDetectionUtil.changeDetectionMode(this.strategy);
|
this.mode = ChangeDetectionUtil.changeDetectionMode(this.strategy);
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
|
if (this.strategy === ChangeDetectionStrategy.OnPushObserve) {
|
||||||
|
this.observeComponent(context);
|
||||||
|
}
|
||||||
|
|
||||||
this.locals = locals;
|
this.locals = locals;
|
||||||
this.pipes = pipes;
|
this.pipes = pipes;
|
||||||
this.hydrateDirectives(dispatcher);
|
this.hydrateDirectives(dispatcher);
|
||||||
@ -167,6 +176,11 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
|||||||
dehydrate(): void {
|
dehydrate(): void {
|
||||||
this.dehydrateDirectives(true);
|
this.dehydrateDirectives(true);
|
||||||
|
|
||||||
|
// This is an experimental feature. Works only in Dart.
|
||||||
|
if (this.strategy === ChangeDetectionStrategy.OnPushObserve) {
|
||||||
|
this._unsubsribeFromObservables();
|
||||||
|
}
|
||||||
|
|
||||||
this._unsubscribeFromOutputs();
|
this._unsubscribeFromOutputs();
|
||||||
|
|
||||||
this.dispatcher = null;
|
this.dispatcher = null;
|
||||||
@ -234,6 +248,19 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is an experimental feature. Works only in Dart.
|
||||||
|
private _unsubsribeFromObservables(): void {
|
||||||
|
if (isPresent(this.subscriptions)) {
|
||||||
|
for (var i = 0; i < this.subscriptions.length; ++i) {
|
||||||
|
var s = this.subscriptions[i];
|
||||||
|
if (isPresent(this.subscriptions[i])) {
|
||||||
|
s.cancel();
|
||||||
|
this.subscriptions[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _unsubscribeFromOutputs(): void {
|
private _unsubscribeFromOutputs(): void {
|
||||||
if (isPresent(this.outputSubscriptions)) {
|
if (isPresent(this.outputSubscriptions)) {
|
||||||
for (var i = 0; i < this.outputSubscriptions.length; ++i) {
|
for (var i = 0; i < this.outputSubscriptions.length; ++i) {
|
||||||
@ -243,6 +270,53 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is an experimental feature. Works only in Dart.
|
||||||
|
observeValue(value: any, index: number): any {
|
||||||
|
if (isObservable(value)) {
|
||||||
|
this._createArrayToStoreObservables();
|
||||||
|
if (isBlank(this.subscriptions[index])) {
|
||||||
|
this.streams[index] = value.changes;
|
||||||
|
this.subscriptions[index] = value.changes.listen((_) => this.ref.markForCheck());
|
||||||
|
} else if (this.streams[index] !== value.changes) {
|
||||||
|
this.subscriptions[index].cancel();
|
||||||
|
this.streams[index] = value.changes;
|
||||||
|
this.subscriptions[index] = value.changes.listen((_) => this.ref.markForCheck());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is an experimental feature. Works only in Dart.
|
||||||
|
observeDirective(value: any, index: number): any {
|
||||||
|
if (isObservable(value)) {
|
||||||
|
this._createArrayToStoreObservables();
|
||||||
|
var arrayIndex = this.numberOfPropertyProtoRecords + index + 2; // +1 is component
|
||||||
|
this.streams[arrayIndex] = value.changes;
|
||||||
|
this.subscriptions[arrayIndex] = value.changes.listen((_) => this.ref.markForCheck());
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is an experimental feature. Works only in Dart.
|
||||||
|
observeComponent(value: any): any {
|
||||||
|
if (isObservable(value)) {
|
||||||
|
this._createArrayToStoreObservables();
|
||||||
|
var index = this.numberOfPropertyProtoRecords + 1;
|
||||||
|
this.streams[index] = value.changes;
|
||||||
|
this.subscriptions[index] = value.changes.listen((_) => this.ref.markForCheck());
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _createArrayToStoreObservables(): void {
|
||||||
|
if (isBlank(this.subscriptions)) {
|
||||||
|
this.subscriptions = ListWrapper.createFixedSize(this.numberOfPropertyProtoRecords +
|
||||||
|
this.directiveIndices.length + 2);
|
||||||
|
this.streams = ListWrapper.createFixedSize(this.numberOfPropertyProtoRecords +
|
||||||
|
this.directiveIndices.length + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getDirectiveFor(directives: any, index: number): any {
|
getDirectiveFor(directives: any, index: number): any {
|
||||||
return directives.getDirectiveFor(this.directiveIndices[index]);
|
return directives.getDirectiveFor(this.directiveIndices[index]);
|
||||||
}
|
}
|
||||||
@ -288,7 +362,7 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
|
|||||||
oldValue, newValue, null);
|
oldValue, newValue, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
throwDehydratedError(detail: string): void { throw new DehydratedException(detail); }
|
throwDehydratedError(): void { throw new DehydratedException(); }
|
||||||
|
|
||||||
private _currentBinding(): BindingTarget {
|
private _currentBinding(): BindingTarget {
|
||||||
return this.bindingTargets[this.propertyBindingIndex];
|
return this.bindingTargets[this.propertyBindingIndex];
|
||||||
|
@ -57,8 +57,9 @@ export class ChangeDetectorJITGenerator {
|
|||||||
this.directiveRecords = definition.directiveRecords;
|
this.directiveRecords = definition.directiveRecords;
|
||||||
this._names = new CodegenNameUtil(this.records, this.eventBindings, this.directiveRecords,
|
this._names = new CodegenNameUtil(this.records, this.eventBindings, this.directiveRecords,
|
||||||
this.changeDetectionUtilVarName);
|
this.changeDetectionUtilVarName);
|
||||||
this._logic = new CodegenLogicUtil(this._names, this.changeDetectionUtilVarName,
|
this._logic =
|
||||||
this.changeDetectorStateVarName);
|
new CodegenLogicUtil(this._names, this.changeDetectionUtilVarName,
|
||||||
|
this.changeDetectorStateVarName, this.changeDetectionStrategy);
|
||||||
this.typeName = sanitizeName(`ChangeDetector_${this.id}`);
|
this.typeName = sanitizeName(`ChangeDetector_${this.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,7 +174,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
var evalRecord = this._logic.genEventBindingEvalValue(eb, r);
|
var evalRecord = this._logic.genEventBindingEvalValue(eb, r);
|
||||||
var markPath = this._genMarkPathToRootAsCheckOnce(r);
|
var markPath = this._genMarkPathToRootAsCheckOnce(r);
|
||||||
var prevDefault = this._genUpdatePreventDefault(eb, r);
|
var prevDefault = this._genUpdatePreventDefault(eb, r);
|
||||||
return `${markPath}\n${evalRecord}\n${prevDefault}`;
|
return `${evalRecord}\n${markPath}\n${prevDefault}`;
|
||||||
} else {
|
} else {
|
||||||
return this._logic.genEventBindingEvalValue(eb, r);
|
return this._logic.genEventBindingEvalValue(eb, r);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import {codify, combineGeneratedStrings, rawString} from './codegen_facade';
|
|||||||
import {ProtoRecord, RecordType} from './proto_record';
|
import {ProtoRecord, RecordType} from './proto_record';
|
||||||
import {BindingTarget} from './binding_record';
|
import {BindingTarget} from './binding_record';
|
||||||
import {DirectiveRecord} from './directive_record';
|
import {DirectiveRecord} from './directive_record';
|
||||||
|
import {ChangeDetectionStrategy} from './constants';
|
||||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,7 +12,8 @@ import {BaseException} from 'angular2/src/facade/exceptions';
|
|||||||
*/
|
*/
|
||||||
export class CodegenLogicUtil {
|
export class CodegenLogicUtil {
|
||||||
constructor(private _names: CodegenNameUtil, private _utilName: string,
|
constructor(private _names: CodegenNameUtil, private _utilName: string,
|
||||||
private _changeDetectorStateName: string) {}
|
private _changeDetectorStateName: string,
|
||||||
|
private _changeDetection: ChangeDetectionStrategy) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a statement which updates the local variable representing `protoRec` with the current
|
* Generates a statement which updates the local variable representing `protoRec` with the current
|
||||||
@ -49,12 +51,13 @@ export class CodegenLogicUtil {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.PropertyRead:
|
case RecordType.PropertyRead:
|
||||||
rhs = `${context}.${protoRec.name}`;
|
rhs = this._observe(`${context}.${protoRec.name}`, protoRec);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.SafeProperty:
|
case RecordType.SafeProperty:
|
||||||
var read = `${context}.${protoRec.name}`;
|
var read = this._observe(`${context}.${protoRec.name}`, protoRec);
|
||||||
rhs = `${this._utilName}.isValueBlank(${context}) ? null : ${read}`;
|
rhs =
|
||||||
|
`${this._utilName}.isValueBlank(${context}) ? null : ${this._observe(read, protoRec)}`;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.PropertyWrite:
|
case RecordType.PropertyWrite:
|
||||||
@ -62,16 +65,17 @@ export class CodegenLogicUtil {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.Local:
|
case RecordType.Local:
|
||||||
rhs = `${localsAccessor}.get(${rawString(protoRec.name)})`;
|
rhs = this._observe(`${localsAccessor}.get(${rawString(protoRec.name)})`, protoRec);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.InvokeMethod:
|
case RecordType.InvokeMethod:
|
||||||
rhs = `${context}.${protoRec.name}(${argString})`;
|
rhs = this._observe(`${context}.${protoRec.name}(${argString})`, protoRec);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.SafeMethodInvoke:
|
case RecordType.SafeMethodInvoke:
|
||||||
var invoke = `${context}.${protoRec.name}(${argString})`;
|
var invoke = `${context}.${protoRec.name}(${argString})`;
|
||||||
rhs = `${this._utilName}.isValueBlank(${context}) ? null : ${invoke}`;
|
rhs =
|
||||||
|
`${this._utilName}.isValueBlank(${context}) ? null : ${this._observe(invoke, protoRec)}`;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.InvokeClosure:
|
case RecordType.InvokeClosure:
|
||||||
@ -91,7 +95,7 @@ export class CodegenLogicUtil {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.KeyedRead:
|
case RecordType.KeyedRead:
|
||||||
rhs = `${context}[${getLocalName(protoRec.args[0])}]`;
|
rhs = this._observe(`${context}[${getLocalName(protoRec.args[0])}]`, protoRec);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.KeyedWrite:
|
case RecordType.KeyedWrite:
|
||||||
@ -108,6 +112,16 @@ export class CodegenLogicUtil {
|
|||||||
return `${getLocalName(protoRec.selfIndex)} = ${rhs};`;
|
return `${getLocalName(protoRec.selfIndex)} = ${rhs};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
_observe(exp: string, rec: ProtoRecord): string {
|
||||||
|
// This is an experimental feature. Works only in Dart.
|
||||||
|
if (this._changeDetection === ChangeDetectionStrategy.OnPushObserve) {
|
||||||
|
return `this.observeValue(${exp}, ${rec.selfIndex})`;
|
||||||
|
} else {
|
||||||
|
return exp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
genPropertyBindingTargets(propertyBindingTargets: BindingTarget[],
|
genPropertyBindingTargets(propertyBindingTargets: BindingTarget[],
|
||||||
genDebugInfo: boolean): string {
|
genDebugInfo: boolean): string {
|
||||||
var bs = propertyBindingTargets.map(b => {
|
var bs = propertyBindingTargets.map(b => {
|
||||||
@ -188,7 +202,15 @@ export class CodegenLogicUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _genReadDirective(index: number) { return `this.getDirectiveFor(directives, ${index})`; }
|
private _genReadDirective(index: number) {
|
||||||
|
var directiveExpr = `this.getDirectiveFor(directives, ${index})`;
|
||||||
|
// This is an experimental feature. Works only in Dart.
|
||||||
|
if (this._changeDetection === ChangeDetectionStrategy.OnPushObserve) {
|
||||||
|
return `this.observeDirective(${directiveExpr}, ${index})`;
|
||||||
|
} else {
|
||||||
|
return directiveExpr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
genHydrateDetectors(directiveRecords: DirectiveRecord[]): string {
|
genHydrateDetectors(directiveRecords: DirectiveRecord[]): string {
|
||||||
var res = [];
|
var res = [];
|
||||||
|
@ -62,6 +62,11 @@ export enum ChangeDetectionStrategy {
|
|||||||
* `Default` means that the change detector's mode will be set to `CheckAlways` during hydration.
|
* `Default` means that the change detector's mode will be set to `CheckAlways` during hydration.
|
||||||
*/
|
*/
|
||||||
Default,
|
Default,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is an experimental feature. Works only in Dart.
|
||||||
|
*/
|
||||||
|
OnPushObserve
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,7 +78,8 @@ export var CHANGE_DETECTION_STRATEGY_VALUES = [
|
|||||||
ChangeDetectionStrategy.CheckAlways,
|
ChangeDetectionStrategy.CheckAlways,
|
||||||
ChangeDetectionStrategy.Detached,
|
ChangeDetectionStrategy.Detached,
|
||||||
ChangeDetectionStrategy.OnPush,
|
ChangeDetectionStrategy.OnPush,
|
||||||
ChangeDetectionStrategy.Default
|
ChangeDetectionStrategy.Default,
|
||||||
|
ChangeDetectionStrategy.OnPushObserve
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,9 +40,6 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
private _movesTail: CollectionChangeRecord = null;
|
private _movesTail: CollectionChangeRecord = null;
|
||||||
private _removalsHead: CollectionChangeRecord = null;
|
private _removalsHead: CollectionChangeRecord = null;
|
||||||
private _removalsTail: CollectionChangeRecord = null;
|
private _removalsTail: CollectionChangeRecord = null;
|
||||||
// Keeps track of records where custom track by is the same, but item identity has changed
|
|
||||||
private _identityChangesHead: CollectionChangeRecord = null;
|
|
||||||
private _identityChangesTail: CollectionChangeRecord = null;
|
|
||||||
|
|
||||||
constructor(private _trackByFn?: TrackByFn) {
|
constructor(private _trackByFn?: TrackByFn) {
|
||||||
this._trackByFn = isPresent(this._trackByFn) ? this._trackByFn : trackByIdentity;
|
this._trackByFn = isPresent(this._trackByFn) ? this._trackByFn : trackByIdentity;
|
||||||
@ -87,13 +84,6 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forEachIdentityChange(fn: Function) {
|
|
||||||
var record: CollectionChangeRecord;
|
|
||||||
for (record = this._identityChangesHead; record !== null; record = record._nextIdentityChange) {
|
|
||||||
fn(record);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
diff(collection: any): DefaultIterableDiffer {
|
diff(collection: any): DefaultIterableDiffer {
|
||||||
if (isBlank(collection)) collection = [];
|
if (isBlank(collection)) collection = [];
|
||||||
if (!isListLikeIterable(collection)) {
|
if (!isListLikeIterable(collection)) {
|
||||||
@ -133,7 +123,7 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
// TODO(misko): can we limit this to duplicates only?
|
// TODO(misko): can we limit this to duplicates only?
|
||||||
record = this._verifyReinsertion(record, item, itemTrackBy, index);
|
record = this._verifyReinsertion(record, item, itemTrackBy, index);
|
||||||
}
|
}
|
||||||
if (!looseIdentical(record.item, item)) this._addIdentityChange(record, item);
|
record.item = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
record = record._next;
|
record = record._next;
|
||||||
@ -145,13 +135,10 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
if (record === null || !looseIdentical(record.trackById, itemTrackBy)) {
|
if (record === null || !looseIdentical(record.trackById, itemTrackBy)) {
|
||||||
record = this._mismatch(record, item, itemTrackBy, index);
|
record = this._mismatch(record, item, itemTrackBy, index);
|
||||||
mayBeDirty = true;
|
mayBeDirty = true;
|
||||||
} else {
|
} else if (mayBeDirty) {
|
||||||
if (mayBeDirty) {
|
|
||||||
// TODO(misko): can we limit this to duplicates only?
|
// TODO(misko): can we limit this to duplicates only?
|
||||||
record = this._verifyReinsertion(record, item, itemTrackBy, index);
|
record = this._verifyReinsertion(record, item, itemTrackBy, index);
|
||||||
}
|
}
|
||||||
if (!looseIdentical(record.item, item)) this._addIdentityChange(record, item);
|
|
||||||
}
|
|
||||||
record = record._next;
|
record = record._next;
|
||||||
index++;
|
index++;
|
||||||
});
|
});
|
||||||
@ -163,12 +150,9 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
return this.isDirty;
|
return this.isDirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CollectionChanges is considered dirty if it has any additions, moves, removals, or identity
|
// CollectionChanges is considered dirty if it has any additions, moves or removals.
|
||||||
* changes.
|
|
||||||
*/
|
|
||||||
get isDirty(): boolean {
|
get isDirty(): boolean {
|
||||||
return this._additionsHead !== null || this._movesHead !== null ||
|
return this._additionsHead !== null || this._movesHead !== null || this._removalsHead !== null;
|
||||||
this._removalsHead !== null || this._identityChangesHead !== null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -199,7 +183,6 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
}
|
}
|
||||||
this._movesHead = this._movesTail = null;
|
this._movesHead = this._movesTail = null;
|
||||||
this._removalsHead = this._removalsTail = null;
|
this._removalsHead = this._removalsTail = null;
|
||||||
this._identityChangesHead = this._identityChangesTail = null;
|
|
||||||
|
|
||||||
// todo(vicb) when assert gets supported
|
// todo(vicb) when assert gets supported
|
||||||
// assert(!this.isDirty);
|
// assert(!this.isDirty);
|
||||||
@ -233,18 +216,12 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
record = this._linkedRecords === null ? null : this._linkedRecords.get(itemTrackBy, index);
|
record = this._linkedRecords === null ? null : this._linkedRecords.get(itemTrackBy, index);
|
||||||
if (record !== null) {
|
if (record !== null) {
|
||||||
// We have seen this before, we need to move it forward in the collection.
|
// We have seen this before, we need to move it forward in the collection.
|
||||||
// But first we need to check if identity changed, so we can update in view if necessary
|
|
||||||
if (!looseIdentical(record.item, item)) this._addIdentityChange(record, item);
|
|
||||||
|
|
||||||
this._moveAfter(record, previousRecord, index);
|
this._moveAfter(record, previousRecord, index);
|
||||||
} else {
|
} else {
|
||||||
// Never seen it, check evicted list.
|
// Never seen it, check evicted list.
|
||||||
record = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy);
|
record = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy);
|
||||||
if (record !== null) {
|
if (record !== null) {
|
||||||
// It is an item which we have evicted earlier: reinsert it back into the list.
|
// It is an item which we have evicted earlier: reinsert it back into the list.
|
||||||
// But first we need to check if identity changed, so we can update in view if necessary
|
|
||||||
if (!looseIdentical(record.item, item)) this._addIdentityChange(record, item);
|
|
||||||
|
|
||||||
this._reinsertAfter(record, previousRecord, index);
|
this._reinsertAfter(record, previousRecord, index);
|
||||||
} else {
|
} else {
|
||||||
// It is a new item: add it.
|
// It is a new item: add it.
|
||||||
@ -292,6 +269,7 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
record.currentIndex = index;
|
record.currentIndex = index;
|
||||||
this._addToMoves(record, index);
|
this._addToMoves(record, index);
|
||||||
}
|
}
|
||||||
|
record.item = item;
|
||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,9 +303,6 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
if (this._removalsTail !== null) {
|
if (this._removalsTail !== null) {
|
||||||
this._removalsTail._nextRemoved = null;
|
this._removalsTail._nextRemoved = null;
|
||||||
}
|
}
|
||||||
if (this._identityChangesTail !== null) {
|
|
||||||
this._identityChangesTail._nextIdentityChange = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
@ -494,18 +469,6 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
_addIdentityChange(record: CollectionChangeRecord, item: any) {
|
|
||||||
record.item = item;
|
|
||||||
if (this._identityChangesTail === null) {
|
|
||||||
this._identityChangesTail = this._identityChangesHead = record;
|
|
||||||
} else {
|
|
||||||
this._identityChangesTail = this._identityChangesTail._nextIdentityChange = record;
|
|
||||||
}
|
|
||||||
return record;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
var list = [];
|
var list = [];
|
||||||
this.forEachItem((record) => list.push(record));
|
this.forEachItem((record) => list.push(record));
|
||||||
@ -522,13 +485,9 @@ export class DefaultIterableDiffer implements IterableDiffer {
|
|||||||
var removals = [];
|
var removals = [];
|
||||||
this.forEachRemovedItem((record) => removals.push(record));
|
this.forEachRemovedItem((record) => removals.push(record));
|
||||||
|
|
||||||
var identityChanges = [];
|
|
||||||
this.forEachIdentityChange((record) => identityChanges.push(record));
|
|
||||||
|
|
||||||
return "collection: " + list.join(', ') + "\n" + "previous: " + previous.join(', ') + "\n" +
|
return "collection: " + list.join(', ') + "\n" + "previous: " + previous.join(', ') + "\n" +
|
||||||
"additions: " + additions.join(', ') + "\n" + "moves: " + moves.join(', ') + "\n" +
|
"additions: " + additions.join(', ') + "\n" + "moves: " + moves.join(', ') + "\n" +
|
||||||
"removals: " + removals.join(', ') + "\n" + "identityChanges: " +
|
"removals: " + removals.join(', ') + "\n";
|
||||||
identityChanges.join(', ') + "\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,9 +513,6 @@ export class CollectionChangeRecord {
|
|||||||
_nextAdded: CollectionChangeRecord = null;
|
_nextAdded: CollectionChangeRecord = null;
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_nextMoved: CollectionChangeRecord = null;
|
_nextMoved: CollectionChangeRecord = null;
|
||||||
/** @internal */
|
|
||||||
_nextIdentityChange: CollectionChangeRecord = null;
|
|
||||||
|
|
||||||
|
|
||||||
constructor(public item: any, public trackById: any) {}
|
constructor(public item: any, public trackById: any) {}
|
||||||
|
|
||||||
|
@ -60,11 +60,9 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
|
|||||||
if (proto.isSkipRecord()) {
|
if (proto.isSkipRecord()) {
|
||||||
protoIdx += this._computeSkipLength(protoIdx, proto, values);
|
protoIdx += this._computeSkipLength(protoIdx, proto, values);
|
||||||
} else {
|
} else {
|
||||||
if (proto.lastInBinding) {
|
|
||||||
this._markPathAsCheckOnce(proto);
|
|
||||||
}
|
|
||||||
var res = this._calculateCurrValue(proto, values, locals);
|
var res = this._calculateCurrValue(proto, values, locals);
|
||||||
if (proto.lastInBinding) {
|
if (proto.lastInBinding) {
|
||||||
|
this._markPathAsCheckOnce(proto);
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
this._writeSelf(proto, res, values);
|
this._writeSelf(proto, res, values);
|
||||||
@ -110,6 +108,12 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
|
|||||||
this.values[0] = this.context;
|
this.values[0] = this.context;
|
||||||
this.dispatcher = dispatcher;
|
this.dispatcher = dispatcher;
|
||||||
|
|
||||||
|
if (this.strategy === ChangeDetectionStrategy.OnPushObserve) {
|
||||||
|
for (var i = 0; i < this.directiveIndices.length; ++i) {
|
||||||
|
var index = this.directiveIndices[i];
|
||||||
|
super.observeDirective(this._getDirectiveFor(index), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
this.outputSubscriptions = [];
|
this.outputSubscriptions = [];
|
||||||
for (var i = 0; i < this._directiveRecords.length; ++i) {
|
for (var i = 0; i < this._directiveRecords.length; ++i) {
|
||||||
var r = this._directiveRecords[i];
|
var r = this._directiveRecords[i];
|
||||||
@ -294,6 +298,9 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var currValue = this._calculateCurrValue(proto, values, locals);
|
var currValue = this._calculateCurrValue(proto, values, locals);
|
||||||
|
if (this.strategy === ChangeDetectionStrategy.OnPushObserve) {
|
||||||
|
super.observeValue(currValue, proto.selfIndex);
|
||||||
|
}
|
||||||
|
|
||||||
if (proto.shouldBeChecked()) {
|
if (proto.shouldBeChecked()) {
|
||||||
var prevValue = this._readSelf(proto, values);
|
var prevValue = this._readSelf(proto, values);
|
||||||
|
@ -91,7 +91,7 @@ export class ChangeDetectionError extends WrappedException {
|
|||||||
* This is an internal Angular error.
|
* This is an internal Angular error.
|
||||||
*/
|
*/
|
||||||
export class DehydratedException extends BaseException {
|
export class DehydratedException extends BaseException {
|
||||||
constructor(details: string) { super(`Attempt to use a dehydrated detector: ${details}`); }
|
constructor() { super('Attempt to use a dehydrated detector.'); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
library change_detection.observable_facade;
|
||||||
|
|
||||||
|
import 'package:observe/observe.dart';
|
||||||
|
|
||||||
|
bool isObservable(value) => value is Observable;
|
@ -0,0 +1,3 @@
|
|||||||
|
export function isObservable(value: any): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
@ -248,12 +248,15 @@ class _Scanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scanCharacter(start: number, code: number): Token {
|
scanCharacter(start: number, code: number): Token {
|
||||||
|
assert(this.peek == code);
|
||||||
this.advance();
|
this.advance();
|
||||||
return newCharacterToken(start, code);
|
return newCharacterToken(start, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
scanOperator(start: number, str: string): Token {
|
scanOperator(start: number, str: string): Token {
|
||||||
|
assert(this.peek == StringWrapper.charCodeAt(str, 0));
|
||||||
|
assert(SetWrapper.has(OPERATORS, str));
|
||||||
this.advance();
|
this.advance();
|
||||||
return newOperatorToken(start, str);
|
return newOperatorToken(start, str);
|
||||||
}
|
}
|
||||||
@ -271,6 +274,7 @@ class _Scanner {
|
|||||||
*/
|
*/
|
||||||
scanComplexOperator(start: number, one: string, twoCode: number, two: string, threeCode?: number,
|
scanComplexOperator(start: number, one: string, twoCode: number, two: string, threeCode?: number,
|
||||||
three?: string): Token {
|
three?: string): Token {
|
||||||
|
assert(this.peek == StringWrapper.charCodeAt(one, 0));
|
||||||
this.advance();
|
this.advance();
|
||||||
var str: string = one;
|
var str: string = one;
|
||||||
if (this.peek == twoCode) {
|
if (this.peek == twoCode) {
|
||||||
@ -281,10 +285,12 @@ class _Scanner {
|
|||||||
this.advance();
|
this.advance();
|
||||||
str += three;
|
str += three;
|
||||||
}
|
}
|
||||||
|
assert(SetWrapper.has(OPERATORS, str));
|
||||||
return newOperatorToken(start, str);
|
return newOperatorToken(start, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
scanIdentifier(): Token {
|
scanIdentifier(): Token {
|
||||||
|
assert(isIdentifierStart(this.peek));
|
||||||
var start: number = this.index;
|
var start: number = this.index;
|
||||||
this.advance();
|
this.advance();
|
||||||
while (isIdentifierPart(this.peek)) this.advance();
|
while (isIdentifierPart(this.peek)) this.advance();
|
||||||
@ -297,6 +303,7 @@ class _Scanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scanNumber(start: number): Token {
|
scanNumber(start: number): Token {
|
||||||
|
assert(isDigit(this.peek));
|
||||||
var simple: boolean = (this.index === start);
|
var simple: boolean = (this.index === start);
|
||||||
this.advance(); // Skip initial digit.
|
this.advance(); // Skip initial digit.
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -322,6 +329,7 @@ class _Scanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scanString(): Token {
|
scanString(): Token {
|
||||||
|
assert(this.peek == $SQ || this.peek == $DQ);
|
||||||
var start: number = this.index;
|
var start: number = this.index;
|
||||||
var quote: number = this.peek;
|
var quote: number = this.peek;
|
||||||
this.advance(); // Skip initial quote.
|
this.advance(); // Skip initial quote.
|
||||||
|
@ -49,7 +49,7 @@ import {
|
|||||||
|
|
||||||
var _implicitReceiver = new ImplicitReceiver();
|
var _implicitReceiver = new ImplicitReceiver();
|
||||||
// TODO(tbosch): Cannot make this const/final right now because of the transpiler...
|
// TODO(tbosch): Cannot make this const/final right now because of the transpiler...
|
||||||
var INTERPOLATION_REGEXP = /\{\{([\s\S]*?)\}\}/g;
|
var INTERPOLATION_REGEXP = /\{\{(.*?)\}\}/g;
|
||||||
|
|
||||||
class ParseException extends BaseException {
|
class ParseException extends BaseException {
|
||||||
constructor(message: string, input: string, errLocation: string, ctxLocation?: any) {
|
constructor(message: string, input: string, errLocation: string, ctxLocation?: any) {
|
||||||
|
@ -31,7 +31,7 @@ export {
|
|||||||
ResolvedProvider,
|
ResolvedProvider,
|
||||||
provide
|
provide
|
||||||
} from './di/provider';
|
} from './di/provider';
|
||||||
export {Key} from './di/key';
|
export {Key, TypeLiteral} from './di/key';
|
||||||
export {
|
export {
|
||||||
NoProviderError,
|
NoProviderError,
|
||||||
AbstractProviderError,
|
AbstractProviderError,
|
||||||
|
@ -17,7 +17,6 @@ import {
|
|||||||
OutOfBoundsError
|
OutOfBoundsError
|
||||||
} from './exceptions';
|
} from './exceptions';
|
||||||
import {FunctionWrapper, Type, isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
|
import {FunctionWrapper, Type, isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
|
||||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
|
||||||
import {Key} from './key';
|
import {Key} from './key';
|
||||||
import {SelfMetadata, HostMetadata, SkipSelfMetadata} from './metadata';
|
import {SelfMetadata, HostMetadata, SkipSelfMetadata} from './metadata';
|
||||||
|
|
||||||
@ -777,26 +776,7 @@ export class Injector {
|
|||||||
var deps = resolvedFactory.dependencies;
|
var deps = resolvedFactory.dependencies;
|
||||||
var length = deps.length;
|
var length = deps.length;
|
||||||
|
|
||||||
var d0: any;
|
var d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16, d17, d18, d19;
|
||||||
var d1: any;
|
|
||||||
var d2: any;
|
|
||||||
var d3: any;
|
|
||||||
var d4: any;
|
|
||||||
var d5: any;
|
|
||||||
var d6: any;
|
|
||||||
var d7: any;
|
|
||||||
var d8: any;
|
|
||||||
var d9: any;
|
|
||||||
var d10: any;
|
|
||||||
var d11: any;
|
|
||||||
var d12: any;
|
|
||||||
var d13: any;
|
|
||||||
var d14: any;
|
|
||||||
var d15: any;
|
|
||||||
var d16: any;
|
|
||||||
var d17: any;
|
|
||||||
var d18: any;
|
|
||||||
var d19: any;
|
|
||||||
try {
|
try {
|
||||||
d0 = length > 0 ? this._getByDependency(provider, deps[0], visibility) : null;
|
d0 = length > 0 ? this._getByDependency(provider, deps[0], visibility) : null;
|
||||||
d1 = length > 1 ? this._getByDependency(provider, deps[1], visibility) : null;
|
d1 = length > 1 ? this._getByDependency(provider, deps[1], visibility) : null;
|
||||||
@ -894,9 +874,6 @@ export class Injector {
|
|||||||
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16,
|
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16,
|
||||||
d17, d18, d19);
|
d17, d18, d19);
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
throw new BaseException(
|
|
||||||
`Cannot instantiate '${provider.key.displayName}' because it has more than 20 dependencies`);
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new InstantiationError(this, e, e.stack, provider.key);
|
throw new InstantiationError(this, e, e.stack, provider.key);
|
||||||
@ -1004,7 +981,7 @@ export class Injector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get displayName(): string {
|
get displayName(): string {
|
||||||
return `Injector(providers: [${_mapProviders(this, (b: ResolvedProvider) => ` "${b.key.displayName}" `).join(", ")}])`;
|
return `Injector(providers: [${_mapProviders(this, b => ` "${b.key.displayName}" `).join(", ")}])`;
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string { return this.displayName; }
|
toString(): string { return this.displayName; }
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import {stringify, CONST, Type, isBlank} from 'angular2/src/facade/lang';
|
import {stringify, CONST, Type, isBlank} from 'angular2/src/facade/lang';
|
||||||
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
||||||
|
import {TypeLiteral} from './type_literal';
|
||||||
import {resolveForwardRef} from './forward_ref';
|
import {resolveForwardRef} from './forward_ref';
|
||||||
|
|
||||||
|
export {TypeLiteral} from './type_literal';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A unique object used for retrieving items from the {@link Injector}.
|
* A unique object used for retrieving items from the {@link Injector}.
|
||||||
*
|
*
|
||||||
@ -50,6 +53,13 @@ export class KeyRegistry {
|
|||||||
get(token: Object): Key {
|
get(token: Object): Key {
|
||||||
if (token instanceof Key) return token;
|
if (token instanceof Key) return token;
|
||||||
|
|
||||||
|
// TODO: workaround for https://github.com/Microsoft/TypeScript/issues/3123
|
||||||
|
var theToken = token;
|
||||||
|
if (token instanceof TypeLiteral) {
|
||||||
|
theToken = token.type;
|
||||||
|
}
|
||||||
|
token = theToken;
|
||||||
|
|
||||||
if (this._allKeys.has(token)) {
|
if (this._allKeys.has(token)) {
|
||||||
return this._allKeys.get(token);
|
return this._allKeys.get(token);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import {CONST} from 'angular2/src/facade/lang';
|
|||||||
* var t = new OpaqueToken("value");
|
* var t = new OpaqueToken("value");
|
||||||
*
|
*
|
||||||
* var injector = Injector.resolveAndCreate([
|
* var injector = Injector.resolveAndCreate([
|
||||||
* provide(t, {useValue: "bindingValue"})
|
* provide(t, {useValue: "providedValue"})
|
||||||
* ]);
|
* ]);
|
||||||
*
|
*
|
||||||
* expect(injector.get(t)).toEqual("bindingValue");
|
* expect(injector.get(t)).toEqual("bindingValue");
|
||||||
|
26
modules/angular2/src/core/di/type_literal.dart
Normal file
26
modules/angular2/src/core/di/type_literal.dart
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
library angular2.di.type_literal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use type literals as DI keys corresponding to generic types.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* Injector.resolveAndCreate([
|
||||||
|
* bind(new TypeLiteral<List<int>>()).toValue([1, 2, 3])
|
||||||
|
* ]);
|
||||||
|
*
|
||||||
|
* class Foo {
|
||||||
|
* // Delend on `List<int>` normally.
|
||||||
|
* Foo(List<int> list) { ... }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This capability might be added to the language one day. See:
|
||||||
|
*
|
||||||
|
* https://code.google.com/p/dart/issues/detail?id=11923
|
||||||
|
*/
|
||||||
|
class TypeLiteral<T> {
|
||||||
|
const TypeLiteral();
|
||||||
|
Type get type => T;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user