feat(di): removed app injector
BREAKING CHANGE: THe appInjector property has been removed. Instead use viewInjector or hostInjector.
This commit is contained in:
@ -822,8 +822,7 @@ export interface DirectiveArgs {
|
||||
* When a component is instantiated, Angular
|
||||
* - creates a shadow DOM for the component.
|
||||
* - loads the selected template into the shadow DOM.
|
||||
* - creates a child {@link Injector} which is configured with the `appInjector` for the
|
||||
* {@link Component}.
|
||||
* - creates all the injectable objects configured with `hostInjector` and `viewInjector`.
|
||||
*
|
||||
* All template expressions and statements are then evaluated against the component instance.
|
||||
*
|
||||
@ -865,59 +864,6 @@ export class Component extends Directive {
|
||||
*/
|
||||
changeDetection: string;
|
||||
|
||||
/**
|
||||
* Defines the set of injectable objects that are visible to a Component and its children.
|
||||
*
|
||||
* The `appInjector` defined in the Component annotation allow you to configure a set of bindings
|
||||
* for the component's
|
||||
* injector.
|
||||
*
|
||||
* When a component is instantiated, Angular creates a new child Injector, which is configured
|
||||
* with the bindings in
|
||||
* the Component `appInjector` annotation. The injectable objects then become available for
|
||||
* injection to the component
|
||||
* itself and any of the directives in the component's template, i.e. they are not available to
|
||||
* the directives which
|
||||
* are children in the component's light DOM.
|
||||
*
|
||||
*
|
||||
* The syntax for configuring the `appInjector` injectable is identical to {@link Injector}
|
||||
* injectable configuration.
|
||||
* See {@link Injector} for additional detail.
|
||||
*
|
||||
*
|
||||
* ## Simple Example
|
||||
*
|
||||
* Here is an example of a class that can be injected:
|
||||
*
|
||||
* ```
|
||||
* class Greeter {
|
||||
* greet(name:string) {
|
||||
* return 'Hello ' + name + '!';
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @Component({
|
||||
* selector: 'greet',
|
||||
* appInjector: [
|
||||
* Greeter
|
||||
* ]
|
||||
* })
|
||||
* @View({
|
||||
* template: `{{greeter.greet('world')}}!`,
|
||||
* directives: [Child]
|
||||
* })
|
||||
* class HelloWorld {
|
||||
* greeter:Greeter;
|
||||
*
|
||||
* constructor(greeter:Greeter) {
|
||||
* this.greeter = greeter;
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
appInjector: List<any>;
|
||||
|
||||
/**
|
||||
* Defines the set of injectable objects that are visible to its view dom children.
|
||||
*
|
||||
@ -960,9 +906,8 @@ export class Component extends Directive {
|
||||
*/
|
||||
viewInjector: List<any>;
|
||||
|
||||
constructor({selector, properties, events, host, exportAs, appInjector, lifecycle, hostInjector,
|
||||
viewInjector, changeDetection = DEFAULT,
|
||||
compileChildren = true}: ComponentArgs = {}) {
|
||||
constructor({selector, properties, events, host, exportAs, lifecycle, hostInjector, viewInjector,
|
||||
changeDetection = DEFAULT, compileChildren = true}: ComponentArgs = {}) {
|
||||
super({
|
||||
selector: selector,
|
||||
properties: properties,
|
||||
@ -975,13 +920,11 @@ export class Component extends Directive {
|
||||
});
|
||||
|
||||
this.changeDetection = changeDetection;
|
||||
this.appInjector = appInjector;
|
||||
this.viewInjector = viewInjector;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ComponentArgs extends DirectiveArgs {
|
||||
appInjector?: List<any>;
|
||||
viewInjector?: List<any>;
|
||||
changeDetection?: string;
|
||||
}
|
||||
|
@ -209,11 +209,9 @@ function _createNgZone(givenReporter: Function): NgZone {
|
||||
* 1. It uses the component's `selector` property to locate the DOM element which needs to be
|
||||
* upgraded into
|
||||
* the angular component.
|
||||
* 2. It creates a new child injector (from the platform injector) and configures the injector with
|
||||
* the component's
|
||||
* `appInjector`. Optionally, you can also override the injector configuration for an app by
|
||||
* invoking
|
||||
* `bootstrap` with the `componentInjectableBindings` argument.
|
||||
* 2. It creates a new child injector (from the platform injector). Optionally, you can also
|
||||
* override the injector configuration for an app by
|
||||
* invoking `bootstrap` with the `componentInjectableBindings` argument.
|
||||
* 3. It creates a new `Zone` and connects it to the angular application's change detection domain
|
||||
* instance.
|
||||
* 4. It creates a shadow DOM on the selected component's host element and loads the template into
|
||||
@ -270,9 +268,9 @@ function _createNgZone(givenReporter: Function): NgZone {
|
||||
* - `appComponentType`: The root component which should act as the application. This is a reference
|
||||
* to a `Type`
|
||||
* which is annotated with `@Component(...)`.
|
||||
* - `componentInjectableBindings`: An additional set of bindings that can be added to `appInjector`
|
||||
* for the
|
||||
* {@link Component} to override default injection behavior.
|
||||
* - `componentInjectableBindings`: An additional set of bindings that can be added to the app
|
||||
* injector
|
||||
* to override default injection behavior.
|
||||
* - `errorReporter`: `function(exception:any, stackTrace:string)` a default error reporter for
|
||||
* unhandled exceptions.
|
||||
*
|
||||
|
@ -30,8 +30,8 @@ export class DynamicComponentLoader {
|
||||
* component's selector.
|
||||
* The loaded component receives injection normally as a hosted view.
|
||||
*/
|
||||
loadAsRoot(typeOrBinding: Type | Binding, overrideSelector: string = null,
|
||||
injector: Injector = null): Promise<ComponentRef> {
|
||||
loadAsRoot(typeOrBinding: Type | Binding, overrideSelector: string,
|
||||
injector: Injector): Promise<ComponentRef> {
|
||||
return this._compiler.compileInHost(typeOrBinding)
|
||||
.then(hostProtoViewRef => {
|
||||
var hostViewRef =
|
||||
@ -51,10 +51,10 @@ export class DynamicComponentLoader {
|
||||
* injection normally as a hosted view.
|
||||
*/
|
||||
loadIntoLocation(typeOrBinding: Type | Binding, hostLocation: ElementRef, anchorName: string,
|
||||
injector: Injector = null): Promise<ComponentRef> {
|
||||
bindings: ResolvedBinding[] = null): Promise<ComponentRef> {
|
||||
return this.loadNextToLocation(
|
||||
typeOrBinding, this._viewManager.getNamedElementInComponentView(hostLocation, anchorName),
|
||||
injector);
|
||||
bindings);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,12 +62,12 @@ export class DynamicComponentLoader {
|
||||
* injection normally as a hosted view.
|
||||
*/
|
||||
loadNextToLocation(typeOrBinding: Type | Binding, location: ElementRef,
|
||||
injector: Injector = null): Promise<ComponentRef> {
|
||||
bindings: ResolvedBinding[] = null): Promise<ComponentRef> {
|
||||
return this._compiler.compileInHost(typeOrBinding)
|
||||
.then(hostProtoViewRef => {
|
||||
var viewContainer = this._viewManager.getViewContainer(location);
|
||||
var hostViewRef =
|
||||
viewContainer.create(hostProtoViewRef, viewContainer.length, null, injector);
|
||||
viewContainer.create(hostProtoViewRef, viewContainer.length, null, bindings);
|
||||
var newLocation = this._viewManager.getHostElement(hostViewRef);
|
||||
var component = this._viewManager.getComponent(newLocation);
|
||||
|
||||
|
@ -16,8 +16,6 @@ import {
|
||||
PUBLIC,
|
||||
PRIVATE,
|
||||
undefinedValue,
|
||||
InjectorInlineStrategy,
|
||||
InjectorDynamicStrategy,
|
||||
Key,
|
||||
Dependency,
|
||||
bind,
|
||||
@ -32,6 +30,11 @@ import {
|
||||
VisibilityAnnotation,
|
||||
self
|
||||
} from 'angular2/di';
|
||||
import {
|
||||
InjectorInlineStrategy,
|
||||
InjectorDynamicStrategy,
|
||||
BindingWithVisibility
|
||||
} from 'angular2/src/di/injector';
|
||||
|
||||
import {Attribute, Query} from 'angular2/src/core/annotations_impl/di';
|
||||
|
||||
@ -201,7 +204,6 @@ export class DirectiveDependency extends Dependency {
|
||||
|
||||
export class DirectiveBinding extends ResolvedBinding {
|
||||
constructor(key: Key, factory: Function, dependencies: List<Dependency>,
|
||||
public resolvedAppInjectables: List<ResolvedBinding>,
|
||||
public resolvedHostInjectables: List<ResolvedBinding>,
|
||||
public resolvedViewInjectables: List<ResolvedBinding>,
|
||||
public metadata: DirectiveMetadata) {
|
||||
@ -235,9 +237,6 @@ export class DirectiveBinding extends ResolvedBinding {
|
||||
|
||||
var rb = binding.resolve();
|
||||
var deps = ListWrapper.map(rb.dependencies, DirectiveDependency.createFrom);
|
||||
var resolvedAppInjectables = ann instanceof Component && isPresent(ann.appInjector) ?
|
||||
Injector.resolve(ann.appInjector) :
|
||||
[];
|
||||
var resolvedHostInjectables =
|
||||
isPresent(ann.hostInjector) ? resolveBindings(ann.hostInjector) : [];
|
||||
var resolvedViewInjectables = ann instanceof Component && isPresent(ann.viewInjector) ?
|
||||
@ -265,8 +264,8 @@ export class DirectiveBinding extends ResolvedBinding {
|
||||
|
||||
exportAs: ann.exportAs
|
||||
});
|
||||
return new DirectiveBinding(rb.key, rb.factory, deps, resolvedAppInjectables,
|
||||
resolvedHostInjectables, resolvedViewInjectables, metadata);
|
||||
return new DirectiveBinding(rb.key, rb.factory, deps, resolvedHostInjectables,
|
||||
resolvedViewInjectables, metadata);
|
||||
}
|
||||
|
||||
static _readAttributes(deps) {
|
||||
@ -313,39 +312,35 @@ export class HostActionAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
export class BindingData {
|
||||
constructor(public binding: ResolvedBinding, public visibility: number) {}
|
||||
function _createEventEmitterAccessors(bwv: BindingWithVisibility): EventEmitterAccessor[] {
|
||||
var binding = bwv.binding;
|
||||
if (!(binding instanceof DirectiveBinding)) return [];
|
||||
var db = <DirectiveBinding>binding;
|
||||
return ListWrapper.map(db.eventEmitters, eventConfig => {
|
||||
let fieldName;
|
||||
let eventName;
|
||||
var colonIdx = eventConfig.indexOf(':');
|
||||
if (colonIdx > -1) {
|
||||
// long format: 'fieldName: eventName'
|
||||
fieldName = StringWrapper.substring(eventConfig, 0, colonIdx).trim();
|
||||
eventName = StringWrapper.substring(eventConfig, colonIdx + 1).trim();
|
||||
} else {
|
||||
// short format: 'name' when fieldName and eventName are the same
|
||||
fieldName = eventName = eventConfig;
|
||||
}
|
||||
return new EventEmitterAccessor(eventName, reflector.getter(fieldName));
|
||||
});
|
||||
}
|
||||
|
||||
getKeyId(): number { return this.binding.key.id; }
|
||||
|
||||
createEventEmitterAccessors(): List<EventEmitterAccessor> {
|
||||
if (!(this.binding instanceof DirectiveBinding)) return [];
|
||||
var db = <DirectiveBinding>this.binding;
|
||||
return ListWrapper.map(db.eventEmitters, eventConfig => {
|
||||
let fieldName;
|
||||
let eventName;
|
||||
var colonIdx = eventConfig.indexOf(':');
|
||||
if (colonIdx > -1) {
|
||||
// long format: 'fieldName: eventName'
|
||||
fieldName = StringWrapper.substring(eventConfig, 0, colonIdx).trim();
|
||||
eventName = StringWrapper.substring(eventConfig, colonIdx + 1).trim();
|
||||
} else {
|
||||
// short format: 'name' when fieldName and eventName are the same
|
||||
fieldName = eventName = eventConfig;
|
||||
}
|
||||
return new EventEmitterAccessor(eventName, reflector.getter(fieldName));
|
||||
});
|
||||
}
|
||||
|
||||
createHostActionAccessors(): HostActionAccessor[] {
|
||||
if (!(this.binding instanceof DirectiveBinding)) return [];
|
||||
var res = [];
|
||||
var db = <DirectiveBinding>this.binding;
|
||||
MapWrapper.forEach(db.hostActions, (actionExpression, actionName) => {
|
||||
res.push(new HostActionAccessor(actionExpression, reflector.getter(actionName)));
|
||||
});
|
||||
return res;
|
||||
}
|
||||
function _createHostActionAccessors(bwv: BindingWithVisibility): HostActionAccessor[] {
|
||||
var binding = bwv.binding;
|
||||
if (!(binding instanceof DirectiveBinding)) return [];
|
||||
var res = [];
|
||||
var db = <DirectiveBinding>binding;
|
||||
MapWrapper.forEach(db.hostActions, (actionExpression, actionName) => {
|
||||
res.push(new HostActionAccessor(actionExpression, reflector.getter(actionName)));
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
export class ProtoElementInjector {
|
||||
@ -360,62 +355,65 @@ export class ProtoElementInjector {
|
||||
directiveVariableBindings: Map<string, number>): ProtoElementInjector {
|
||||
var bd = [];
|
||||
|
||||
ProtoElementInjector._createDirectiveBindingData(bindings, bd, firstBindingIsComponent);
|
||||
ProtoElementInjector._createDirectiveBindingWithVisibility(bindings, bd,
|
||||
firstBindingIsComponent);
|
||||
if (firstBindingIsComponent) {
|
||||
ProtoElementInjector._createViewInjectorBindingData(bindings, bd);
|
||||
ProtoElementInjector._createViewInjectorBindingWithVisibility(bindings, bd);
|
||||
}
|
||||
ProtoElementInjector._createHostInjectorBindingData(bindings, bd, firstBindingIsComponent);
|
||||
ProtoElementInjector._createHostInjectorBindingWithVisibility(bindings, bd,
|
||||
firstBindingIsComponent);
|
||||
return new ProtoElementInjector(parent, index, bd, distanceToParent, firstBindingIsComponent,
|
||||
directiveVariableBindings);
|
||||
}
|
||||
|
||||
private static _createDirectiveBindingData(dirBindings: List<ResolvedBinding>,
|
||||
bd: List<BindingData>,
|
||||
firstBindingIsComponent: boolean) {
|
||||
private static _createDirectiveBindingWithVisibility(dirBindings: List<ResolvedBinding>,
|
||||
bd: BindingWithVisibility[],
|
||||
firstBindingIsComponent: boolean) {
|
||||
ListWrapper.forEach(dirBindings, dirBinding => {
|
||||
bd.push(ProtoElementInjector._createBindingData(firstBindingIsComponent, dirBinding,
|
||||
dirBindings, dirBinding));
|
||||
bd.push(ProtoElementInjector._createBindingWithVisibility(firstBindingIsComponent, dirBinding,
|
||||
dirBindings, dirBinding));
|
||||
});
|
||||
}
|
||||
|
||||
private static _createHostInjectorBindingData(dirBindings: List<ResolvedBinding>,
|
||||
bd: List<BindingData>,
|
||||
firstBindingIsComponent: boolean) {
|
||||
private static _createHostInjectorBindingWithVisibility(dirBindings: List<ResolvedBinding>,
|
||||
bd: BindingWithVisibility[],
|
||||
firstBindingIsComponent: boolean) {
|
||||
ListWrapper.forEach(dirBindings, dirBinding => {
|
||||
ListWrapper.forEach(dirBinding.resolvedHostInjectables, b => {
|
||||
bd.push(ProtoElementInjector._createBindingData(firstBindingIsComponent, dirBinding,
|
||||
dirBindings, b));
|
||||
bd.push(ProtoElementInjector._createBindingWithVisibility(firstBindingIsComponent,
|
||||
dirBinding, dirBindings, b));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static _createBindingData(firstBindingIsComponent, dirBinding, dirBindings, binding) {
|
||||
private static _createBindingWithVisibility(firstBindingIsComponent, dirBinding, dirBindings,
|
||||
binding) {
|
||||
var isComponent = firstBindingIsComponent && dirBindings[0] === dirBinding;
|
||||
return new BindingData(binding, isComponent ? PUBLIC_AND_PRIVATE : PUBLIC);
|
||||
return new BindingWithVisibility(binding, isComponent ? PUBLIC_AND_PRIVATE : PUBLIC);
|
||||
}
|
||||
|
||||
private static _createViewInjectorBindingData(bindings: List<ResolvedBinding>,
|
||||
bd: List<BindingData>) {
|
||||
private static _createViewInjectorBindingWithVisibility(bindings: List<ResolvedBinding>,
|
||||
bd: BindingWithVisibility[]) {
|
||||
var db = <DirectiveBinding>bindings[0];
|
||||
ListWrapper.forEach(db.resolvedViewInjectables, b => bd.push(new BindingData(b, PRIVATE)));
|
||||
ListWrapper.forEach(db.resolvedViewInjectables,
|
||||
b => bd.push(new BindingWithVisibility(b, PRIVATE)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
constructor(public parent: ProtoElementInjector, public index: int, bd: List<BindingData>,
|
||||
constructor(public parent: ProtoElementInjector, public index: int, bwv: BindingWithVisibility[],
|
||||
public distanceToParent: number, public _firstBindingIsComponent: boolean,
|
||||
public directiveVariableBindings: Map<string, number>) {
|
||||
var length = bd.length;
|
||||
var length = bwv.length;
|
||||
|
||||
this.protoInjector =
|
||||
new ProtoInjector(isPresent(parent) ? parent.protoInjector : null, bd, distanceToParent);
|
||||
this.protoInjector = new ProtoInjector(bwv, distanceToParent);
|
||||
|
||||
this.eventEmitterAccessors = ListWrapper.createFixedSize(length);
|
||||
this.hostActionAccessors = ListWrapper.createFixedSize(length);
|
||||
|
||||
for (var i = 0; i < length; ++i) {
|
||||
this.eventEmitterAccessors[i] = bd[i].createEventEmitterAccessors();
|
||||
this.hostActionAccessors[i] = bd[i].createHostActionAccessors();
|
||||
this.eventEmitterAccessors[i] = _createEventEmitterAccessors(bwv[i]);
|
||||
this.hostActionAccessors[i] = _createHostActionAccessors(bwv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -432,10 +430,7 @@ export class ProtoElementInjector {
|
||||
|
||||
|
||||
export class ElementInjector extends TreeNode<ElementInjector> {
|
||||
private _lightDomAppInjector: Injector = null;
|
||||
private _shadowDomAppInjector: Injector = null;
|
||||
private _host: ElementInjector;
|
||||
|
||||
private _preBuiltObjects = null;
|
||||
|
||||
// Queries are added during construction or linking with a new parent.
|
||||
@ -453,9 +448,10 @@ export class ElementInjector extends TreeNode<ElementInjector> {
|
||||
super(parent);
|
||||
|
||||
this._injector = new Injector(this._proto.protoInjector);
|
||||
this._injector.ei = this; // TODO savkin remove after mergin DI and EI
|
||||
|
||||
// we couple ourselves to the injector strategy to avoid polymoprhic calls
|
||||
var injectorStrategy = <any>this._injector.strategy;
|
||||
var injectorStrategy = <any>this._injector.internalStrategy;
|
||||
this._strategy = injectorStrategy instanceof InjectorInlineStrategy ?
|
||||
new ElementInjectorInlineStrategy(
|
||||
injectorStrategy, this) :
|
||||
@ -472,10 +468,8 @@ export class ElementInjector extends TreeNode<ElementInjector> {
|
||||
this.hydrated = false;
|
||||
this._host = null;
|
||||
this._preBuiltObjects = null;
|
||||
this._lightDomAppInjector = null;
|
||||
this._shadowDomAppInjector = null;
|
||||
this._strategy.callOnDestroy();
|
||||
this._injector.dehydrate();
|
||||
this._injector.internalStrategy.dehydrate();
|
||||
}
|
||||
|
||||
onAllChangesDone(): void {
|
||||
@ -490,24 +484,12 @@ export class ElementInjector extends TreeNode<ElementInjector> {
|
||||
}
|
||||
}
|
||||
|
||||
hydrate(injector: Injector, host: ElementInjector, preBuiltObjects: PreBuiltObjects): void {
|
||||
var p = this._proto;
|
||||
|
||||
hydrate(imperativelyCreatedInjector: Injector, host: ElementInjector,
|
||||
preBuiltObjects: PreBuiltObjects): void {
|
||||
this._host = host;
|
||||
this._lightDomAppInjector = injector;
|
||||
this._preBuiltObjects = preBuiltObjects;
|
||||
|
||||
if (p._firstBindingIsComponent) {
|
||||
this._shadowDomAppInjector =
|
||||
this._createShadowDomAppInjector(this._strategy.getComponentBinding(), injector);
|
||||
}
|
||||
|
||||
this._checkShadowDomAppInjector(this._shadowDomAppInjector);
|
||||
|
||||
var parentInjector = isPresent(this._parent) ? this._parent._injector : null;
|
||||
var hostInjector = isPresent(host) ? host._injector : null;
|
||||
|
||||
this._injector.hydrate(parentInjector, hostInjector, this);
|
||||
this._hydrateInjector(imperativelyCreatedInjector, host);
|
||||
|
||||
this._addDirectivesToQueries();
|
||||
this._addVarBindingsToQueries();
|
||||
@ -515,6 +497,59 @@ export class ElementInjector extends TreeNode<ElementInjector> {
|
||||
this.hydrated = true;
|
||||
}
|
||||
|
||||
private _hydrateInjector(imperativelyCreatedInjector: Injector, host: ElementInjector): void {
|
||||
if (isPresent(this._parent)) {
|
||||
this._reattachInjector(this._injector, this._parent._injector, false);
|
||||
} else {
|
||||
// This injector is at the boundary.
|
||||
//
|
||||
// The injector tree we are assembling:
|
||||
//
|
||||
// host._injector (only if present)
|
||||
// |
|
||||
// |boundary
|
||||
// |
|
||||
// imperativelyCreatedInjector (only if present)
|
||||
// |
|
||||
// |boundary
|
||||
// |
|
||||
// this._injector
|
||||
//
|
||||
|
||||
// host._injector (only if present)
|
||||
// |
|
||||
// |boundary
|
||||
// |
|
||||
// imperativelyCreatedInjector (only if present)
|
||||
if (isPresent(imperativelyCreatedInjector) && isPresent(host)) {
|
||||
this._reattachInjector(imperativelyCreatedInjector, host._injector, true);
|
||||
}
|
||||
|
||||
// host._injector OR imperativelyCreatedInjector OR null
|
||||
// |
|
||||
// |boundary
|
||||
// |
|
||||
// this._injector
|
||||
var parent = this._getParentInjector(imperativelyCreatedInjector, host);
|
||||
this._reattachInjector(this._injector, parent, true);
|
||||
}
|
||||
}
|
||||
|
||||
private _getParentInjector(injector: Injector, host: ElementInjector): Injector {
|
||||
if (isPresent(injector)) {
|
||||
return injector;
|
||||
} else if (isPresent(host)) {
|
||||
return host._injector;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private _reattachInjector(injector: Injector, parentInjector: Injector, isBoundary: boolean) {
|
||||
injector.internalStrategy.attach(parentInjector, isBoundary);
|
||||
injector.internalStrategy.hydrate();
|
||||
}
|
||||
|
||||
hasVariableBinding(name: string): boolean {
|
||||
var vb = this._proto.directiveVariableBindings;
|
||||
return isPresent(vb) && vb.has(name);
|
||||
@ -525,25 +560,6 @@ export class ElementInjector extends TreeNode<ElementInjector> {
|
||||
return isPresent(index) ? this.getDirectiveAtIndex(<number>index) : this.getElementRef();
|
||||
}
|
||||
|
||||
private _createShadowDomAppInjector(componentDirective: DirectiveBinding,
|
||||
appInjector: Injector): Injector {
|
||||
if (!ListWrapper.isEmpty(componentDirective.resolvedAppInjectables)) {
|
||||
return appInjector.createChildFromResolved(componentDirective.resolvedAppInjectables);
|
||||
} else {
|
||||
return appInjector;
|
||||
}
|
||||
}
|
||||
|
||||
private _checkShadowDomAppInjector(shadowDomAppInjector: Injector): void {
|
||||
if (this._proto._firstBindingIsComponent && isBlank(shadowDomAppInjector)) {
|
||||
throw new BaseException(
|
||||
'A shadowDomAppInjector is required as this ElementInjector contains a component');
|
||||
} else if (!this._proto._firstBindingIsComponent && isPresent(shadowDomAppInjector)) {
|
||||
throw new BaseException(
|
||||
'No shadowDomAppInjector allowed as there is not component stored in this ElementInjector');
|
||||
}
|
||||
}
|
||||
|
||||
get(token): any { return this._injector.get(token); }
|
||||
|
||||
hasDirective(type: Type): boolean { return isPresent(this._injector.getOptional(type)); }
|
||||
@ -573,7 +589,7 @@ export class ElementInjector extends TreeNode<ElementInjector> {
|
||||
isComponentKey(key: Key): boolean { return this._strategy.isComponentKey(key); }
|
||||
|
||||
getDependency(dep: any): any {
|
||||
var key = dep.key;
|
||||
var key: Key = dep.key;
|
||||
|
||||
if (!(dep instanceof DirectiveDependency)) return undefinedValue;
|
||||
|
||||
@ -802,22 +818,10 @@ export class ElementInjector extends TreeNode<ElementInjector> {
|
||||
if (this._query2 == query) this._query2 = null;
|
||||
}
|
||||
|
||||
appInjector(requestor: Key): Injector {
|
||||
if (isPresent(requestor) && this.isComponentKey(requestor)) {
|
||||
return this._shadowDomAppInjector;
|
||||
} else {
|
||||
return this._lightDomAppInjector;
|
||||
}
|
||||
}
|
||||
|
||||
getDirectiveAtIndex(index: number): any { return this._injector.getObjAtIndex(index); }
|
||||
getDirectiveAtIndex(index: number): any { return this._injector.getAt(index); }
|
||||
|
||||
hasInstances(): boolean { return this._proto.hasBindings && this.hydrated; }
|
||||
|
||||
getLightDomAppInjector(): Injector { return this._lightDomAppInjector; }
|
||||
|
||||
getShadowDomAppInjector(): Injector { return this._shadowDomAppInjector; }
|
||||
|
||||
getHost(): ElementInjector { return this._host; }
|
||||
|
||||
getBoundElementIndex(): number { return this._proto.index; }
|
||||
|
@ -348,7 +348,7 @@ function _findParentProtoElementInjectorWithDistance(
|
||||
}
|
||||
}
|
||||
} while (binderIndex !== -1);
|
||||
return new ParentProtoElementInjectorWithDistance(null, -1);
|
||||
return new ParentProtoElementInjectorWithDistance(null, 0);
|
||||
}
|
||||
|
||||
function _createProtoElementInjector(binderIndex, parentPeiWithDistance, renderElementBinder,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {ListWrapper, List} from 'angular2/src/facade/collection';
|
||||
import {Injector} from 'angular2/di';
|
||||
import {ResolvedBinding} from 'angular2/di';
|
||||
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||
|
||||
import * as avmModule from './view_manager';
|
||||
@ -31,10 +31,10 @@ export class ViewContainerRef {
|
||||
// TODO(rado): profile and decide whether bounds checks should be added
|
||||
// to the methods below.
|
||||
create(protoViewRef: ProtoViewRef = null, atIndex: number = -1, context: ElementRef = null,
|
||||
injector: Injector = null): ViewRef {
|
||||
bindings: ResolvedBinding[] = null): ViewRef {
|
||||
if (atIndex == -1) atIndex = this.length;
|
||||
return this.viewManager.createViewInContainer(this.element, atIndex, protoViewRef, context,
|
||||
injector);
|
||||
bindings);
|
||||
}
|
||||
|
||||
insert(viewRef: ViewRef, atIndex: number = -1): ViewRef {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Injector, Binding, Injectable} from 'angular2/di';
|
||||
import {Injector, Binding, Injectable, ResolvedBinding} from 'angular2/di';
|
||||
import {isPresent, isBlank, BaseException} from 'angular2/src/facade/lang';
|
||||
import * as viewModule from './view';
|
||||
import {ElementRef} from './element_ref';
|
||||
@ -73,6 +73,7 @@ export class AppViewManager {
|
||||
|
||||
this._utils.hydrateRootHostView(hostView, injector);
|
||||
this._viewHydrateRecurse(hostView);
|
||||
|
||||
return hostView.ref;
|
||||
}
|
||||
|
||||
@ -89,7 +90,7 @@ export class AppViewManager {
|
||||
|
||||
createViewInContainer(viewContainerLocation: ElementRef, atIndex: number,
|
||||
protoViewRef: ProtoViewRef, context: ElementRef = null,
|
||||
injector: Injector = null): ViewRef {
|
||||
bindings: ResolvedBinding[] = null): ViewRef {
|
||||
var protoView = internalProtoView(protoViewRef);
|
||||
var parentView = internalView(viewContainerLocation.parentView);
|
||||
var boundElementIndex = viewContainerLocation.boundElementIndex;
|
||||
@ -106,7 +107,7 @@ export class AppViewManager {
|
||||
this._utils.attachViewInContainer(parentView, boundElementIndex, contextView,
|
||||
contextBoundElementIndex, atIndex, view);
|
||||
this._utils.hydrateViewInContainer(parentView, boundElementIndex, contextView,
|
||||
contextBoundElementIndex, atIndex, injector);
|
||||
contextBoundElementIndex, atIndex, bindings);
|
||||
this._viewHydrateRecurse(view);
|
||||
return view.ref;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Injector, Binding, Injectable} from 'angular2/di';
|
||||
import {Injector, Binding, Injectable, ResolvedBinding} from 'angular2/di';
|
||||
import {ListWrapper, MapWrapper, Map, StringMapWrapper, List} from 'angular2/src/facade/collection';
|
||||
import * as eli from './element_injector';
|
||||
import {isPresent, isBlank, BaseException} from 'angular2/src/facade/lang';
|
||||
@ -74,15 +74,14 @@ export class AppViewManagerUtils {
|
||||
hostView.componentChildViews[boundElementIndex] = null;
|
||||
}
|
||||
|
||||
hydrateComponentView(hostView: viewModule.AppView, boundElementIndex: number,
|
||||
injector: Injector = null) {
|
||||
hydrateComponentView(hostView: viewModule.AppView, boundElementIndex: number) {
|
||||
var elementInjector = hostView.elementInjectors[boundElementIndex];
|
||||
var componentView = hostView.componentChildViews[boundElementIndex];
|
||||
var component = this.getComponentInstance(hostView, boundElementIndex);
|
||||
this._hydrateView(componentView, injector, elementInjector, component, null);
|
||||
this._hydrateView(componentView, null, elementInjector, component, null);
|
||||
}
|
||||
|
||||
hydrateRootHostView(hostView: viewModule.AppView, injector: Injector = null) {
|
||||
hydrateRootHostView(hostView: viewModule.AppView, injector: Injector) {
|
||||
this._hydrateView(hostView, injector, null, new Object(), null);
|
||||
}
|
||||
|
||||
@ -132,7 +131,7 @@ export class AppViewManagerUtils {
|
||||
|
||||
hydrateViewInContainer(parentView: viewModule.AppView, boundElementIndex: number,
|
||||
contextView: viewModule.AppView, contextBoundElementIndex: number,
|
||||
atIndex: number, injector: Injector) {
|
||||
atIndex: number, bindings: ResolvedBinding[]) {
|
||||
if (isBlank(contextView)) {
|
||||
contextView = parentView;
|
||||
contextBoundElementIndex = boundElementIndex;
|
||||
@ -140,21 +139,15 @@ export class AppViewManagerUtils {
|
||||
var viewContainer = parentView.viewContainers[boundElementIndex];
|
||||
var view = viewContainer.views[atIndex];
|
||||
var elementInjector = contextView.elementInjectors[contextBoundElementIndex];
|
||||
if (isBlank(elementInjector.getHost()) && isBlank(injector)) {
|
||||
injector = elementInjector.getShadowDomAppInjector();
|
||||
}
|
||||
|
||||
var injector = isPresent(bindings) ? Injector.fromResolvedBindings(bindings) : null;
|
||||
|
||||
this._hydrateView(view, injector, elementInjector.getHost(), contextView.context,
|
||||
contextView.locals);
|
||||
}
|
||||
|
||||
_hydrateView(view: viewModule.AppView, appInjector: Injector,
|
||||
_hydrateView(view: viewModule.AppView, injector: Injector,
|
||||
hostElementInjector: eli.ElementInjector, context: Object, parentLocals: Locals) {
|
||||
if (isBlank(appInjector)) {
|
||||
appInjector = hostElementInjector.getShadowDomAppInjector();
|
||||
}
|
||||
if (isBlank(appInjector)) {
|
||||
appInjector = hostElementInjector.getLightDomAppInjector();
|
||||
}
|
||||
view.context = context;
|
||||
view.locals.parent = parentLocals;
|
||||
|
||||
@ -163,7 +156,7 @@ export class AppViewManagerUtils {
|
||||
var elementInjector = view.elementInjectors[i];
|
||||
|
||||
if (isPresent(elementInjector)) {
|
||||
elementInjector.hydrate(appInjector, hostElementInjector, view.preBuiltObjects[i]);
|
||||
elementInjector.hydrate(injector, hostElementInjector, view.preBuiltObjects[i]);
|
||||
this._populateViewLocals(view, elementInjector);
|
||||
this._setUpEventEmitters(view, elementInjector, i);
|
||||
this._setUpHostActions(view, elementInjector, i);
|
||||
|
@ -15,7 +15,7 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||
* ```javascript
|
||||
* @Component({
|
||||
* selector: 'my-app',
|
||||
* appInjector: [
|
||||
* viewInjector: [
|
||||
* bind(ExceptionHandler).toClass(MyExceptionHandler)
|
||||
* ]
|
||||
* })
|
||||
|
Reference in New Issue
Block a user