parent
fd34a56347
commit
b4338b623c
|
@ -1,4 +1,4 @@
|
|||
import {Type, FIELD} from 'facade/lang';
|
||||
import {Type} from 'facade/lang';
|
||||
import {Directive} from '../annotations/annotations'
|
||||
import {List} from 'facade/collection'
|
||||
import {ShadowDomStrategy} from './shadow_dom';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {List, Map, ListWrapper, MapWrapper} from 'facade/collection';
|
||||
import {Element, DOM} from 'facade/dom';
|
||||
import {int, isBlank, isPresent} from 'facade/lang';
|
||||
import {int, isBlank, isPresent, Type} from 'facade/lang';
|
||||
import {DirectiveMetadata} from '../directive_metadata';
|
||||
import {Decorator} from '../../annotations/annotations';
|
||||
import {Component} from '../../annotations/annotations';
|
||||
|
@ -27,6 +27,7 @@ export class CompileElement {
|
|||
decoratorDirectives:List<DirectiveMetadata>;
|
||||
templateDirective:DirectiveMetadata;
|
||||
componentDirective:DirectiveMetadata;
|
||||
_allDirectives:List<DirectiveMetadata>;
|
||||
isViewRoot:boolean;
|
||||
hasBindings:boolean;
|
||||
inheritedProtoView:ProtoView;
|
||||
|
@ -45,6 +46,7 @@ export class CompileElement {
|
|||
this.decoratorDirectives = null;
|
||||
this.templateDirective = null;
|
||||
this.componentDirective = null;
|
||||
this._allDirectives = null;
|
||||
this.isViewRoot = false;
|
||||
this.hasBindings = false;
|
||||
// inherited down to children if they don't have
|
||||
|
@ -116,6 +118,7 @@ export class CompileElement {
|
|||
|
||||
addDirective(directive:DirectiveMetadata) {
|
||||
var annotation = directive.annotation;
|
||||
this._allDirectives = null;
|
||||
if (annotation instanceof Decorator) {
|
||||
if (isBlank(this.decoratorDirectives)) {
|
||||
this.decoratorDirectives = ListWrapper.create();
|
||||
|
@ -130,4 +133,23 @@ export class CompileElement {
|
|||
this.componentDirective = directive;
|
||||
}
|
||||
}
|
||||
|
||||
getAllDirectives(): List<DirectiveMetadata> {
|
||||
if (this._allDirectives === null) {
|
||||
// Collect all the directives
|
||||
// When present the component directive must be first
|
||||
var directives = ListWrapper.create();
|
||||
if (isPresent(this.componentDirective)) {
|
||||
ListWrapper.push(directives, this.componentDirective);
|
||||
}
|
||||
if (isPresent(this.templateDirective)) {
|
||||
ListWrapper.push(directives, this.templateDirective);
|
||||
}
|
||||
if (isPresent(this.decoratorDirectives)) {
|
||||
directives = ListWrapper.concat(directives, this.decoratorDirectives);
|
||||
}
|
||||
this._allDirectives = directives;
|
||||
}
|
||||
return this._allDirectives;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ export class ElementBinderBuilder extends CompileStep {
|
|||
if (isPresent(current.eventBindings)) {
|
||||
this._bindEvents(protoView, current);
|
||||
}
|
||||
this._bindDirectiveProperties(this._collectDirectives(current), current);
|
||||
this._bindDirectiveProperties(current.getAllDirectives(), current);
|
||||
} else if (isPresent(parent)) {
|
||||
elementBinder = parent.inheritedElementBinder;
|
||||
}
|
||||
|
@ -85,37 +85,21 @@ export class ElementBinderBuilder extends CompileStep {
|
|||
});
|
||||
}
|
||||
|
||||
_collectDirectives(compileElement) {
|
||||
var directives;
|
||||
if (isPresent(compileElement.decoratorDirectives)) {
|
||||
directives = ListWrapper.clone(compileElement.decoratorDirectives);
|
||||
} else {
|
||||
directives = [];
|
||||
}
|
||||
if (isPresent(compileElement.templateDirective)) {
|
||||
ListWrapper.push(directives, compileElement.templateDirective);
|
||||
}
|
||||
if (isPresent(compileElement.componentDirective)) {
|
||||
ListWrapper.push(directives, compileElement.componentDirective);
|
||||
}
|
||||
return directives;
|
||||
}
|
||||
|
||||
_bindDirectiveProperties(typesWithAnnotations, compileElement) {
|
||||
_bindDirectiveProperties(directives: List<DirectiveMetadata>,
|
||||
compileElement: CompileElement) {
|
||||
var protoView = compileElement.inheritedProtoView;
|
||||
var directiveIndex = 0;
|
||||
ListWrapper.forEach(typesWithAnnotations, (typeWithAnnotation) => {
|
||||
var annotation = typeWithAnnotation.annotation;
|
||||
if (isBlank(annotation.bind)) {
|
||||
return;
|
||||
}
|
||||
StringMapWrapper.forEach(annotation.bind, (dirProp, elProp) => {
|
||||
|
||||
for (var directiveIndex = 0; directiveIndex < directives.length; directiveIndex++) {
|
||||
var directive = ListWrapper.get(directives, directiveIndex);
|
||||
var annotation = directive.annotation;
|
||||
if (isBlank(annotation.bind)) continue;
|
||||
StringMapWrapper.forEach(annotation.bind, function (dirProp, elProp) {
|
||||
var expression = isPresent(compileElement.propertyBindings) ?
|
||||
MapWrapper.get(compileElement.propertyBindings, elProp) :
|
||||
null;
|
||||
if (isBlank(expression)) {
|
||||
throw new BaseException('No element binding found for property '+elProp
|
||||
+' which is required by directive '+stringify(typeWithAnnotation.type));
|
||||
+' which is required by directive '+stringify(directive.type));
|
||||
}
|
||||
var len = dirProp.length;
|
||||
var dirBindingName = dirProp;
|
||||
|
@ -129,7 +113,6 @@ export class ElementBinderBuilder extends CompileStep {
|
|||
isContentWatch
|
||||
);
|
||||
});
|
||||
directiveIndex++;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,8 +32,7 @@ export class ProtoElementInjectorBuilder extends CompileStep {
|
|||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
||||
var distanceToParentInjector = this._getDistanceToParentInjector(parent, current);
|
||||
var parentProtoElementInjector = this._getParentProtoElementInjector(parent, current);
|
||||
var injectorBindings = this._collectDirectiveBindings(current);
|
||||
|
||||
var injectorBindings = ListWrapper.map(current.getAllDirectives(), this._createBinding);
|
||||
// TODO: add lightDomServices as well,
|
||||
// but after the directives as we rely on that order
|
||||
// in the element_binder_builder.
|
||||
|
@ -65,22 +64,6 @@ export class ProtoElementInjectorBuilder extends CompileStep {
|
|||
return null;
|
||||
}
|
||||
|
||||
_collectDirectiveBindings(pipelineElement) {
|
||||
var directiveTypes = [];
|
||||
if (isPresent(pipelineElement.componentDirective)) {
|
||||
ListWrapper.push(directiveTypes, this._createBinding(pipelineElement.componentDirective));
|
||||
}
|
||||
if (isPresent(pipelineElement.templateDirective)) {
|
||||
ListWrapper.push(directiveTypes, this._createBinding(pipelineElement.templateDirective));
|
||||
}
|
||||
if (isPresent(pipelineElement.decoratorDirectives)) {
|
||||
for (var i=0; i<pipelineElement.decoratorDirectives.length; i++) {
|
||||
ListWrapper.push(directiveTypes, this._createBinding(pipelineElement.decoratorDirectives[i]));
|
||||
}
|
||||
}
|
||||
return directiveTypes;
|
||||
}
|
||||
|
||||
_createBinding(d:DirectiveMetadata): DirectiveBinding {
|
||||
return DirectiveBinding.createFromType(d.type, d.annotation);
|
||||
}
|
||||
|
|
|
@ -79,6 +79,22 @@ export function main() {
|
|||
});
|
||||
});
|
||||
|
||||
// GH issue 328 - https://github.com/angular/angular/issues/328
|
||||
it('should support different directive types on a single node', (done) => {
|
||||
compiler.compile(MyComp, el('<child-cmp my-dir [elprop]="ctxProp"></child-cmp>')).then((pv) => {
|
||||
createView(pv);
|
||||
|
||||
ctx.ctxProp = 'Hello World!';
|
||||
cd.detectChanges();
|
||||
|
||||
var elInj = view.elementInjectors[0];
|
||||
expect(elInj.get(MyDir).dirProp).toEqual('Hello World!');
|
||||
expect(elInj.get(ChildComp).dirProp).toEqual(null);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should support template directives via `<template>` elements.', (done) => {
|
||||
compiler.compile(MyComp, el('<div><template let-some-tmpl="greeting"><copy-me>{{greeting}}</copy-me></template></div>')).then((pv) => {
|
||||
createView(pv);
|
||||
|
@ -145,8 +161,10 @@ class MyComp {
|
|||
})
|
||||
class ChildComp {
|
||||
ctxProp:string;
|
||||
dirProp:string;
|
||||
constructor(service: MyService) {
|
||||
this.ctxProp = service.greeting;
|
||||
this.dirProp = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,14 @@ export function main() {
|
|||
expect(results[0].componentDirective).toEqual(reader.read(SomeComponent));
|
||||
});
|
||||
|
||||
it('component directives must be first in collected directives', () => {
|
||||
var results = createPipeline().process(el('<div some-comp some-decor></div>'));
|
||||
var dirs = results[0].getAllDirectives();
|
||||
expect(dirs.length).toEqual(2);
|
||||
expect(dirs[0]).toEqual(reader.read(SomeComponent));
|
||||
expect(dirs[1]).toEqual(reader.read(SomeDecorator));
|
||||
});
|
||||
|
||||
it('should detect them in property bindings', () => {
|
||||
var pipeline = createPipeline({propertyBindings: {
|
||||
'some-comp': 'someExpr'
|
||||
|
|
|
@ -56,7 +56,8 @@ export function main() {
|
|||
if (isPresent(current.element.getAttribute('directives'))) {
|
||||
hasBinding = true;
|
||||
for (var i=0; i<directives.length; i++) {
|
||||
current.addDirective(reflector.read(directives[i]));
|
||||
var dirMetadata = reflector.read(directives[i]);
|
||||
current.addDirective(dirMetadata);
|
||||
}
|
||||
}
|
||||
if (hasBinding) {
|
||||
|
@ -192,9 +193,9 @@ export function main() {
|
|||
'boundprop2': 'prop2',
|
||||
'boundprop3': 'prop3'
|
||||
});
|
||||
var directives = [SomeDecoratorDirectiveWith2Bindings,
|
||||
var directives = [SomeComponentDirectiveWithBinding,
|
||||
SomeTemplateDirectiveWithBinding,
|
||||
SomeComponentDirectiveWithBinding];
|
||||
SomeDecoratorDirectiveWith2Bindings];
|
||||
var protoElementInjector = new ProtoElementInjector(null, 0, directives, true);
|
||||
var pipeline = createPipeline({
|
||||
propertyBindings: propertyBindings,
|
||||
|
|
|
@ -32,7 +32,8 @@ export function main() {
|
|||
}
|
||||
if (isPresent(current.element.getAttribute('directives'))) {
|
||||
for (var i=0; i<directives.length; i++) {
|
||||
current.addDirective(reader.read(directives[i]));
|
||||
var dirMetadata = reader.read(directives[i]);
|
||||
current.addDirective(dirMetadata);
|
||||
}
|
||||
}
|
||||
current.inheritedProtoView = protoView;
|
||||
|
@ -133,9 +134,11 @@ export function main() {
|
|||
|
||||
class TestableProtoElementInjectorBuilder extends ProtoElementInjectorBuilder {
|
||||
debugObjects:List;
|
||||
|
||||
constructor() {
|
||||
this.debugObjects = [];
|
||||
}
|
||||
|
||||
findArgsFor(protoElementInjector:ProtoElementInjector) {
|
||||
for (var i=0; i<this.debugObjects.length; i+=2) {
|
||||
if (this.debugObjects[i] === protoElementInjector) {
|
||||
|
@ -144,6 +147,7 @@ class TestableProtoElementInjectorBuilder extends ProtoElementInjectorBuilder {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internalCreateProtoElementInjector(parent, index, bindings, firstBindingIsComponent, distance) {
|
||||
var result = new ProtoElementInjector(parent, index, bindings, firstBindingIsComponent, distance);
|
||||
ListWrapper.push(this.debugObjects, result);
|
||||
|
|
Loading…
Reference in New Issue