parent
ce6b364dc5
commit
4efc4a5520
|
@ -242,10 +242,30 @@ function _createEventEmitterAccessors(bwv: BindingWithVisibility): EventEmitterA
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _createProtoQueryRefs(bindings: BindingWithVisibility[]): ProtoQueryRef[] {
|
||||||
|
var res = [];
|
||||||
|
ListWrapper.forEachWithIndex(bindings, (b, i) => {
|
||||||
|
if (b.binding instanceof DirectiveBinding) {
|
||||||
|
// field queries
|
||||||
|
var queries: QueryMetadataWithSetter[] = b.binding.queries;
|
||||||
|
queries.forEach(q => res.push(new ProtoQueryRef(i, q.setter, q.metadata)));
|
||||||
|
|
||||||
|
// queries passed into the constructor.
|
||||||
|
// TODO: remove this after constructor queries are no longer supported
|
||||||
|
var deps: DirectiveDependency[] = b.binding.resolvedFactories[0].dependencies;
|
||||||
|
deps.forEach(d => {
|
||||||
|
if (isPresent(d.queryDecorator)) res.push(new ProtoQueryRef(i, null, d.queryDecorator));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
export class ProtoElementInjector {
|
export class ProtoElementInjector {
|
||||||
view: viewModule.AppView;
|
view: viewModule.AppView;
|
||||||
attributes: Map<string, string>;
|
attributes: Map<string, string>;
|
||||||
eventEmitterAccessors: EventEmitterAccessor[][];
|
eventEmitterAccessors: EventEmitterAccessor[][];
|
||||||
|
protoQueryRefs: ProtoQueryRef[];
|
||||||
protoInjector: ProtoInjector;
|
protoInjector: ProtoInjector;
|
||||||
|
|
||||||
static create(parent: ProtoElementInjector, index: number, bindings: DirectiveBinding[],
|
static create(parent: ProtoElementInjector, index: number, bindings: DirectiveBinding[],
|
||||||
|
@ -312,6 +332,7 @@ export class ProtoElementInjector {
|
||||||
for (var i = 0; i < length; ++i) {
|
for (var i = 0; i < length; ++i) {
|
||||||
this.eventEmitterAccessors[i] = _createEventEmitterAccessors(bwv[i]);
|
this.eventEmitterAccessors[i] = _createEventEmitterAccessors(bwv[i]);
|
||||||
}
|
}
|
||||||
|
this.protoQueryRefs = _createProtoQueryRefs(bwv);
|
||||||
}
|
}
|
||||||
|
|
||||||
instantiate(parent: ElementInjector): ElementInjector {
|
instantiate(parent: ElementInjector): ElementInjector {
|
||||||
|
@ -332,11 +353,7 @@ class _Context {
|
||||||
export class ElementInjector extends TreeNode<ElementInjector> implements DependencyProvider {
|
export class ElementInjector extends TreeNode<ElementInjector> implements DependencyProvider {
|
||||||
private _host: ElementInjector;
|
private _host: ElementInjector;
|
||||||
private _preBuiltObjects: PreBuiltObjects = null;
|
private _preBuiltObjects: PreBuiltObjects = null;
|
||||||
|
private _queryStrategy: _QueryStrategy;
|
||||||
// QueryRefs are added during construction. They are never removed.
|
|
||||||
private _query0: QueryRef;
|
|
||||||
private _query1: QueryRef;
|
|
||||||
private _query2: QueryRef;
|
|
||||||
|
|
||||||
hydrated: boolean;
|
hydrated: boolean;
|
||||||
|
|
||||||
|
@ -357,7 +374,7 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
|
||||||
|
|
||||||
this.hydrated = false;
|
this.hydrated = false;
|
||||||
|
|
||||||
this._buildQueries();
|
this._queryStrategy = this._buildQueryStrategy();
|
||||||
}
|
}
|
||||||
|
|
||||||
dehydrate(): void {
|
dehydrate(): void {
|
||||||
|
@ -366,7 +383,7 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
|
||||||
this._preBuiltObjects = null;
|
this._preBuiltObjects = null;
|
||||||
this._strategy.callOnDestroy();
|
this._strategy.callOnDestroy();
|
||||||
this._strategy.dehydrate();
|
this._strategy.dehydrate();
|
||||||
this._clearQueryLists();
|
this._queryStrategy.clearQueryLists();
|
||||||
}
|
}
|
||||||
|
|
||||||
hydrate(imperativelyCreatedInjector: Injector, host: ElementInjector,
|
hydrate(imperativelyCreatedInjector: Injector, host: ElementInjector,
|
||||||
|
@ -380,36 +397,6 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
|
||||||
this.hydrated = true;
|
this.hydrated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLocalQueries() {
|
|
||||||
if (isPresent(this._query0) && !this._query0.isViewQuery) {
|
|
||||||
this._query0.update();
|
|
||||||
this._query0.list.fireCallbacks();
|
|
||||||
}
|
|
||||||
if (isPresent(this._query1) && !this._query1.isViewQuery) {
|
|
||||||
this._query1.update();
|
|
||||||
this._query1.list.fireCallbacks();
|
|
||||||
}
|
|
||||||
if (isPresent(this._query2) && !this._query2.isViewQuery) {
|
|
||||||
this._query2.update();
|
|
||||||
this._query2.list.fireCallbacks();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateLocalViewQueries() {
|
|
||||||
if (isPresent(this._query0) && this._query0.isViewQuery) {
|
|
||||||
this._query0.update();
|
|
||||||
this._query0.list.fireCallbacks();
|
|
||||||
}
|
|
||||||
if (isPresent(this._query1) && this._query1.isViewQuery) {
|
|
||||||
this._query1.update();
|
|
||||||
this._query1.list.fireCallbacks();
|
|
||||||
}
|
|
||||||
if (isPresent(this._query2) && this._query2.isViewQuery) {
|
|
||||||
this._query2.update();
|
|
||||||
this._query2.list.fireCallbacks();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _debugContext(): any {
|
private _debugContext(): any {
|
||||||
var p = this._preBuiltObjects;
|
var p = this._preBuiltObjects;
|
||||||
var index = p.elementRef.boundElementIndex - p.view.elementOffset;
|
var index = p.elementRef.boundElementIndex - p.view.elementOffset;
|
||||||
|
@ -504,7 +491,8 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
|
||||||
|
|
||||||
if (isPresent(dirDep.attributeName)) return this._buildAttribute(dirDep);
|
if (isPresent(dirDep.attributeName)) return this._buildAttribute(dirDep);
|
||||||
|
|
||||||
if (isPresent(dirDep.queryDecorator)) return this._findQuery(dirDep.queryDecorator).list;
|
if (isPresent(dirDep.queryDecorator))
|
||||||
|
return this._queryStrategy.findQuery(dirDep.queryDecorator).list;
|
||||||
|
|
||||||
if (dirDep.key.id === StaticKeys.instance().changeDetectorRefId) {
|
if (dirDep.key.id === StaticKeys.instance().changeDetectorRefId) {
|
||||||
// We provide the component's view change detector to components and
|
// We provide the component's view change detector to components and
|
||||||
|
@ -557,34 +545,6 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_buildQueriesForDeps(deps: DirectiveDependency[]): void {
|
|
||||||
for (var i = 0; i < deps.length; i++) {
|
|
||||||
var dep = deps[i];
|
|
||||||
if (isPresent(dep.queryDecorator)) {
|
|
||||||
this._createQueryRef(null, null, dep.queryDecorator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_buildQueriesForDirective(dirIndex: number, meta: QueryMetadataWithSetter[]): void {
|
|
||||||
for (var i = 0; i < meta.length; i++) {
|
|
||||||
var m = meta[i];
|
|
||||||
this._createQueryRef(dirIndex, m.setter, m.metadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _createQueryRef(dirIndex: number, setter: SetterFn, query: QueryMetadata): void {
|
|
||||||
var queryList = new QueryList<any>();
|
|
||||||
if (isBlank(this._query0)) {
|
|
||||||
this._query0 = new QueryRef(dirIndex, setter, query, queryList, this);
|
|
||||||
} else if (isBlank(this._query1)) {
|
|
||||||
this._query1 = new QueryRef(dirIndex, setter, query, queryList, this);
|
|
||||||
} else if (isBlank(this._query2)) {
|
|
||||||
this._query2 = new QueryRef(dirIndex, setter, query, queryList, this);
|
|
||||||
} else {
|
|
||||||
throw new QueryError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addDirectivesMatchingQuery(query: QueryMetadata, list: any[]): void {
|
addDirectivesMatchingQuery(query: QueryMetadata, list: any[]): void {
|
||||||
var templateRef = isBlank(this._preBuiltObjects) ? null : this._preBuiltObjects.templateRef;
|
var templateRef = isBlank(this._preBuiltObjects) ? null : this._preBuiltObjects.templateRef;
|
||||||
if (query.selector === TemplateRef && isPresent(templateRef)) {
|
if (query.selector === TemplateRef && isPresent(templateRef)) {
|
||||||
|
@ -593,25 +553,17 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
|
||||||
this._strategy.addDirectivesMatchingQuery(query, list);
|
this._strategy.addDirectivesMatchingQuery(query, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _buildQueries(): void {
|
private _buildQueryStrategy(): _QueryStrategy {
|
||||||
if (isPresent(this._proto)) {
|
if (this._proto.protoQueryRefs.length === 0) {
|
||||||
this._strategy.buildQueries();
|
return _emptyQueryStrategy;
|
||||||
|
} else if (this._proto.protoQueryRefs.length <=
|
||||||
|
InlineQueryStrategy.NUMBER_OF_SUPPORTED_QUERIES) {
|
||||||
|
return new InlineQueryStrategy(this);
|
||||||
|
} else {
|
||||||
|
return new DynamicQueryStrategy(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _findQuery(query): QueryRef {
|
|
||||||
if (isPresent(this._query0) && this._query0.query === query) {
|
|
||||||
return this._query0;
|
|
||||||
}
|
|
||||||
if (isPresent(this._query1) && this._query1.query === query) {
|
|
||||||
return this._query1;
|
|
||||||
}
|
|
||||||
if (isPresent(this._query2) && this._query2.query === query) {
|
|
||||||
return this._query2;
|
|
||||||
}
|
|
||||||
throw new BaseException(`Cannot find query for directive ${query}.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
link(parent: ElementInjector): void { parent.addChild(this); }
|
link(parent: ElementInjector): void { parent.addChild(this); }
|
||||||
|
|
||||||
unlink(): void { this.remove(); }
|
unlink(): void { this.remove(); }
|
||||||
|
@ -631,15 +583,9 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
|
||||||
return isPresent(nestedView) ? nestedView.rootElementInjectors : [];
|
return isPresent(nestedView) ? nestedView.rootElementInjectors : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
private _clearQueryLists(): void {
|
afterViewChecked(): void { this._queryStrategy.updateViewQueries(); }
|
||||||
if (isPresent(this._query0)) this._query0.reset();
|
|
||||||
if (isPresent(this._query1)) this._query1.reset();
|
|
||||||
if (isPresent(this._query2)) this._query2.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
afterViewChecked(): void { this.updateLocalViewQueries(); }
|
afterContentChecked(): void { this._queryStrategy.updateContentQueries(); }
|
||||||
|
|
||||||
afterContentChecked(): void { this.updateLocalQueries(); }
|
|
||||||
|
|
||||||
traverseAndSetQueriesAsDirty(): void {
|
traverseAndSetQueriesAsDirty(): void {
|
||||||
var inj = this;
|
var inj = this;
|
||||||
|
@ -650,16 +596,165 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setQueriesAsDirty(): void {
|
private _setQueriesAsDirty(): void {
|
||||||
if (isPresent(this._query0) && !this._query0.isViewQuery) this._query0.dirty = true;
|
this._queryStrategy.setContentQueriesAsDirty();
|
||||||
if (isPresent(this._query1) && !this._query1.isViewQuery) this._query1.dirty = true;
|
if (isPresent(this._host)) this._host._queryStrategy.setViewQueriesAsDirty();
|
||||||
if (isPresent(this._query2) && !this._query2.isViewQuery) this._query2.dirty = true;
|
}
|
||||||
if (isPresent(this._host)) this._host._setViewQueriesAsDirty();
|
}
|
||||||
|
|
||||||
|
interface _QueryStrategy {
|
||||||
|
setContentQueriesAsDirty(): void;
|
||||||
|
setViewQueriesAsDirty(): void;
|
||||||
|
clearQueryLists(): void;
|
||||||
|
updateContentQueries(): void;
|
||||||
|
updateViewQueries(): void;
|
||||||
|
findQuery(query: QueryMetadata): QueryRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EmptyQueryStrategy implements _QueryStrategy {
|
||||||
|
setContentQueriesAsDirty(): void {}
|
||||||
|
setViewQueriesAsDirty(): void {}
|
||||||
|
clearQueryLists(): void {}
|
||||||
|
updateContentQueries(): void {}
|
||||||
|
updateViewQueries(): void {}
|
||||||
|
findQuery(query: QueryMetadata): QueryRef {
|
||||||
|
throw new BaseException(`Cannot find query for directive ${query}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _emptyQueryStrategy = new _EmptyQueryStrategy();
|
||||||
|
|
||||||
|
class InlineQueryStrategy implements _QueryStrategy {
|
||||||
|
static NUMBER_OF_SUPPORTED_QUERIES = 3;
|
||||||
|
|
||||||
|
query0: QueryRef;
|
||||||
|
query1: QueryRef;
|
||||||
|
query2: QueryRef;
|
||||||
|
|
||||||
|
constructor(ei: ElementInjector) {
|
||||||
|
var protoRefs = ei._proto.protoQueryRefs;
|
||||||
|
if (protoRefs.length > 0) this.query0 = new QueryRef(protoRefs[0], new QueryList<any>(), ei);
|
||||||
|
if (protoRefs.length > 1) this.query1 = new QueryRef(protoRefs[1], new QueryList<any>(), ei);
|
||||||
|
if (protoRefs.length > 2) this.query2 = new QueryRef(protoRefs[2], new QueryList<any>(), ei);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setViewQueriesAsDirty(): void {
|
setContentQueriesAsDirty(): void {
|
||||||
if (isPresent(this._query0) && this._query0.isViewQuery) this._query0.dirty = true;
|
if (isPresent(this.query0) && !this.query0.isViewQuery) this.query0.dirty = true;
|
||||||
if (isPresent(this._query1) && this._query1.isViewQuery) this._query1.dirty = true;
|
if (isPresent(this.query1) && !this.query1.isViewQuery) this.query1.dirty = true;
|
||||||
if (isPresent(this._query2) && this._query2.isViewQuery) this._query2.dirty = true;
|
if (isPresent(this.query2) && !this.query2.isViewQuery) this.query2.dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
setViewQueriesAsDirty(): void {
|
||||||
|
if (isPresent(this.query0) && this.query0.isViewQuery) this.query0.dirty = true;
|
||||||
|
if (isPresent(this.query1) && this.query1.isViewQuery) this.query1.dirty = true;
|
||||||
|
if (isPresent(this.query2) && this.query2.isViewQuery) this.query2.dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearQueryLists(): void {
|
||||||
|
if (isPresent(this.query0)) this.query0.reset();
|
||||||
|
if (isPresent(this.query1)) this.query1.reset();
|
||||||
|
if (isPresent(this.query2)) this.query2.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateContentQueries() {
|
||||||
|
if (isPresent(this.query0) && !this.query0.isViewQuery) {
|
||||||
|
this.query0.update();
|
||||||
|
this.query0.list.fireCallbacks();
|
||||||
|
}
|
||||||
|
if (isPresent(this.query1) && !this.query1.isViewQuery) {
|
||||||
|
this.query1.update();
|
||||||
|
this.query1.list.fireCallbacks();
|
||||||
|
}
|
||||||
|
if (isPresent(this.query2) && !this.query2.isViewQuery) {
|
||||||
|
this.query2.update();
|
||||||
|
this.query2.list.fireCallbacks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateViewQueries() {
|
||||||
|
if (isPresent(this.query0) && this.query0.isViewQuery) {
|
||||||
|
this.query0.update();
|
||||||
|
this.query0.list.fireCallbacks();
|
||||||
|
}
|
||||||
|
if (isPresent(this.query1) && this.query1.isViewQuery) {
|
||||||
|
this.query1.update();
|
||||||
|
this.query1.list.fireCallbacks();
|
||||||
|
}
|
||||||
|
if (isPresent(this.query2) && this.query2.isViewQuery) {
|
||||||
|
this.query2.update();
|
||||||
|
this.query2.list.fireCallbacks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
findQuery(query: QueryMetadata): QueryRef {
|
||||||
|
if (isPresent(this.query0) && this.query0.protoQueryRef.query === query) {
|
||||||
|
return this.query0;
|
||||||
|
}
|
||||||
|
if (isPresent(this.query1) && this.query1.protoQueryRef.query === query) {
|
||||||
|
return this.query1;
|
||||||
|
}
|
||||||
|
if (isPresent(this.query2) && this.query2.protoQueryRef.query === query) {
|
||||||
|
return this.query2;
|
||||||
|
}
|
||||||
|
throw new BaseException(`Cannot find query for directive ${query}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DynamicQueryStrategy implements _QueryStrategy {
|
||||||
|
queries: QueryRef[];
|
||||||
|
|
||||||
|
constructor(ei: ElementInjector) {
|
||||||
|
this.queries = ei._proto.protoQueryRefs.map(p => new QueryRef(p, new QueryList<any>(), ei));
|
||||||
|
}
|
||||||
|
|
||||||
|
setContentQueriesAsDirty(): void {
|
||||||
|
for (var i = 0; i < this.queries.length; ++i) {
|
||||||
|
var q = this.queries[i];
|
||||||
|
if (!q.isViewQuery) q.dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setViewQueriesAsDirty(): void {
|
||||||
|
for (var i = 0; i < this.queries.length; ++i) {
|
||||||
|
var q = this.queries[i];
|
||||||
|
if (q.isViewQuery) q.dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearQueryLists(): void {
|
||||||
|
for (var i = 0; i < this.queries.length; ++i) {
|
||||||
|
var q = this.queries[i];
|
||||||
|
q.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateContentQueries() {
|
||||||
|
for (var i = 0; i < this.queries.length; ++i) {
|
||||||
|
var q = this.queries[i];
|
||||||
|
if (!q.isViewQuery) {
|
||||||
|
q.update();
|
||||||
|
q.list.fireCallbacks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateViewQueries() {
|
||||||
|
for (var i = 0; i < this.queries.length; ++i) {
|
||||||
|
var q = this.queries[i];
|
||||||
|
if (q.isViewQuery) {
|
||||||
|
q.update();
|
||||||
|
q.list.fireCallbacks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
findQuery(query: QueryMetadata): QueryRef {
|
||||||
|
for (var i = 0; i < this.queries.length; ++i) {
|
||||||
|
var q = this.queries[i];
|
||||||
|
if (q.protoQueryRef.query === query) {
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new BaseException(`Cannot find query for directive ${query}.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,7 +762,6 @@ interface _ElementInjectorStrategy {
|
||||||
callOnDestroy(): void;
|
callOnDestroy(): void;
|
||||||
getComponent(): any;
|
getComponent(): any;
|
||||||
isComponentKey(key: Key): boolean;
|
isComponentKey(key: Key): boolean;
|
||||||
buildQueries(): void;
|
|
||||||
addDirectivesMatchingQuery(q: QueryMetadata, res: any[]): void;
|
addDirectivesMatchingQuery(q: QueryMetadata, res: any[]): void;
|
||||||
hydrate(): void;
|
hydrate(): void;
|
||||||
dehydrate(): void;
|
dehydrate(): void;
|
||||||
|
@ -765,63 +859,6 @@ class ElementInjectorInlineStrategy implements _ElementInjectorStrategy {
|
||||||
key.id === this.injectorStrategy.protoStrategy.keyId0;
|
key.id === this.injectorStrategy.protoStrategy.keyId0;
|
||||||
}
|
}
|
||||||
|
|
||||||
buildQueries(): void {
|
|
||||||
var p = this.injectorStrategy.protoStrategy;
|
|
||||||
|
|
||||||
if (p.binding0 instanceof DirectiveBinding) {
|
|
||||||
this._ei._buildQueriesForDeps(
|
|
||||||
<DirectiveDependency[]>p.binding0.resolvedFactories[0].dependencies);
|
|
||||||
|
|
||||||
this._ei._buildQueriesForDirective(0, (<DirectiveBinding>p.binding0).queries);
|
|
||||||
}
|
|
||||||
if (p.binding1 instanceof DirectiveBinding) {
|
|
||||||
this._ei._buildQueriesForDeps(
|
|
||||||
<DirectiveDependency[]>p.binding1.resolvedFactories[0].dependencies);
|
|
||||||
|
|
||||||
this._ei._buildQueriesForDirective(1, (<DirectiveBinding>p.binding1).queries);
|
|
||||||
}
|
|
||||||
if (p.binding2 instanceof DirectiveBinding) {
|
|
||||||
this._ei._buildQueriesForDeps(
|
|
||||||
<DirectiveDependency[]>p.binding2.resolvedFactories[0].dependencies);
|
|
||||||
this._ei._buildQueriesForDirective(2, (<DirectiveBinding>p.binding2).queries);
|
|
||||||
}
|
|
||||||
if (p.binding3 instanceof DirectiveBinding) {
|
|
||||||
this._ei._buildQueriesForDeps(
|
|
||||||
<DirectiveDependency[]>p.binding3.resolvedFactories[0].dependencies);
|
|
||||||
this._ei._buildQueriesForDirective(3, (<DirectiveBinding>p.binding3).queries);
|
|
||||||
}
|
|
||||||
if (p.binding4 instanceof DirectiveBinding) {
|
|
||||||
this._ei._buildQueriesForDeps(
|
|
||||||
<DirectiveDependency[]>p.binding4.resolvedFactories[0].dependencies);
|
|
||||||
this._ei._buildQueriesForDirective(4, (<DirectiveBinding>p.binding4).queries);
|
|
||||||
}
|
|
||||||
if (p.binding5 instanceof DirectiveBinding) {
|
|
||||||
this._ei._buildQueriesForDeps(
|
|
||||||
<DirectiveDependency[]>p.binding5.resolvedFactories[0].dependencies);
|
|
||||||
this._ei._buildQueriesForDirective(5, (<DirectiveBinding>p.binding5).queries);
|
|
||||||
}
|
|
||||||
if (p.binding6 instanceof DirectiveBinding) {
|
|
||||||
this._ei._buildQueriesForDeps(
|
|
||||||
<DirectiveDependency[]>p.binding6.resolvedFactories[0].dependencies);
|
|
||||||
this._ei._buildQueriesForDirective(6, (<DirectiveBinding>p.binding6).queries);
|
|
||||||
}
|
|
||||||
if (p.binding7 instanceof DirectiveBinding) {
|
|
||||||
this._ei._buildQueriesForDeps(
|
|
||||||
<DirectiveDependency[]>p.binding7.resolvedFactories[0].dependencies);
|
|
||||||
this._ei._buildQueriesForDirective(7, (<DirectiveBinding>p.binding7).queries);
|
|
||||||
}
|
|
||||||
if (p.binding8 instanceof DirectiveBinding) {
|
|
||||||
this._ei._buildQueriesForDeps(
|
|
||||||
<DirectiveDependency[]>p.binding8.resolvedFactories[0].dependencies);
|
|
||||||
this._ei._buildQueriesForDirective(8, (<DirectiveBinding>p.binding8).queries);
|
|
||||||
}
|
|
||||||
if (p.binding9 instanceof DirectiveBinding) {
|
|
||||||
this._ei._buildQueriesForDeps(
|
|
||||||
<DirectiveDependency[]>p.binding9.resolvedFactories[0].dependencies);
|
|
||||||
this._ei._buildQueriesForDirective(9, (<DirectiveBinding>p.binding9).queries);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addDirectivesMatchingQuery(query: QueryMetadata, list: any[]): void {
|
addDirectivesMatchingQuery(query: QueryMetadata, list: any[]): void {
|
||||||
var i = this.injectorStrategy;
|
var i = this.injectorStrategy;
|
||||||
var p = i.protoStrategy;
|
var p = i.protoStrategy;
|
||||||
|
@ -913,19 +950,6 @@ class ElementInjectorDynamicStrategy implements _ElementInjectorStrategy {
|
||||||
return this._ei._proto._firstBindingIsComponent && isPresent(key) && key.id === p.keyIds[0];
|
return this._ei._proto._firstBindingIsComponent && isPresent(key) && key.id === p.keyIds[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
buildQueries(): void {
|
|
||||||
var inj = this.injectorStrategy;
|
|
||||||
var p = inj.protoStrategy;
|
|
||||||
|
|
||||||
for (var i = 0; i < p.bindings.length; i++) {
|
|
||||||
if (p.bindings[i] instanceof DirectiveBinding) {
|
|
||||||
this._ei._buildQueriesForDeps(
|
|
||||||
<DirectiveDependency[]>p.bindings[i].resolvedFactory.dependencies);
|
|
||||||
this._ei._buildQueriesForDirective(i, (<DirectiveBinding>p.bindings[i]).queries);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addDirectivesMatchingQuery(query: QueryMetadata, list: any[]): void {
|
addDirectivesMatchingQuery(query: QueryMetadata, list: any[]): void {
|
||||||
var ist = this.injectorStrategy;
|
var ist = this.injectorStrategy;
|
||||||
var p = ist.protoStrategy;
|
var p = ist.protoStrategy;
|
||||||
|
@ -941,23 +965,17 @@ class ElementInjectorDynamicStrategy implements _ElementInjectorStrategy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class QueryError extends BaseException {
|
export class ProtoQueryRef {
|
||||||
message: string;
|
constructor(public dirIndex: number, public setter: SetterFn, public query: QueryMetadata) {}
|
||||||
// TODO(rado): pass the names of the active directives.
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.message = 'Only 3 queries can be concurrently active on an element.';
|
|
||||||
}
|
|
||||||
|
|
||||||
toString(): string { return this.message; }
|
get usesPropertySyntax(): boolean { return isPresent(this.setter); }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class QueryRef {
|
export class QueryRef {
|
||||||
constructor(public dirIndex: number, public setter: SetterFn, public query: QueryMetadata,
|
constructor(public protoQueryRef: ProtoQueryRef, public list: QueryList<any>,
|
||||||
public list: QueryList<any>, public originator: ElementInjector,
|
private originator: ElementInjector, public dirty: boolean = true) {}
|
||||||
public dirty: boolean = true) {}
|
|
||||||
|
|
||||||
get isViewQuery(): boolean { return this.query.isViewQuery; }
|
get isViewQuery(): boolean { return this.protoQueryRef.query.isViewQuery; }
|
||||||
|
|
||||||
update(): void {
|
update(): void {
|
||||||
if (!this.dirty) return;
|
if (!this.dirty) return;
|
||||||
|
@ -965,19 +983,19 @@ export class QueryRef {
|
||||||
this.dirty = false;
|
this.dirty = false;
|
||||||
|
|
||||||
// TODO delete the check once only field queries are supported
|
// TODO delete the check once only field queries are supported
|
||||||
if (isPresent(this.dirIndex)) {
|
if (this.protoQueryRef.usesPropertySyntax) {
|
||||||
var dir = this.originator.getDirectiveAtIndex(this.dirIndex);
|
var dir = this.originator.getDirectiveAtIndex(this.protoQueryRef.dirIndex);
|
||||||
if (this.query.first) {
|
if (this.protoQueryRef.query.first) {
|
||||||
this.setter(dir, this.list.length > 0 ? this.list.first : null);
|
this.protoQueryRef.setter(dir, this.list.length > 0 ? this.list.first : null);
|
||||||
} else {
|
} else {
|
||||||
this.setter(dir, this.list);
|
this.protoQueryRef.setter(dir, this.list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _update(): void {
|
private _update(): void {
|
||||||
var aggregator = [];
|
var aggregator = [];
|
||||||
if (this.query.isViewQuery) {
|
if (this.protoQueryRef.query.isViewQuery) {
|
||||||
var view = this.originator.getView();
|
var view = this.originator.getView();
|
||||||
// intentionally skipping originator for view queries.
|
// intentionally skipping originator for view queries.
|
||||||
var nestedView =
|
var nestedView =
|
||||||
|
@ -1002,7 +1020,7 @@ export class QueryRef {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.query.descendants &&
|
if (!this.protoQueryRef.query.descendants &&
|
||||||
!(curInj.parent == this.originator || curInj == this.originator))
|
!(curInj.parent == this.originator || curInj == this.originator))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1017,7 +1035,7 @@ export class QueryRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _visitInjector(inj: ElementInjector, aggregator: any[]) {
|
private _visitInjector(inj: ElementInjector, aggregator: any[]) {
|
||||||
if (this.query.isVarBindingQuery) {
|
if (this.protoQueryRef.query.isVarBindingQuery) {
|
||||||
this._aggregateVariableBindings(inj, aggregator);
|
this._aggregateVariableBindings(inj, aggregator);
|
||||||
} else {
|
} else {
|
||||||
this._aggregateDirective(inj, aggregator);
|
this._aggregateDirective(inj, aggregator);
|
||||||
|
@ -1043,7 +1061,7 @@ export class QueryRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _aggregateVariableBindings(inj: ElementInjector, aggregator: any[]): void {
|
private _aggregateVariableBindings(inj: ElementInjector, aggregator: any[]): void {
|
||||||
var vb = this.query.varBindings;
|
var vb = this.protoQueryRef.query.varBindings;
|
||||||
for (var i = 0; i < vb.length; ++i) {
|
for (var i = 0; i < vb.length; ++i) {
|
||||||
if (inj.hasVariableBinding(vb[i])) {
|
if (inj.hasVariableBinding(vb[i])) {
|
||||||
aggregator.push(inj.getVariableBinding(vb[i]));
|
aggregator.push(inj.getVariableBinding(vb[i]));
|
||||||
|
@ -1052,7 +1070,7 @@ export class QueryRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _aggregateDirective(inj: ElementInjector, aggregator: any[]): void {
|
private _aggregateDirective(inj: ElementInjector, aggregator: any[]): void {
|
||||||
inj.addDirectivesMatchingQuery(this.query, aggregator);
|
inj.addDirectivesMatchingQuery(this.protoQueryRef.query, aggregator);
|
||||||
}
|
}
|
||||||
|
|
||||||
reset(): void {
|
reset(): void {
|
||||||
|
|
|
@ -43,7 +43,6 @@ import {BrowserDomAdapter} from 'angular2/src/core/dom/browser_adapter';
|
||||||
export function main() {
|
export function main() {
|
||||||
BrowserDomAdapter.makeCurrent();
|
BrowserDomAdapter.makeCurrent();
|
||||||
describe('Query API', () => {
|
describe('Query API', () => {
|
||||||
|
|
||||||
describe("querying by directive type", () => {
|
describe("querying by directive type", () => {
|
||||||
it('should contain all direct child directives in the light dom (constructor)',
|
it('should contain all direct child directives in the light dom (constructor)',
|
||||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||||
|
@ -646,6 +645,25 @@ export function main() {
|
||||||
expect(q.query.map((d: TextDirective) => d.text)).toEqual(['1', newString, '4']);
|
expect(q.query.map((d: TextDirective) => d.text)).toEqual(['1', newString, '4']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should support more than three queries',
|
||||||
|
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||||
|
var template = '<needs-four-queries #q><div text="1"></div></needs-four-queries>';
|
||||||
|
|
||||||
|
tcb.overrideTemplate(MyComp, template)
|
||||||
|
.createAsync(MyComp)
|
||||||
|
.then((view) => {
|
||||||
|
view.detectChanges();
|
||||||
|
|
||||||
|
var q = view.debugElement.componentViewChildren[0].getLocal('q');
|
||||||
|
expect(q.query1).toBeDefined();
|
||||||
|
expect(q.query2).toBeDefined();
|
||||||
|
expect(q.query3).toBeDefined();
|
||||||
|
expect(q.query4).toBeDefined();
|
||||||
|
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
@ -743,6 +761,15 @@ class NeedsQuery {
|
||||||
constructor(@Query(TextDirective) query: QueryList<TextDirective>) { this.query = query; }
|
constructor(@Query(TextDirective) query: QueryList<TextDirective>) { this.query = query; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Component({selector: 'needs-four-queries'})
|
||||||
|
@View({template: ''})
|
||||||
|
class NeedsFourQueries {
|
||||||
|
@ContentChild(TextDirective) query1: TextDirective;
|
||||||
|
@ContentChild(TextDirective) query2: TextDirective;
|
||||||
|
@ContentChild(TextDirective) query3: TextDirective;
|
||||||
|
@ContentChild(TextDirective) query4: TextDirective;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({selector: 'needs-query-desc'})
|
@Component({selector: 'needs-query-desc'})
|
||||||
@View({directives: [NgFor], template: '<div *ng-for="var dir of query">{{dir.text}}|</div>'})
|
@View({directives: [NgFor], template: '<div *ng-for="var dir of query">{{dir.text}}|</div>'})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -900,7 +927,8 @@ class NeedsTpl {
|
||||||
TextDirective,
|
TextDirective,
|
||||||
InertDirective,
|
InertDirective,
|
||||||
NgIf,
|
NgIf,
|
||||||
NgFor
|
NgFor,
|
||||||
|
NeedsFourQueries
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|
Loading…
Reference in New Issue