Skip to content

Commit 7736964

Browse files
committed
feat(di): add support for multi bindings
BREAKING CHANGE Previously a content binding of a component was visible to the directives in its view with the host constraint. This is not the case any more. To access that binding, remove the constraint.
1 parent 2fea0c2 commit 7736964

File tree

9 files changed

+389
-176
lines changed

9 files changed

+389
-176
lines changed

modules/angular2/src/core/compiler/element_injector.ts

Lines changed: 72 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
InjectorDynamicStrategy,
3131
BindingWithVisibility
3232
} from 'angular2/src/core/di/injector';
33+
import {resolveBinding, ResolvedFactory} from 'angular2/src/core/di/binding';
3334

3435
import {AttributeMetadata, QueryMetadata} from '../metadata/di';
3536

@@ -195,70 +196,63 @@ export class DirectiveDependency extends Dependency {
195196
}
196197

197198
export class DirectiveBinding extends ResolvedBinding {
198-
constructor(key: Key, factory: Function, dependencies: Dependency[],
199-
public resolvedBindings: ResolvedBinding[],
200-
public resolvedViewBindings: ResolvedBinding[],
201-
public metadata: RenderDirectiveMetadata) {
202-
super(key, factory, dependencies);
199+
constructor(key: Key, factory: Function, deps: Dependency[],
200+
public metadata: RenderDirectiveMetadata,
201+
public bindings: Array<Type | Binding | any[]>,
202+
public viewBindings: Array<Type | Binding | any[]>) {
203+
super(key, [new ResolvedFactory(factory, deps)], false);
203204
}
204205

205-
get callOnDestroy(): boolean { return this.metadata.callOnDestroy; }
206-
207-
get callOnChanges(): boolean { return this.metadata.callOnChanges; }
208-
209-
get callAfterContentChecked(): boolean { return this.metadata.callAfterContentChecked; }
210-
211206
get displayName(): string { return this.key.displayName; }
212207

208+
get callOnDestroy(): boolean { return this.metadata.callOnDestroy; }
209+
213210
get eventEmitters(): string[] {
214211
return isPresent(this.metadata) && isPresent(this.metadata.events) ? this.metadata.events : [];
215212
}
216213

217-
get changeDetection() { return this.metadata.changeDetection; }
218-
219214
static createFromBinding(binding: Binding, meta: DirectiveMetadata): DirectiveBinding {
220215
if (isBlank(meta)) {
221216
meta = new DirectiveMetadata();
222217
}
223218

224-
var rb = binding.resolve();
225-
var deps = ListWrapper.map(rb.dependencies, DirectiveDependency.createFrom);
226-
var resolvedBindings = isPresent(meta.bindings) ? Injector.resolve(meta.bindings) : [];
227-
var resolvedViewBindings = meta instanceof ComponentMetadata && isPresent(meta.viewBindings) ?
228-
Injector.resolve(meta.viewBindings) :
229-
[];
219+
var rb = resolveBinding(binding);
220+
var rf = rb.resolvedFactories[0];
221+
var deps = rf.dependencies.map(DirectiveDependency.createFrom);
222+
var token = binding.token;
230223
var metadata = RenderDirectiveMetadata.create({
231-
id: stringify(rb.key.token),
224+
id: stringify(binding.token),
232225
type: meta instanceof ComponentMetadata ? RenderDirectiveMetadata.COMPONENT_TYPE :
233226
RenderDirectiveMetadata.DIRECTIVE_TYPE,
234227
selector: meta.selector,
235228
compileChildren: meta.compileChildren,
236229
events: meta.events,
237230
host: isPresent(meta.host) ? MapWrapper.createFromStringMap(meta.host) : null,
238231
properties: meta.properties,
239-
readAttributes: DirectiveBinding._readAttributes(deps),
240-
241-
callOnDestroy: hasLifecycleHook(LifecycleEvent.OnDestroy, rb.key.token, meta),
242-
callOnChanges: hasLifecycleHook(LifecycleEvent.OnChanges, rb.key.token, meta),
243-
callDoCheck: hasLifecycleHook(LifecycleEvent.DoCheck, rb.key.token, meta),
244-
callOnInit: hasLifecycleHook(LifecycleEvent.OnInit, rb.key.token, meta),
245-
callAfterContentInit: hasLifecycleHook(LifecycleEvent.AfterContentInit, rb.key.token, meta),
246-
callAfterContentChecked:
247-
hasLifecycleHook(LifecycleEvent.AfterContentChecked, rb.key.token, meta),
248-
callAfterViewInit: hasLifecycleHook(LifecycleEvent.AfterViewInit, rb.key.token, meta),
249-
callAfterViewChecked: hasLifecycleHook(LifecycleEvent.AfterViewChecked, rb.key.token, meta),
232+
readAttributes: DirectiveBinding._readAttributes(<any>deps),
233+
234+
callOnDestroy: hasLifecycleHook(LifecycleEvent.OnDestroy, token, meta),
235+
callOnChanges: hasLifecycleHook(LifecycleEvent.OnChanges, token, meta),
236+
callDoCheck: hasLifecycleHook(LifecycleEvent.DoCheck, token, meta),
237+
callOnInit: hasLifecycleHook(LifecycleEvent.OnInit, token, meta),
238+
callAfterContentInit: hasLifecycleHook(LifecycleEvent.AfterContentInit, token, meta),
239+
callAfterContentChecked: hasLifecycleHook(LifecycleEvent.AfterContentChecked, token, meta),
240+
callAfterViewInit: hasLifecycleHook(LifecycleEvent.AfterViewInit, token, meta),
241+
callAfterViewChecked: hasLifecycleHook(LifecycleEvent.AfterViewChecked, token, meta),
250242

251243
changeDetection: meta instanceof ComponentMetadata ? meta.changeDetection : null,
252244

253245
exportAs: meta.exportAs
254246
});
255-
return new DirectiveBinding(rb.key, rb.factory, deps, resolvedBindings, resolvedViewBindings,
256-
metadata);
247+
var bindings = isPresent(meta.bindings) ? meta.bindings : [];
248+
var viewBindigs =
249+
meta instanceof ComponentMetadata && isPresent(meta.viewBindings) ? meta.viewBindings : [];
250+
return new DirectiveBinding(rb.key, rf.factory, deps, metadata, bindings, viewBindigs);
257251
}
258252

259-
static _readAttributes(deps) {
253+
static _readAttributes(deps: DirectiveDependency[]): string[] {
260254
var readAttributes = [];
261-
ListWrapper.forEach(deps, (dep) => {
255+
deps.forEach(dep => {
262256
if (isPresent(dep.attributeName)) {
263257
readAttributes.push(dep.attributeName);
264258
}
@@ -316,7 +310,7 @@ export class ProtoElementInjector {
316310
eventEmitterAccessors: EventEmitterAccessor[][];
317311
protoInjector: ProtoInjector;
318312

319-
static create(parent: ProtoElementInjector, index: number, bindings: ResolvedBinding[],
313+
static create(parent: ProtoElementInjector, index: number, bindings: DirectiveBinding[],
320314
firstBindingIsComponent: boolean, distanceToParent: number,
321315
directiveVariableBindings: Map<string, number>): ProtoElementInjector {
322316
var bd = [];
@@ -326,43 +320,46 @@ export class ProtoElementInjector {
326320
if (firstBindingIsComponent) {
327321
ProtoElementInjector._createViewBindingsWithVisibility(bindings, bd);
328322
}
329-
ProtoElementInjector._createBindingsWithVisibility(bindings, bd, firstBindingIsComponent);
323+
324+
ProtoElementInjector._createBindingsWithVisibility(bindings, bd);
330325
return new ProtoElementInjector(parent, index, bd, distanceToParent, firstBindingIsComponent,
331326
directiveVariableBindings);
332327
}
333328

334-
private static _createDirectiveBindingWithVisibility(dirBindings: ResolvedBinding[],
329+
private static _createDirectiveBindingWithVisibility(dirBindings: DirectiveBinding[],
335330
bd: BindingWithVisibility[],
336331
firstBindingIsComponent: boolean) {
337-
ListWrapper.forEach(dirBindings, dirBinding => {
332+
dirBindings.forEach(dirBinding => {
338333
bd.push(ProtoElementInjector._createBindingWithVisibility(firstBindingIsComponent, dirBinding,
339334
dirBindings, dirBinding));
340335
});
341336
}
342337

343-
private static _createBindingsWithVisibility(dirBindings: ResolvedBinding[],
344-
bd: BindingWithVisibility[],
345-
firstBindingIsComponent: boolean) {
346-
ListWrapper.forEach(dirBindings, dirBinding => {
347-
ListWrapper.forEach(dirBinding.resolvedBindings, b => {
348-
bd.push(ProtoElementInjector._createBindingWithVisibility(firstBindingIsComponent,
349-
dirBinding, dirBindings, b));
350-
});
338+
private static _createBindingsWithVisibility(dirBindings: DirectiveBinding[],
339+
bd: BindingWithVisibility[]) {
340+
var bindingsFromAllDirectives = [];
341+
dirBindings.forEach(dirBinding => {
342+
bindingsFromAllDirectives =
343+
ListWrapper.concat(bindingsFromAllDirectives, dirBinding.bindings);
351344
});
345+
346+
var resolved = Injector.resolve(bindingsFromAllDirectives);
347+
resolved.forEach(b => bd.push(new BindingWithVisibility(b, Visibility.Public)));
352348
}
353349

354-
private static _createBindingWithVisibility(firstBindingIsComponent, dirBinding, dirBindings,
355-
binding) {
350+
private static _createBindingWithVisibility(firstBindingIsComponent: boolean,
351+
dirBinding: DirectiveBinding,
352+
dirBindings: DirectiveBinding[],
353+
binding: ResolvedBinding) {
356354
var isComponent = firstBindingIsComponent && dirBindings[0] === dirBinding;
357355
return new BindingWithVisibility(binding,
358356
isComponent ? Visibility.PublicAndPrivate : Visibility.Public);
359357
}
360358

361-
private static _createViewBindingsWithVisibility(bindings: ResolvedBinding[],
359+
private static _createViewBindingsWithVisibility(dirBindings: DirectiveBinding[],
362360
bd: BindingWithVisibility[]) {
363-
var db = <DirectiveBinding>bindings[0];
364-
ListWrapper.forEach(db.resolvedViewBindings,
365-
b => bd.push(new BindingWithVisibility(b, Visibility.Private)));
361+
var resolvedViewBindings = Injector.resolve(dirBindings[0].viewBindings);
362+
resolvedViewBindings.forEach(b => bd.push(new BindingWithVisibility(b, Visibility.Private)));
366363
}
367364

368365

@@ -852,7 +849,6 @@ interface _ElementInjectorStrategy {
852849
isComponentKey(key: Key): boolean;
853850
buildQueries(): void;
854851
addDirectivesMatchingQuery(q: QueryMetadata, res: any[]): void;
855-
getComponentBinding(): DirectiveBinding;
856852
hydrate(): void;
857853
dehydrate(): void;
858854
}
@@ -953,34 +949,44 @@ class ElementInjectorInlineStrategy implements _ElementInjectorStrategy {
953949
var p = this.injectorStrategy.protoStrategy;
954950

955951
if (p.binding0 instanceof DirectiveBinding) {
956-
this._ei._buildQueriesForDeps(<DirectiveDependency[]>p.binding0.dependencies);
952+
this._ei._buildQueriesForDeps(
953+
<DirectiveDependency[]>p.binding0.resolvedFactories[0].dependencies);
957954
}
958955
if (p.binding1 instanceof DirectiveBinding) {
959-
this._ei._buildQueriesForDeps(<DirectiveDependency[]>p.binding1.dependencies);
956+
this._ei._buildQueriesForDeps(
957+
<DirectiveDependency[]>p.binding1.resolvedFactories[0].dependencies);
960958
}
961959
if (p.binding2 instanceof DirectiveBinding) {
962-
this._ei._buildQueriesForDeps(<DirectiveDependency[]>p.binding2.dependencies);
960+
this._ei._buildQueriesForDeps(
961+
<DirectiveDependency[]>p.binding2.resolvedFactories[0].dependencies);
963962
}
964963
if (p.binding3 instanceof DirectiveBinding) {
965-
this._ei._buildQueriesForDeps(<DirectiveDependency[]>p.binding3.dependencies);
964+
this._ei._buildQueriesForDeps(
965+
<DirectiveDependency[]>p.binding3.resolvedFactories[0].dependencies);
966966
}
967967
if (p.binding4 instanceof DirectiveBinding) {
968-
this._ei._buildQueriesForDeps(<DirectiveDependency[]>p.binding4.dependencies);
968+
this._ei._buildQueriesForDeps(
969+
<DirectiveDependency[]>p.binding4.resolvedFactories[0].dependencies);
969970
}
970971
if (p.binding5 instanceof DirectiveBinding) {
971-
this._ei._buildQueriesForDeps(<DirectiveDependency[]>p.binding5.dependencies);
972+
this._ei._buildQueriesForDeps(
973+
<DirectiveDependency[]>p.binding5.resolvedFactories[0].dependencies);
972974
}
973975
if (p.binding6 instanceof DirectiveBinding) {
974-
this._ei._buildQueriesForDeps(<DirectiveDependency[]>p.binding6.dependencies);
976+
this._ei._buildQueriesForDeps(
977+
<DirectiveDependency[]>p.binding6.resolvedFactories[0].dependencies);
975978
}
976979
if (p.binding7 instanceof DirectiveBinding) {
977-
this._ei._buildQueriesForDeps(<DirectiveDependency[]>p.binding7.dependencies);
980+
this._ei._buildQueriesForDeps(
981+
<DirectiveDependency[]>p.binding7.resolvedFactories[0].dependencies);
978982
}
979983
if (p.binding8 instanceof DirectiveBinding) {
980-
this._ei._buildQueriesForDeps(<DirectiveDependency[]>p.binding8.dependencies);
984+
this._ei._buildQueriesForDeps(
985+
<DirectiveDependency[]>p.binding8.resolvedFactories[0].dependencies);
981986
}
982987
if (p.binding9 instanceof DirectiveBinding) {
983-
this._ei._buildQueriesForDeps(<DirectiveDependency[]>p.binding9.dependencies);
988+
this._ei._buildQueriesForDeps(
989+
<DirectiveDependency[]>p.binding9.resolvedFactories[0].dependencies);
984990
}
985991
}
986992

@@ -1029,11 +1035,6 @@ class ElementInjectorInlineStrategy implements _ElementInjectorStrategy {
10291035
list.push(i.obj9);
10301036
}
10311037
}
1032-
1033-
getComponentBinding(): DirectiveBinding {
1034-
var p = this.injectorStrategy.protoStrategy;
1035-
return <DirectiveBinding>p.binding0;
1036-
}
10371038
}
10381039

10391040
/**
@@ -1086,7 +1087,8 @@ class ElementInjectorDynamicStrategy implements _ElementInjectorStrategy {
10861087

10871088
for (var i = 0; i < p.bindings.length; i++) {
10881089
if (p.bindings[i] instanceof DirectiveBinding) {
1089-
this._ei._buildQueriesForDeps(<DirectiveDependency[]>p.bindings[i].dependencies);
1090+
this._ei._buildQueriesForDeps(
1091+
<DirectiveDependency[]>p.bindings[i].resolvedFactory.dependencies);
10901092
}
10911093
}
10921094
}
@@ -1104,11 +1106,6 @@ class ElementInjectorDynamicStrategy implements _ElementInjectorStrategy {
11041106
}
11051107
}
11061108
}
1107-
1108-
getComponentBinding(): DirectiveBinding {
1109-
var p = this.injectorStrategy.protoStrategy;
1110-
return <DirectiveBinding>p.bindings[0];
1111-
}
11121109
}
11131110

11141111
export class QueryError extends BaseException {

0 commit comments

Comments
 (0)