feat: added an ability to dynamically load components
This commit is contained in:
parent
7488456d68
commit
2041860a21
|
@ -245,21 +245,18 @@ export class DynamicComponent extends Directive {
|
||||||
bind,
|
bind,
|
||||||
events,
|
events,
|
||||||
services,
|
services,
|
||||||
implementsTypes,
|
|
||||||
lifecycle
|
lifecycle
|
||||||
}:{
|
}:{
|
||||||
selector:string,
|
selector:string,
|
||||||
bind:any,
|
bind:Object,
|
||||||
events:any,
|
events:Object,
|
||||||
services:List,
|
services:List,
|
||||||
implementsTypes:List,
|
|
||||||
lifecycle:List
|
lifecycle:List
|
||||||
}={}) {
|
}={}) {
|
||||||
super({
|
super({
|
||||||
selector: selector,
|
selector: selector,
|
||||||
bind: bind,
|
bind: bind,
|
||||||
events: events,
|
events: events,
|
||||||
implementsTypes: implementsTypes,
|
|
||||||
lifecycle: lifecycle
|
lifecycle: lifecycle
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import {Compiler} from './compiler';
|
||||||
|
import {ShadowDomStrategy} from './shadow_dom_strategy';
|
||||||
|
import {EventManager} from 'angular2/src/core/events/event_manager';
|
||||||
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||||
|
import {PrivateComponentLocation} from './private_component_location';
|
||||||
|
import {Type} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
|
|
||||||
|
export class PrivateComponentLoader {
|
||||||
|
compiler:Compiler;
|
||||||
|
shadowDomStrategy:ShadowDomStrategy;
|
||||||
|
eventManager:EventManager;
|
||||||
|
directiveMetadataReader:DirectiveMetadataReader;
|
||||||
|
|
||||||
|
constructor(compiler:Compiler, shadowDomStrategy:ShadowDomStrategy,
|
||||||
|
eventManager:EventManager, directiveMetadataReader:DirectiveMetadataReader) {
|
||||||
|
|
||||||
|
this.compiler = compiler;
|
||||||
|
this.shadowDomStrategy = shadowDomStrategy;
|
||||||
|
this.eventManager = eventManager;
|
||||||
|
this.directiveMetadataReader = directiveMetadataReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
load(type:Type, location:PrivateComponentLocation) {
|
||||||
|
var annotation = this.directiveMetadataReader.read(type).annotation;
|
||||||
|
return this.compiler.compile(type).then((componentProtoView) => {
|
||||||
|
location.createComponent(
|
||||||
|
type, annotation,
|
||||||
|
componentProtoView,
|
||||||
|
this.eventManager,
|
||||||
|
this.shadowDomStrategy);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,7 +24,7 @@ export class PrivateComponentLocation {
|
||||||
var context = this._elementInjector.createPrivateComponent(type, annotation);
|
var context = this._elementInjector.createPrivateComponent(type, annotation);
|
||||||
|
|
||||||
var view = componentProtoView.instantiate(this._elementInjector, eventManager);
|
var view = componentProtoView.instantiate(this._elementInjector, eventManager);
|
||||||
view.hydrate(this._elementInjector.getShadowDomAppInjector(), this._elementInjector, context);
|
view.hydrate(this._elementInjector.getShadowDomAppInjector(), this._elementInjector, null, context, null);
|
||||||
|
|
||||||
shadowDomStrategy.attachTemplate(this._elt.domElement, view);
|
shadowDomStrategy.attachTemplate(this._elt.domElement, view);
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,15 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {Type, isPresent, BaseException, assertionsEnabled, isJsObject} from 'angular2/src/facade/lang';
|
import {Type, isPresent, BaseException, assertionsEnabled, isJsObject} from 'angular2/src/facade/lang';
|
||||||
import {PromiseWrapper} from 'angular2/src/facade/async';
|
import {PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
import {Injector} from 'angular2/di';
|
import {Injector, bind} from 'angular2/di';
|
||||||
import {Lexer, Parser, dynamicChangeDetection,
|
import {Lexer, Parser, dynamicChangeDetection,
|
||||||
DynamicChangeDetection, Pipe, PipeRegistry} from 'angular2/change_detection';
|
DynamicChangeDetection, Pipe, PipeRegistry} from 'angular2/change_detection';
|
||||||
|
|
||||||
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||||
import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
import {ShadowDomStrategy, NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
|
import {PrivateComponentLocation} from 'angular2/src/core/compiler/private_component_location';
|
||||||
|
import {PrivateComponentLoader} from 'angular2/src/core/compiler/private_component_loader';
|
||||||
import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
||||||
import {MockTemplateResolver} from 'angular2/src/mock/template_resolver_mock';
|
import {MockTemplateResolver} from 'angular2/src/mock/template_resolver_mock';
|
||||||
import {BindingPropagationConfig} from 'angular2/src/core/compiler/binding_propagation_config';
|
import {BindingPropagationConfig} from 'angular2/src/core/compiler/binding_propagation_config';
|
||||||
|
@ -29,8 +31,9 @@ import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mappe
|
||||||
import {UrlResolver} from 'angular2/src/core/compiler/url_resolver';
|
import {UrlResolver} from 'angular2/src/core/compiler/url_resolver';
|
||||||
import {StyleUrlResolver} from 'angular2/src/core/compiler/style_url_resolver';
|
import {StyleUrlResolver} from 'angular2/src/core/compiler/style_url_resolver';
|
||||||
import {CssProcessor} from 'angular2/src/core/compiler/css_processor';
|
import {CssProcessor} from 'angular2/src/core/compiler/css_processor';
|
||||||
|
import {EventManager} from 'angular2/src/core/events/event_manager';
|
||||||
|
|
||||||
import {Decorator, Component, Viewport} from 'angular2/src/core/annotations/annotations';
|
import {Decorator, Component, Viewport, DynamicComponent} from 'angular2/src/core/annotations/annotations';
|
||||||
import {Template} from 'angular2/src/core/annotations/template';
|
import {Template} from 'angular2/src/core/annotations/template';
|
||||||
import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
|
import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
|
||||||
import {EventEmitter} from 'angular2/src/core/annotations/di';
|
import {EventEmitter} from 'angular2/src/core/annotations/di';
|
||||||
|
@ -41,16 +44,16 @@ import {ViewContainer} from 'angular2/src/core/compiler/view_container';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('integration tests', function() {
|
describe('integration tests', function() {
|
||||||
var compiler, tplResolver;
|
var directiveMetadataReader, shadowDomStrategy, compiler, tplResolver;
|
||||||
|
|
||||||
function createCompiler(tplResolver, changedDetection) {
|
function createCompiler(tplResolver, changedDetection) {
|
||||||
var urlResolver = new UrlResolver();
|
var urlResolver = new UrlResolver();
|
||||||
return new Compiler(changedDetection,
|
return new Compiler(changedDetection,
|
||||||
new TemplateLoader(null, null),
|
new TemplateLoader(null, null),
|
||||||
new DirectiveMetadataReader(),
|
directiveMetadataReader,
|
||||||
new Parser(new Lexer()),
|
new Parser(new Lexer()),
|
||||||
new CompilerCache(),
|
new CompilerCache(),
|
||||||
new NativeShadowDomStrategy(new StyleUrlResolver(urlResolver)),
|
shadowDomStrategy,
|
||||||
tplResolver,
|
tplResolver,
|
||||||
new ComponentUrlMapper(),
|
new ComponentUrlMapper(),
|
||||||
urlResolver,
|
urlResolver,
|
||||||
|
@ -60,6 +63,12 @@ export function main() {
|
||||||
|
|
||||||
beforeEach( () => {
|
beforeEach( () => {
|
||||||
tplResolver = new MockTemplateResolver();
|
tplResolver = new MockTemplateResolver();
|
||||||
|
|
||||||
|
directiveMetadataReader = new DirectiveMetadataReader();
|
||||||
|
|
||||||
|
var urlResolver = new UrlResolver();
|
||||||
|
shadowDomStrategy = new NativeShadowDomStrategy(new StyleUrlResolver(urlResolver));
|
||||||
|
|
||||||
compiler = createCompiler(tplResolver, dynamicChangeDetection);
|
compiler = createCompiler(tplResolver, dynamicChangeDetection);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -68,7 +77,15 @@ export function main() {
|
||||||
function createView(pv) {
|
function createView(pv) {
|
||||||
ctx = new MyComp();
|
ctx = new MyComp();
|
||||||
view = pv.instantiate(null, null);
|
view = pv.instantiate(null, null);
|
||||||
view.hydrate(new Injector([]), null, null, ctx, null);
|
|
||||||
|
view.hydrate(new Injector([
|
||||||
|
bind(Compiler).toValue(compiler),
|
||||||
|
bind(DirectiveMetadataReader).toValue(directiveMetadataReader),
|
||||||
|
bind(ShadowDomStrategy).toValue(shadowDomStrategy),
|
||||||
|
bind(EventManager).toValue(null),
|
||||||
|
PrivateComponentLoader
|
||||||
|
]), null, null, ctx, null);
|
||||||
|
|
||||||
cd = view.changeDetector;
|
cd = view.changeDetector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,6 +529,25 @@ export function main() {
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should support dynamic components', inject([AsyncTestCompleter], (async) => {
|
||||||
|
tplResolver.setTemplate(MyComp, new Template({
|
||||||
|
inline: '<dynamic-comp #dynamic></dynamic-comp>',
|
||||||
|
directives: [DynamicComp]
|
||||||
|
}));
|
||||||
|
|
||||||
|
compiler.compile(MyComp).then((pv) => {
|
||||||
|
createView(pv);
|
||||||
|
|
||||||
|
var dynamicComponent = view.locals.get("dynamic");
|
||||||
|
expect(dynamicComponent).toBeAnInstanceOf(DynamicComp);
|
||||||
|
|
||||||
|
dynamicComponent.done.then((_) => {
|
||||||
|
cd.detectChanges();
|
||||||
|
expect(view.nodes).toHaveText('hello');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (assertionsEnabled()) {
|
if (assertionsEnabled()) {
|
||||||
|
@ -572,6 +608,30 @@ export function main() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@DynamicComponent({
|
||||||
|
selector: 'dynamic-comp'
|
||||||
|
})
|
||||||
|
class DynamicComp {
|
||||||
|
done;
|
||||||
|
constructor(loader:PrivateComponentLoader, location:PrivateComponentLocation) {
|
||||||
|
this.done = loader.load(HelloCmp, location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hello-cmp'
|
||||||
|
})
|
||||||
|
@Template({
|
||||||
|
inline: "{{greeting}}"
|
||||||
|
})
|
||||||
|
class HelloCmp {
|
||||||
|
greeting:string;
|
||||||
|
constructor() {
|
||||||
|
this.greeting = "hello";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Decorator({
|
@Decorator({
|
||||||
selector: '[my-dir]',
|
selector: '[my-dir]',
|
||||||
bind: {'dirProp':'elprop'}
|
bind: {'dirProp':'elprop'}
|
||||||
|
|
Loading…
Reference in New Issue