Skip to content

Commit 2041860

Browse files
committed
feat: added an ability to dynamically load components
1 parent 7488456 commit 2041860

File tree

4 files changed

+104
-13
lines changed

4 files changed

+104
-13
lines changed

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -245,21 +245,18 @@ export class DynamicComponent extends Directive {
245245
bind,
246246
events,
247247
services,
248-
implementsTypes,
249248
lifecycle
250249
}:{
251250
selector:string,
252-
bind:any,
253-
events:any,
251+
bind:Object,
252+
events:Object,
254253
services:List,
255-
implementsTypes:List,
256254
lifecycle:List
257255
}={}) {
258256
super({
259257
selector: selector,
260258
bind: bind,
261259
events: events,
262-
implementsTypes: implementsTypes,
263260
lifecycle: lifecycle
264261
});
265262

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {Compiler} from './compiler';
2+
import {ShadowDomStrategy} from './shadow_dom_strategy';
3+
import {EventManager} from 'angular2/src/core/events/event_manager';
4+
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
5+
import {PrivateComponentLocation} from './private_component_location';
6+
import {Type} from 'angular2/src/facade/lang';
7+
8+
9+
export class PrivateComponentLoader {
10+
compiler:Compiler;
11+
shadowDomStrategy:ShadowDomStrategy;
12+
eventManager:EventManager;
13+
directiveMetadataReader:DirectiveMetadataReader;
14+
15+
constructor(compiler:Compiler, shadowDomStrategy:ShadowDomStrategy,
16+
eventManager:EventManager, directiveMetadataReader:DirectiveMetadataReader) {
17+
18+
this.compiler = compiler;
19+
this.shadowDomStrategy = shadowDomStrategy;
20+
this.eventManager = eventManager;
21+
this.directiveMetadataReader = directiveMetadataReader;
22+
}
23+
24+
load(type:Type, location:PrivateComponentLocation) {
25+
var annotation = this.directiveMetadataReader.read(type).annotation;
26+
return this.compiler.compile(type).then((componentProtoView) => {
27+
location.createComponent(
28+
type, annotation,
29+
componentProtoView,
30+
this.eventManager,
31+
this.shadowDomStrategy);
32+
});
33+
}
34+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class PrivateComponentLocation {
2424
var context = this._elementInjector.createPrivateComponent(type, annotation);
2525

2626
var view = componentProtoView.instantiate(this._elementInjector, eventManager);
27-
view.hydrate(this._elementInjector.getShadowDomAppInjector(), this._elementInjector, context);
27+
view.hydrate(this._elementInjector.getShadowDomAppInjector(), this._elementInjector, null, context, null);
2828

2929
shadowDomStrategy.attachTemplate(this._elt.domElement, view);
3030

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

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,25 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
1515
import {Type, isPresent, BaseException, assertionsEnabled, isJsObject} from 'angular2/src/facade/lang';
1616
import {PromiseWrapper} from 'angular2/src/facade/async';
1717

18-
import {Injector} from 'angular2/di';
18+
import {Injector, bind} from 'angular2/di';
1919
import {Lexer, Parser, dynamicChangeDetection,
2020
DynamicChangeDetection, Pipe, PipeRegistry} from 'angular2/change_detection';
2121

2222
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
2323
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
24-
import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
24+
import {ShadowDomStrategy, NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
25+
import {PrivateComponentLocation} from 'angular2/src/core/compiler/private_component_location';
26+
import {PrivateComponentLoader} from 'angular2/src/core/compiler/private_component_loader';
2527
import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
2628
import {MockTemplateResolver} from 'angular2/src/mock/template_resolver_mock';
2729
import {BindingPropagationConfig} from 'angular2/src/core/compiler/binding_propagation_config';
2830
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
2931
import {UrlResolver} from 'angular2/src/core/compiler/url_resolver';
3032
import {StyleUrlResolver} from 'angular2/src/core/compiler/style_url_resolver';
3133
import {CssProcessor} from 'angular2/src/core/compiler/css_processor';
34+
import {EventManager} from 'angular2/src/core/events/event_manager';
3235

33-
import {Decorator, Component, Viewport} from 'angular2/src/core/annotations/annotations';
36+
import {Decorator, Component, Viewport, DynamicComponent} from 'angular2/src/core/annotations/annotations';
3437
import {Template} from 'angular2/src/core/annotations/template';
3538
import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
3639
import {EventEmitter} from 'angular2/src/core/annotations/di';
@@ -41,16 +44,16 @@ import {ViewContainer} from 'angular2/src/core/compiler/view_container';
4144

4245
export function main() {
4346
describe('integration tests', function() {
44-
var compiler, tplResolver;
47+
var directiveMetadataReader, shadowDomStrategy, compiler, tplResolver;
4548

4649
function createCompiler(tplResolver, changedDetection) {
4750
var urlResolver = new UrlResolver();
4851
return new Compiler(changedDetection,
4952
new TemplateLoader(null, null),
50-
new DirectiveMetadataReader(),
53+
directiveMetadataReader,
5154
new Parser(new Lexer()),
5255
new CompilerCache(),
53-
new NativeShadowDomStrategy(new StyleUrlResolver(urlResolver)),
56+
shadowDomStrategy,
5457
tplResolver,
5558
new ComponentUrlMapper(),
5659
urlResolver,
@@ -60,6 +63,12 @@ export function main() {
6063

6164
beforeEach( () => {
6265
tplResolver = new MockTemplateResolver();
66+
67+
directiveMetadataReader = new DirectiveMetadataReader();
68+
69+
var urlResolver = new UrlResolver();
70+
shadowDomStrategy = new NativeShadowDomStrategy(new StyleUrlResolver(urlResolver));
71+
6372
compiler = createCompiler(tplResolver, dynamicChangeDetection);
6473
});
6574

@@ -68,7 +77,15 @@ export function main() {
6877
function createView(pv) {
6978
ctx = new MyComp();
7079
view = pv.instantiate(null, null);
71-
view.hydrate(new Injector([]), null, null, ctx, null);
80+
81+
view.hydrate(new Injector([
82+
bind(Compiler).toValue(compiler),
83+
bind(DirectiveMetadataReader).toValue(directiveMetadataReader),
84+
bind(ShadowDomStrategy).toValue(shadowDomStrategy),
85+
bind(EventManager).toValue(null),
86+
PrivateComponentLoader
87+
]), null, null, ctx, null);
88+
7289
cd = view.changeDetector;
7390
}
7491

@@ -512,6 +529,25 @@ export function main() {
512529
});
513530
}));
514531

532+
it('should support dynamic components', inject([AsyncTestCompleter], (async) => {
533+
tplResolver.setTemplate(MyComp, new Template({
534+
inline: '<dynamic-comp #dynamic></dynamic-comp>',
535+
directives: [DynamicComp]
536+
}));
537+
538+
compiler.compile(MyComp).then((pv) => {
539+
createView(pv);
540+
541+
var dynamicComponent = view.locals.get("dynamic");
542+
expect(dynamicComponent).toBeAnInstanceOf(DynamicComp);
543+
544+
dynamicComponent.done.then((_) => {
545+
cd.detectChanges();
546+
expect(view.nodes).toHaveText('hello');
547+
async.done();
548+
});
549+
});
550+
}));
515551
});
516552

517553
if (assertionsEnabled()) {
@@ -572,6 +608,30 @@ export function main() {
572608
});
573609
}
574610

611+
612+
@DynamicComponent({
613+
selector: 'dynamic-comp'
614+
})
615+
class DynamicComp {
616+
done;
617+
constructor(loader:PrivateComponentLoader, location:PrivateComponentLocation) {
618+
this.done = loader.load(HelloCmp, location);
619+
}
620+
}
621+
622+
@Component({
623+
selector: 'hello-cmp'
624+
})
625+
@Template({
626+
inline: "{{greeting}}"
627+
})
628+
class HelloCmp {
629+
greeting:string;
630+
constructor() {
631+
this.greeting = "hello";
632+
}
633+
}
634+
575635
@Decorator({
576636
selector: '[my-dir]',
577637
bind: {'dirProp':'elprop'}

0 commit comments

Comments
 (0)