refactor(di): unified di injector and core injector
BREAKING CHANGES: * InjectAsync and InjectLazy have been removed * toAsyncFactory has been removed
This commit is contained in:
@ -1,6 +1,5 @@
|
||||
library angular2.core.decorators;
|
||||
|
||||
export '../annotations_impl/annotations.dart';
|
||||
export '../annotations_impl/visibility.dart';
|
||||
export '../annotations_impl/view.dart';
|
||||
export '../annotations_impl/di.dart';
|
||||
|
@ -5,12 +5,6 @@ import {
|
||||
DirectiveArgs
|
||||
} from './annotations';
|
||||
import {ViewAnnotation, ViewArgs} from './view';
|
||||
import {
|
||||
SelfAnnotation,
|
||||
ParentAnnotation,
|
||||
AncestorAnnotation,
|
||||
UnboundedAnnotation
|
||||
} from './visibility';
|
||||
import {AttributeAnnotation, QueryAnnotation} from './di';
|
||||
import {makeDecorator, makeParamDecorator, TypeDecorator, Class} from '../../util/decorators';
|
||||
import {Type} from 'angular2/src/facade/lang';
|
||||
@ -46,12 +40,6 @@ export var Directive = <Directive>makeDecorator(DirectiveAnnotation);
|
||||
/* from view */
|
||||
export var View = <View>makeDecorator(ViewAnnotation, (fn: any) => fn.View = View);
|
||||
|
||||
/* from visibility */
|
||||
export var Self = makeParamDecorator(SelfAnnotation);
|
||||
export var Parent = makeParamDecorator(ParentAnnotation);
|
||||
export var Ancestor = makeParamDecorator(AncestorAnnotation);
|
||||
export var Unbounded = makeParamDecorator(UnboundedAnnotation);
|
||||
|
||||
/* from di */
|
||||
export var Attribute = makeParamDecorator(AttributeAnnotation);
|
||||
export var Query = makeParamDecorator(QueryAnnotation);
|
||||
|
@ -1,3 +0,0 @@
|
||||
library angular2.core.annotations.visibility;
|
||||
|
||||
export "../annotations_impl/visibility.dart";
|
@ -1,6 +0,0 @@
|
||||
export {
|
||||
Self as SelfAnnotation,
|
||||
Ancestor as AncestorAnnotation,
|
||||
Parent as ParentAnnotation,
|
||||
Unbounded as UnboundedAnnotation
|
||||
} from '../annotations_impl/visibility';
|
@ -1,6 +1,6 @@
|
||||
import {CONST, CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {List} from 'angular2/src/facade/collection';
|
||||
import {Injectable} from 'angular2/src/di/annotations_impl';
|
||||
import {Injectable, self} from 'angular2/src/di/annotations_impl';
|
||||
import {DEFAULT} from 'angular2/change_detection';
|
||||
|
||||
// type StringMap = {[idx: string]: string};
|
||||
@ -788,7 +788,7 @@ export class Directive extends Injectable {
|
||||
selector, properties, events, host, lifecycle, hostInjector, exportAs,
|
||||
compileChildren = true,
|
||||
}: DirectiveArgs = {}) {
|
||||
super();
|
||||
super(self);
|
||||
this.selector = selector;
|
||||
this.properties = properties;
|
||||
this.events = events;
|
||||
|
@ -1,213 +0,0 @@
|
||||
import {CONST, CONST_EXPR, isBlank} from 'angular2/src/facade/lang';
|
||||
import {DependencyAnnotation} from 'angular2/src/di/annotations_impl';
|
||||
|
||||
@CONST()
|
||||
export class Visibility extends DependencyAnnotation {
|
||||
constructor(public depth: number, public crossComponentBoundaries: boolean,
|
||||
public _includeSelf: boolean) {
|
||||
super();
|
||||
}
|
||||
|
||||
get includeSelf(): boolean { return isBlank(this._includeSelf) ? false : this._includeSelf; }
|
||||
toString() {
|
||||
return `@Visibility(depth: ${this.depth}, crossComponentBoundaries: ${this.crossComponentBoundaries}, includeSelf: ${this.includeSelf}})`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that an injector should retrieve a dependency from its element.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* Here is a simple directive that retrieves a dependency from its element.
|
||||
*
|
||||
* ```
|
||||
* @Directive({
|
||||
* selector: '[dependency]',
|
||||
* properties: [
|
||||
* 'id: dependency'
|
||||
* ]
|
||||
* })
|
||||
* class Dependency {
|
||||
* id:string;
|
||||
* }
|
||||
*
|
||||
*
|
||||
* @Directive({
|
||||
* selector: '[my-directive]'
|
||||
* })
|
||||
* class Dependency {
|
||||
* constructor(@Self() dependency:Dependency) {
|
||||
* expect(dependency.id).toEqual(1);
|
||||
* };
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* We use this with the following HTML template:
|
||||
*
|
||||
* ```
|
||||
*<div dependency="1" my-directive></div>
|
||||
* ```
|
||||
*
|
||||
* @exportedAs angular2/annotations
|
||||
*/
|
||||
@CONST()
|
||||
export class Self extends Visibility {
|
||||
constructor() { super(0, false, true); }
|
||||
toString() { return `@Self()`; }
|
||||
}
|
||||
|
||||
// make constants after switching to ts2dart
|
||||
export var self = new Self();
|
||||
|
||||
/**
|
||||
* Specifies that an injector should retrieve a dependency from the direct parent.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* Here is a simple directive that retrieves a dependency from its parent element.
|
||||
*
|
||||
* ```
|
||||
* @Directive({
|
||||
* selector: '[dependency]',
|
||||
* properties: [
|
||||
* 'id: dependency'
|
||||
* ]
|
||||
* })
|
||||
* class Dependency {
|
||||
* id:string;
|
||||
* }
|
||||
*
|
||||
*
|
||||
* @Directive({
|
||||
* selector: '[my-directive]'
|
||||
* })
|
||||
* class Dependency {
|
||||
* constructor(@Parent() dependency:Dependency) {
|
||||
* expect(dependency.id).toEqual(1);
|
||||
* };
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* We use this with the following HTML template:
|
||||
*
|
||||
* ```
|
||||
* <div dependency="1">
|
||||
* <div dependency="2" my-directive></div>
|
||||
* </div>
|
||||
* ```
|
||||
* The `@Parent()` annotation in our constructor forces the injector to retrieve the dependency from
|
||||
* the
|
||||
* parent element (even thought the current element could resolve it): Angular injects
|
||||
* `dependency=1`.
|
||||
*
|
||||
* @exportedAs angular2/annotations
|
||||
*/
|
||||
@CONST()
|
||||
export class Parent extends Visibility {
|
||||
constructor({self}: {self?: boolean} = {}) { super(1, false, self); }
|
||||
toString() { return `@Parent(self: ${this.includeSelf}})`; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that an injector should retrieve a dependency from any ancestor element within the same
|
||||
* shadow boundary.
|
||||
*
|
||||
* An ancestor is any element between the parent element and the shadow root.
|
||||
*
|
||||
* Use {@link Unbounded} if you need to cross upper shadow boundaries.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* Here is a simple directive that retrieves a dependency from an ancestor element.
|
||||
*
|
||||
* ```
|
||||
* @Directive({
|
||||
* selector: '[dependency]',
|
||||
* properties: [
|
||||
* 'id: dependency'
|
||||
* ]
|
||||
* })
|
||||
* class Dependency {
|
||||
* id:string;
|
||||
* }
|
||||
*
|
||||
*
|
||||
* @Directive({
|
||||
* selector: '[my-directive]'
|
||||
* })
|
||||
* class Dependency {
|
||||
* constructor(@Ancestor() dependency:Dependency) {
|
||||
* expect(dependency.id).toEqual(2);
|
||||
* };
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* We use this with the following HTML template:
|
||||
*
|
||||
* ```
|
||||
* <div dependency="1">
|
||||
* <div dependency="2">
|
||||
* <div>
|
||||
* <div dependency="3" my-directive></div>
|
||||
* </div>
|
||||
* </div>
|
||||
* </div>
|
||||
* ```
|
||||
*
|
||||
* The `@Ancestor()` annotation in our constructor forces the injector to retrieve the dependency
|
||||
* from the
|
||||
* nearest ancestor element:
|
||||
* - The current element `dependency="3"` is skipped because it is not an ancestor.
|
||||
* - Next parent has no directives `<div>`
|
||||
* - Next parent has the `Dependency` directive and so the dependency is satisfied.
|
||||
*
|
||||
* Angular injects `dependency=2`.
|
||||
*
|
||||
* @exportedAs angular2/annotations
|
||||
*/
|
||||
@CONST()
|
||||
export class Ancestor extends Visibility {
|
||||
constructor({self}: {self?: boolean} = {}) { super(999999, false, self); }
|
||||
toString() { return `@Ancestor(self: ${this.includeSelf}})`; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that an injector should retrieve a dependency from any ancestor element, crossing
|
||||
* component boundaries.
|
||||
*
|
||||
* Use {@link Ancestor} to look for ancestors within the current shadow boundary only.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* Here is a simple directive that retrieves a dependency from an ancestor element.
|
||||
*
|
||||
* ```
|
||||
* @Directive({
|
||||
* selector: '[dependency]',
|
||||
* properties: [
|
||||
* 'id: dependency'
|
||||
* ]
|
||||
* })
|
||||
* class Dependency {
|
||||
* id:string;
|
||||
* }
|
||||
*
|
||||
*
|
||||
* @Directive({
|
||||
* selector: '[my-directive]'
|
||||
* })
|
||||
* class Dependency {
|
||||
* constructor(@Unbounded() dependency:Dependency) {
|
||||
* expect(dependency.id).toEqual(2);
|
||||
* };
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @exportedAs angular2/annotations
|
||||
*/
|
||||
@CONST()
|
||||
export class Unbounded extends Visibility {
|
||||
constructor({self}: {self?: boolean} = {}) { super(999999, true, self); }
|
||||
toString() { return `@Unbounded(self: ${this.includeSelf}})`; }
|
||||
}
|
@ -79,20 +79,19 @@ function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
|
||||
.toValue(DOM.defaultDoc()),
|
||||
bind(appComponentTypeToken).toValue(appComponentType),
|
||||
bind(appComponentRefToken)
|
||||
.toAsyncFactory(
|
||||
.toFactory(
|
||||
(dynamicComponentLoader, injector, testability, registry) => {
|
||||
|
||||
// TODO(rado): investigate whether to support bindings on root component.
|
||||
return dynamicComponentLoader.loadAsRoot(appComponentType, null, injector)
|
||||
.then((componentRef) => {
|
||||
registry.registerApplication(componentRef.location.nativeElement, testability);
|
||||
|
||||
return componentRef;
|
||||
});
|
||||
},
|
||||
[DynamicComponentLoader, Injector, Testability, TestabilityRegistry]),
|
||||
|
||||
bind(appComponentType).toFactory((ref) => ref.instance, [appComponentRefToken]),
|
||||
bind(appComponentType)
|
||||
.toFactory((p: Promise<any>) => p.then(ref => ref.instance), [appComponentRefToken]),
|
||||
bind(LifeCycle)
|
||||
.toFactory((exceptionHandler) => new LifeCycle(exceptionHandler, null, assertionsEnabled()),
|
||||
[ExceptionHandler]),
|
||||
@ -293,20 +292,19 @@ export function bootstrap(appComponentType: Type,
|
||||
// index.html and main.js are possible.
|
||||
|
||||
var appInjector = _createAppInjector(appComponentType, componentInjectableBindings, zone);
|
||||
var compRefToken: Promise<any> =
|
||||
PromiseWrapper.wrap(() => appInjector.get(appComponentRefToken));
|
||||
var tick = (componentRef) => {
|
||||
var appChangeDetector = internalView(componentRef.hostView).changeDetector;
|
||||
// retrieve life cycle: may have already been created if injected in root component
|
||||
var lc = appInjector.get(LifeCycle);
|
||||
lc.registerWith(zone, appChangeDetector);
|
||||
lc.tick(); // the first tick that will bootstrap the app
|
||||
|
||||
PromiseWrapper.then(
|
||||
appInjector.asyncGet(appComponentRefToken),
|
||||
(componentRef) => {
|
||||
var appChangeDetector = internalView(componentRef.hostView).changeDetector;
|
||||
// retrieve life cycle: may have already been created if injected in root component
|
||||
var lc = appInjector.get(LifeCycle);
|
||||
lc.registerWith(zone, appChangeDetector);
|
||||
lc.tick(); // the first tick that will bootstrap the app
|
||||
|
||||
bootstrapProcess.resolve(new ApplicationRef(componentRef, appComponentType, appInjector));
|
||||
},
|
||||
|
||||
(err, stackTrace) => {bootstrapProcess.reject(err, stackTrace)});
|
||||
bootstrapProcess.resolve(new ApplicationRef(componentRef, appComponentType, appInjector));
|
||||
};
|
||||
PromiseWrapper.then(compRefToken, tick,
|
||||
(err, stackTrace) => {bootstrapProcess.reject(err, stackTrace)});
|
||||
});
|
||||
|
||||
return bootstrapProcess.promise;
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user