feat(compiler): added the DynamicComponent annotation
This commit is contained in:
parent
1872b03fb8
commit
b69f3043e0
|
@ -233,6 +233,40 @@ export class Component extends Directive {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @publicModule angular2/angular2
|
||||||
|
*/
|
||||||
|
export class DynamicComponent extends Directive {
|
||||||
|
services:any; //List;
|
||||||
|
|
||||||
|
@CONST()
|
||||||
|
constructor({
|
||||||
|
selector,
|
||||||
|
bind,
|
||||||
|
events,
|
||||||
|
services,
|
||||||
|
implementsTypes,
|
||||||
|
lifecycle
|
||||||
|
}:{
|
||||||
|
selector:string,
|
||||||
|
bind:any,
|
||||||
|
events:any,
|
||||||
|
services:List,
|
||||||
|
implementsTypes:List,
|
||||||
|
lifecycle:List
|
||||||
|
}={}) {
|
||||||
|
super({
|
||||||
|
selector: selector,
|
||||||
|
bind: bind,
|
||||||
|
events: events,
|
||||||
|
implementsTypes: implementsTypes,
|
||||||
|
lifecycle: lifecycle
|
||||||
|
});
|
||||||
|
|
||||||
|
this.services = services;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @publicModule angular2/angular2
|
* @publicModule angular2/angular2
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -163,7 +163,7 @@ export class Compiler {
|
||||||
var nestedPVPromises = [];
|
var nestedPVPromises = [];
|
||||||
for (var i = 0; i < compileElements.length; i++) {
|
for (var i = 0; i < compileElements.length; i++) {
|
||||||
var ce = compileElements[i];
|
var ce = compileElements[i];
|
||||||
if (isPresent(ce.componentDirective)) {
|
if (ce.hasNestedView) {
|
||||||
this._compileNestedProtoView(ce, nestedPVPromises);
|
this._compileNestedProtoView(ce, nestedPVPromises);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {List, Map, ListWrapper, MapWrapper} from 'angular2/src/facade/collection
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {int, isBlank, isPresent, Type, StringJoiner, assertionsEnabled} from 'angular2/src/facade/lang';
|
import {int, isBlank, isPresent, Type, StringJoiner, assertionsEnabled} from 'angular2/src/facade/lang';
|
||||||
import {DirectiveMetadata} from '../directive_metadata';
|
import {DirectiveMetadata} from '../directive_metadata';
|
||||||
import {Decorator, Component, Viewport} from '../../annotations/annotations';
|
import {Decorator, Component, Viewport, DynamicComponent} from '../../annotations/annotations';
|
||||||
import {ElementBinder} from '../element_binder';
|
import {ElementBinder} from '../element_binder';
|
||||||
import {ProtoElementInjector} from '../element_injector';
|
import {ProtoElementInjector} from '../element_injector';
|
||||||
import {ProtoView} from '../view';
|
import {ProtoView} from '../view';
|
||||||
|
@ -30,6 +30,7 @@ export class CompileElement {
|
||||||
decoratorDirectives:List<DirectiveMetadata>;
|
decoratorDirectives:List<DirectiveMetadata>;
|
||||||
viewportDirective:DirectiveMetadata;
|
viewportDirective:DirectiveMetadata;
|
||||||
componentDirective:DirectiveMetadata;
|
componentDirective:DirectiveMetadata;
|
||||||
|
hasNestedView:boolean;
|
||||||
_allDirectives:List<DirectiveMetadata>;
|
_allDirectives:List<DirectiveMetadata>;
|
||||||
isViewRoot:boolean;
|
isViewRoot:boolean;
|
||||||
hasBindings:boolean;
|
hasBindings:boolean;
|
||||||
|
@ -54,6 +55,7 @@ export class CompileElement {
|
||||||
this.decoratorDirectives = null;
|
this.decoratorDirectives = null;
|
||||||
this.viewportDirective = null;
|
this.viewportDirective = null;
|
||||||
this.componentDirective = null;
|
this.componentDirective = null;
|
||||||
|
this.hasNestedView = false;
|
||||||
this._allDirectives = null;
|
this._allDirectives = null;
|
||||||
this.isViewRoot = false;
|
this.isViewRoot = false;
|
||||||
this.hasBindings = false;
|
this.hasBindings = false;
|
||||||
|
@ -157,6 +159,9 @@ export class CompileElement {
|
||||||
this.viewportDirective = directive;
|
this.viewportDirective = directive;
|
||||||
} else if (annotation instanceof Component) {
|
} else if (annotation instanceof Component) {
|
||||||
this.componentDirective = directive;
|
this.componentDirective = directive;
|
||||||
|
this.hasNestedView = true;
|
||||||
|
} else if (annotation instanceof DynamicComponent) {
|
||||||
|
this.componentDirective = directive;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {SelectorMatcher} from '../selector';
|
||||||
import {CssSelector} from '../selector';
|
import {CssSelector} from '../selector';
|
||||||
|
|
||||||
import {DirectiveMetadata} from '../directive_metadata';
|
import {DirectiveMetadata} from '../directive_metadata';
|
||||||
import {Component, Viewport} from '../../annotations/annotations';
|
import {DynamicComponent, Component, Viewport} from '../../annotations/annotations';
|
||||||
import {CompileStep} from './compile_step';
|
import {CompileStep} from './compile_step';
|
||||||
import {CompileElement} from './compile_element';
|
import {CompileElement} from './compile_element';
|
||||||
import {CompileControl} from './compile_control';
|
import {CompileControl} from './compile_control';
|
||||||
|
@ -109,6 +109,9 @@ function updateMatchedProperties(matchedProperties, selector, directive) {
|
||||||
|
|
||||||
// check if the directive is compatible with the current element
|
// check if the directive is compatible with the current element
|
||||||
function checkDirectiveValidity(directive, current, isTemplateElement) {
|
function checkDirectiveValidity(directive, current, isTemplateElement) {
|
||||||
|
var isComponent = directive.annotation instanceof Component || directive.annotation instanceof DynamicComponent;
|
||||||
|
var alreadyHasComponent = isPresent(current.componentDirective);
|
||||||
|
|
||||||
if (directive.annotation instanceof Viewport) {
|
if (directive.annotation instanceof Viewport) {
|
||||||
if (!isTemplateElement) {
|
if (!isTemplateElement) {
|
||||||
throw new BaseException(`Viewport directives need to be placed on <template> elements or elements ` +
|
throw new BaseException(`Viewport directives need to be placed on <template> elements or elements ` +
|
||||||
|
@ -118,7 +121,8 @@ function checkDirectiveValidity(directive, current, isTemplateElement) {
|
||||||
}
|
}
|
||||||
} else if (isTemplateElement) {
|
} else if (isTemplateElement) {
|
||||||
throw new BaseException(`Only template directives are allowed on template elements - check ${current.elementDescription}`);
|
throw new BaseException(`Only template directives are allowed on template elements - check ${current.elementDescription}`);
|
||||||
} else if ((directive.annotation instanceof Component) && isPresent(current.componentDirective)) {
|
|
||||||
|
} else if (isComponent && alreadyHasComponent) {
|
||||||
throw new BaseException(`Multiple component directives not allowed on the same element - check ${current.elementDescription}`);
|
throw new BaseException(`Multiple component directives not allowed on the same element - check ${current.elementDescription}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,7 @@ export class View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPresent(componentDirective)) {
|
if (isPresent(binders[i].nestedProtoView) && isPresent(componentDirective)) {
|
||||||
this.componentChildViews[componentChildViewIndex++].hydrate(shadowDomAppInjector,
|
this.componentChildViews[componentChildViewIndex++].hydrate(shadowDomAppInjector,
|
||||||
elementInjector, this.lightDoms[i], elementInjector.getComponent(), null);
|
elementInjector, this.lightDoms[i], elementInjector.getComponent(), null);
|
||||||
}
|
}
|
||||||
|
@ -441,7 +441,7 @@ export class ProtoView {
|
||||||
// componentChildViews
|
// componentChildViews
|
||||||
var lightDom = null;
|
var lightDom = null;
|
||||||
var bindingPropagationConfig = null;
|
var bindingPropagationConfig = null;
|
||||||
if (isPresent(binder.componentDirective)) {
|
if (isPresent(binder.nestedProtoView) && isPresent(binder.componentDirective)) {
|
||||||
var strategy = this.shadowDomStrategy;
|
var strategy = this.shadowDomStrategy;
|
||||||
var childView = binder.nestedProtoView.instantiate(elementInjector, eventManager);
|
var childView = binder.nestedProtoView.instantiate(elementInjector, eventManager);
|
||||||
changeDetector.addChild(childView.changeDetector);
|
changeDetector.addChild(childView.changeDetector);
|
||||||
|
|
|
@ -114,6 +114,7 @@ export function runCompilerCommonTests() {
|
||||||
var compiler = createCompiler( (parent, current, control) => {
|
var compiler = createCompiler( (parent, current, control) => {
|
||||||
if (DOM.hasClass(current.element, 'nested')) {
|
if (DOM.hasClass(current.element, 'nested')) {
|
||||||
current.componentDirective = reader.read(NestedComponent);
|
current.componentDirective = reader.read(NestedComponent);
|
||||||
|
current.hasNestedView = true;
|
||||||
current.inheritedProtoView = parent.inheritedProtoView;
|
current.inheritedProtoView = parent.inheritedProtoView;
|
||||||
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null);
|
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null);
|
||||||
} else {
|
} else {
|
||||||
|
@ -163,6 +164,7 @@ export function runCompilerCommonTests() {
|
||||||
|
|
||||||
it('should allow recursive components', inject([AsyncTestCompleter], (async) => {
|
it('should allow recursive components', inject([AsyncTestCompleter], (async) => {
|
||||||
var compiler = createCompiler( (parent, current, control) => {
|
var compiler = createCompiler( (parent, current, control) => {
|
||||||
|
current.hasNestedView = true;
|
||||||
current.inheritedProtoView = new ProtoView(current.element, null, null);
|
current.inheritedProtoView = new ProtoView(current.element, null, null);
|
||||||
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null);
|
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null);
|
||||||
current.componentDirective = reader.read(RecursiveComponent);
|
current.componentDirective = reader.read(RecursiveComponent);
|
||||||
|
@ -191,6 +193,7 @@ export function runCompilerCommonTests() {
|
||||||
|
|
||||||
var compiler = createCompiler((parent, current, control) => {
|
var compiler = createCompiler((parent, current, control) => {
|
||||||
if (DOM.hasClass(current.element, 'parent')) {
|
if (DOM.hasClass(current.element, 'parent')) {
|
||||||
|
current.hasNestedView = true;
|
||||||
current.componentDirective = reader.read(NestedComponent);
|
current.componentDirective = reader.read(NestedComponent);
|
||||||
current.inheritedProtoView = parent.inheritedProtoView;
|
current.inheritedProtoView = parent.inheritedProtoView;
|
||||||
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null);
|
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {describe, beforeEach, it, expect, iit, ddescribe, el} from 'angular2/test_lib';
|
import {describe, beforeEach, it, xit, expect, iit, ddescribe, el} from 'angular2/test_lib';
|
||||||
import {isPresent, assertionsEnabled} from 'angular2/src/facade/lang';
|
import {isPresent, assertionsEnabled} from 'angular2/src/facade/lang';
|
||||||
import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {DirectiveParser} from 'angular2/src/core/compiler/pipeline/directive_parser';
|
import {DirectiveParser} from 'angular2/src/core/compiler/pipeline/directive_parser';
|
||||||
|
@ -6,7 +6,7 @@ import {CompilePipeline} from 'angular2/src/core/compiler/pipeline/compile_pipel
|
||||||
import {CompileStep} from 'angular2/src/core/compiler/pipeline/compile_step';
|
import {CompileStep} from 'angular2/src/core/compiler/pipeline/compile_step';
|
||||||
import {CompileElement} from 'angular2/src/core/compiler/pipeline/compile_element';
|
import {CompileElement} from 'angular2/src/core/compiler/pipeline/compile_element';
|
||||||
import {CompileControl} from 'angular2/src/core/compiler/pipeline/compile_control';
|
import {CompileControl} from 'angular2/src/core/compiler/pipeline/compile_control';
|
||||||
import {Component, Decorator, Viewport} from 'angular2/src/core/annotations/annotations';
|
import {Component, DynamicComponent, Decorator, Viewport} from 'angular2/src/core/annotations/annotations';
|
||||||
import {Template} from 'angular2/src/core/annotations/template';
|
import {Template} from 'angular2/src/core/annotations/template';
|
||||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||||
import {Lexer, Parser} from 'angular2/change_detection';
|
import {Lexer, Parser} from 'angular2/change_detection';
|
||||||
|
@ -24,7 +24,9 @@ export function main() {
|
||||||
SomeViewport,
|
SomeViewport,
|
||||||
SomeViewport2,
|
SomeViewport2,
|
||||||
SomeComponent,
|
SomeComponent,
|
||||||
SomeComponent2
|
SomeComponent2,
|
||||||
|
SomeDynamicComponent,
|
||||||
|
SomeDynamicComponent2
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -105,6 +107,29 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("dynamic component directives", () => {
|
||||||
|
it('should detect dynamic component', () => {
|
||||||
|
var results = createPipeline().process(el('<div some-dynamic-comp></div>'));
|
||||||
|
expect(results[0].componentDirective).toEqual(reader.read(SomeDynamicComponent));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not allow multiple dynamic component directives on the same element', () => {
|
||||||
|
expect( () => {
|
||||||
|
createPipeline().process(
|
||||||
|
el('<div some-dynamic-comp some-dynamic-comp2></div>')
|
||||||
|
);
|
||||||
|
}).toThrowError(new RegExp('Multiple component directives not allowed on the same element'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not allow component and dynamic directives on the same element', () => {
|
||||||
|
expect( () => {
|
||||||
|
createPipeline().process(
|
||||||
|
el('<div some-dynamic-comp some-comp></div>')
|
||||||
|
);
|
||||||
|
}).toThrowError(new RegExp('Multiple component directives not allowed on the same element'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('viewport directives', () => {
|
describe('viewport directives', () => {
|
||||||
it('should detect them in attributes', () => {
|
it('should detect them in attributes', () => {
|
||||||
var results = createPipeline().process(el('<template some-templ></template>'));
|
var results = createPipeline().process(el('<template some-templ></template>'));
|
||||||
|
@ -236,8 +261,17 @@ class SomeComponent {}
|
||||||
@Component({selector: '[some-comp2]'})
|
@Component({selector: '[some-comp2]'})
|
||||||
class SomeComponent2 {}
|
class SomeComponent2 {}
|
||||||
|
|
||||||
|
@DynamicComponent({selector: '[some-dynamic-comp]'})
|
||||||
|
class SomeDynamicComponent {}
|
||||||
|
|
||||||
|
@DynamicComponent({selector: '[some-dynamic-comp2]'})
|
||||||
|
class SomeDynamicComponent2 {}
|
||||||
|
|
||||||
@Component()
|
@Component()
|
||||||
@Template({
|
@Template({
|
||||||
directives: [SomeDecorator, SomeViewport, SomeViewport2, SomeComponent, SomeComponent2]
|
directives: [SomeDecorator, SomeViewport, SomeViewport2,
|
||||||
|
SomeComponent, SomeComponent2,
|
||||||
|
SomeDynamicComponent, SomeDynamicComponent2
|
||||||
|
]
|
||||||
})
|
})
|
||||||
class MyComp {}
|
class MyComp {}
|
||||||
|
|
|
@ -101,7 +101,6 @@ export function main() {
|
||||||
}).process(el('<div></div>'));
|
}).process(el('<div></div>'));
|
||||||
assertBinding(results[0], true);
|
assertBinding(results[0], true);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue