Skip to content

Commit b69f304

Browse files
committed
feat(compiler): added the DynamicComponent annotation
1 parent 1872b03 commit b69f304

File tree

8 files changed

+90
-11
lines changed

8 files changed

+90
-11
lines changed

modules/angular2/src/core/annotations/annotations.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,40 @@ export class Component extends Directive {
233233
}
234234
}
235235

236+
/**
237+
* @publicModule angular2/angular2
238+
*/
239+
export class DynamicComponent extends Directive {
240+
services:any; //List;
241+
242+
@CONST()
243+
constructor({
244+
selector,
245+
bind,
246+
events,
247+
services,
248+
implementsTypes,
249+
lifecycle
250+
}:{
251+
selector:string,
252+
bind:any,
253+
events:any,
254+
services:List,
255+
implementsTypes:List,
256+
lifecycle:List
257+
}={}) {
258+
super({
259+
selector: selector,
260+
bind: bind,
261+
events: events,
262+
implementsTypes: implementsTypes,
263+
lifecycle: lifecycle
264+
});
265+
266+
this.services = services;
267+
}
268+
}
269+
236270
/**
237271
* @publicModule angular2/angular2
238272
*/

modules/angular2/src/core/compiler/compiler.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ export class Compiler {
163163
var nestedPVPromises = [];
164164
for (var i = 0; i < compileElements.length; i++) {
165165
var ce = compileElements[i];
166-
if (isPresent(ce.componentDirective)) {
166+
if (ce.hasNestedView) {
167167
this._compileNestedProtoView(ce, nestedPVPromises);
168168
}
169169
}

modules/angular2/src/core/compiler/pipeline/compile_element.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {List, Map, ListWrapper, MapWrapper} from 'angular2/src/facade/collection
22
import {DOM} from 'angular2/src/dom/dom_adapter';
33
import {int, isBlank, isPresent, Type, StringJoiner, assertionsEnabled} from 'angular2/src/facade/lang';
44
import {DirectiveMetadata} from '../directive_metadata';
5-
import {Decorator, Component, Viewport} from '../../annotations/annotations';
5+
import {Decorator, Component, Viewport, DynamicComponent} from '../../annotations/annotations';
66
import {ElementBinder} from '../element_binder';
77
import {ProtoElementInjector} from '../element_injector';
88
import {ProtoView} from '../view';
@@ -30,6 +30,7 @@ export class CompileElement {
3030
decoratorDirectives:List<DirectiveMetadata>;
3131
viewportDirective:DirectiveMetadata;
3232
componentDirective:DirectiveMetadata;
33+
hasNestedView:boolean;
3334
_allDirectives:List<DirectiveMetadata>;
3435
isViewRoot:boolean;
3536
hasBindings:boolean;
@@ -54,6 +55,7 @@ export class CompileElement {
5455
this.decoratorDirectives = null;
5556
this.viewportDirective = null;
5657
this.componentDirective = null;
58+
this.hasNestedView = false;
5759
this._allDirectives = null;
5860
this.isViewRoot = false;
5961
this.hasBindings = false;
@@ -157,6 +159,9 @@ export class CompileElement {
157159
this.viewportDirective = directive;
158160
} else if (annotation instanceof Component) {
159161
this.componentDirective = directive;
162+
this.hasNestedView = true;
163+
} else if (annotation instanceof DynamicComponent) {
164+
this.componentDirective = directive;
160165
}
161166
}
162167

modules/angular2/src/core/compiler/pipeline/directive_parser.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {SelectorMatcher} from '../selector';
55
import {CssSelector} from '../selector';
66

77
import {DirectiveMetadata} from '../directive_metadata';
8-
import {Component, Viewport} from '../../annotations/annotations';
8+
import {DynamicComponent, Component, Viewport} from '../../annotations/annotations';
99
import {CompileStep} from './compile_step';
1010
import {CompileElement} from './compile_element';
1111
import {CompileControl} from './compile_control';
@@ -109,6 +109,9 @@ function updateMatchedProperties(matchedProperties, selector, directive) {
109109

110110
// check if the directive is compatible with the current element
111111
function checkDirectiveValidity(directive, current, isTemplateElement) {
112+
var isComponent = directive.annotation instanceof Component || directive.annotation instanceof DynamicComponent;
113+
var alreadyHasComponent = isPresent(current.componentDirective);
114+
112115
if (directive.annotation instanceof Viewport) {
113116
if (!isTemplateElement) {
114117
throw new BaseException(`Viewport directives need to be placed on <template> elements or elements ` +
@@ -118,7 +121,8 @@ function checkDirectiveValidity(directive, current, isTemplateElement) {
118121
}
119122
} else if (isTemplateElement) {
120123
throw new BaseException(`Only template directives are allowed on template elements - check ${current.elementDescription}`);
121-
} else if ((directive.annotation instanceof Component) && isPresent(current.componentDirective)) {
124+
125+
} else if (isComponent && alreadyHasComponent) {
122126
throw new BaseException(`Multiple component directives not allowed on the same element - check ${current.elementDescription}`);
123127
}
124128
}

modules/angular2/src/core/compiler/view.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ export class View {
171171
}
172172
}
173173

174-
if (isPresent(componentDirective)) {
174+
if (isPresent(binders[i].nestedProtoView) && isPresent(componentDirective)) {
175175
this.componentChildViews[componentChildViewIndex++].hydrate(shadowDomAppInjector,
176176
elementInjector, this.lightDoms[i], elementInjector.getComponent(), null);
177177
}
@@ -441,7 +441,7 @@ export class ProtoView {
441441
// componentChildViews
442442
var lightDom = null;
443443
var bindingPropagationConfig = null;
444-
if (isPresent(binder.componentDirective)) {
444+
if (isPresent(binder.nestedProtoView) && isPresent(binder.componentDirective)) {
445445
var strategy = this.shadowDomStrategy;
446446
var childView = binder.nestedProtoView.instantiate(elementInjector, eventManager);
447447
changeDetector.addChild(childView.changeDetector);

modules/angular2/test/core/compiler/compiler_common_tests.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ export function runCompilerCommonTests() {
114114
var compiler = createCompiler( (parent, current, control) => {
115115
if (DOM.hasClass(current.element, 'nested')) {
116116
current.componentDirective = reader.read(NestedComponent);
117+
current.hasNestedView = true;
117118
current.inheritedProtoView = parent.inheritedProtoView;
118119
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null);
119120
} else {
@@ -163,6 +164,7 @@ export function runCompilerCommonTests() {
163164

164165
it('should allow recursive components', inject([AsyncTestCompleter], (async) => {
165166
var compiler = createCompiler( (parent, current, control) => {
167+
current.hasNestedView = true;
166168
current.inheritedProtoView = new ProtoView(current.element, null, null);
167169
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null);
168170
current.componentDirective = reader.read(RecursiveComponent);
@@ -191,6 +193,7 @@ export function runCompilerCommonTests() {
191193

192194
var compiler = createCompiler((parent, current, control) => {
193195
if (DOM.hasClass(current.element, 'parent')) {
196+
current.hasNestedView = true;
194197
current.componentDirective = reader.read(NestedComponent);
195198
current.inheritedProtoView = parent.inheritedProtoView;
196199
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null);

modules/angular2/test/core/compiler/pipeline/directive_parser_spec.js

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import {describe, beforeEach, it, expect, iit, ddescribe, el} from 'angular2/test_lib';
1+
import {describe, beforeEach, it, xit, expect, iit, ddescribe, el} from 'angular2/test_lib';
22
import {isPresent, assertionsEnabled} from 'angular2/src/facade/lang';
33
import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
44
import {DirectiveParser} from 'angular2/src/core/compiler/pipeline/directive_parser';
55
import {CompilePipeline} from 'angular2/src/core/compiler/pipeline/compile_pipeline';
66
import {CompileStep} from 'angular2/src/core/compiler/pipeline/compile_step';
77
import {CompileElement} from 'angular2/src/core/compiler/pipeline/compile_element';
88
import {CompileControl} from 'angular2/src/core/compiler/pipeline/compile_control';
9-
import {Component, Decorator, Viewport} from 'angular2/src/core/annotations/annotations';
9+
import {Component, DynamicComponent, Decorator, Viewport} from 'angular2/src/core/annotations/annotations';
1010
import {Template} from 'angular2/src/core/annotations/template';
1111
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
1212
import {Lexer, Parser} from 'angular2/change_detection';
@@ -24,7 +24,9 @@ export function main() {
2424
SomeViewport,
2525
SomeViewport2,
2626
SomeComponent,
27-
SomeComponent2
27+
SomeComponent2,
28+
SomeDynamicComponent,
29+
SomeDynamicComponent2
2830
];
2931
});
3032

@@ -105,6 +107,29 @@ export function main() {
105107
});
106108
});
107109

110+
describe("dynamic component directives", () => {
111+
it('should detect dynamic component', () => {
112+
var results = createPipeline().process(el('<div some-dynamic-comp></div>'));
113+
expect(results[0].componentDirective).toEqual(reader.read(SomeDynamicComponent));
114+
});
115+
116+
it('should not allow multiple dynamic component directives on the same element', () => {
117+
expect( () => {
118+
createPipeline().process(
119+
el('<div some-dynamic-comp some-dynamic-comp2></div>')
120+
);
121+
}).toThrowError(new RegExp('Multiple component directives not allowed on the same element'));
122+
});
123+
124+
it('should not allow component and dynamic directives on the same element', () => {
125+
expect( () => {
126+
createPipeline().process(
127+
el('<div some-dynamic-comp some-comp></div>')
128+
);
129+
}).toThrowError(new RegExp('Multiple component directives not allowed on the same element'));
130+
});
131+
});
132+
108133
describe('viewport directives', () => {
109134
it('should detect them in attributes', () => {
110135
var results = createPipeline().process(el('<template some-templ></template>'));
@@ -236,8 +261,17 @@ class SomeComponent {}
236261
@Component({selector: '[some-comp2]'})
237262
class SomeComponent2 {}
238263

264+
@DynamicComponent({selector: '[some-dynamic-comp]'})
265+
class SomeDynamicComponent {}
266+
267+
@DynamicComponent({selector: '[some-dynamic-comp2]'})
268+
class SomeDynamicComponent2 {}
269+
239270
@Component()
240271
@Template({
241-
directives: [SomeDecorator, SomeViewport, SomeViewport2, SomeComponent, SomeComponent2]
272+
directives: [SomeDecorator, SomeViewport, SomeViewport2,
273+
SomeComponent, SomeComponent2,
274+
SomeDynamicComponent, SomeDynamicComponent2
275+
]
242276
})
243277
class MyComp {}

modules/angular2/test/core/compiler/pipeline/element_binding_marker_spec.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ export function main() {
101101
}).process(el('<div></div>'));
102102
assertBinding(results[0], true);
103103
});
104-
105104
});
106105
}
107106

0 commit comments

Comments
 (0)