fix(compiler): changed the compiler to set up event listeners and host properties on host view elements

Closes #1584
This commit is contained in:
vsavkin
2015-04-27 15:14:30 -07:00
committed by Misko Hevery
parent 414e58edb5
commit e3c11045bf
14 changed files with 187 additions and 93 deletions

View File

@ -90,7 +90,9 @@ export class Compiler {
compileInHost(componentTypeOrBinding:any):Promise<AppProtoView> {
var componentBinding = this._bindDirective(componentTypeOrBinding);
this._assertTypeIsComponent(componentBinding);
return this._renderer.createHostProtoView('host').then( (hostRenderPv) => {
var directiveMetadata = Compiler.buildRenderDirective(componentBinding);
return this._renderer.createHostProtoView(directiveMetadata).then( (hostRenderPv) => {
return this._compileNestedProtoViews(null, hostRenderPv, [componentBinding], true);
});
}

View File

@ -2,8 +2,9 @@ import {Injectable} from 'angular2/di';
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
import {BaseException} from 'angular2/src/facade/lang';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {ViewDefinition, ProtoViewDto} from '../../api';
import {ViewDefinition, ProtoViewDto, DirectiveMetadata} from '../../api';
import {CompilePipeline} from './compile_pipeline';
import {TemplateLoader} from 'angular2/src/render/dom/compiler/template_loader';
import {CompileStepFactory, DefaultStepFactory} from './compile_step_factory';
@ -32,12 +33,21 @@ export class Compiler {
);
}
_compileTemplate(template: ViewDefinition, tplElement):Promise<ProtoViewDto> {
var subTaskPromises = [];
var pipeline = new CompilePipeline(this._stepFactory.createSteps(template, subTaskPromises));
var compileElements;
compileHost(directiveMetadata: DirectiveMetadata):Promise<ProtoViewDto> {
var hostViewDef = new ViewDefinition({
componentId: directiveMetadata.id,
absUrl: null,
template: null,
directives: [directiveMetadata]
});
var element = DOM.createElement(directiveMetadata.selector);
return this._compileTemplate(hostViewDef, element);
}
compileElements = pipeline.process(tplElement, template.componentId);
_compileTemplate(viewDef: ViewDefinition, tplElement):Promise<ProtoViewDto> {
var subTaskPromises = [];
var pipeline = new CompilePipeline(this._stepFactory.createSteps(viewDef, subTaskPromises));
var compileElements = pipeline.process(tplElement, viewDef.componentId);
var protoView = compileElements[0].inheritedProtoView.build();

View File

@ -27,11 +27,20 @@ export class DirectiveParser extends CompileStep {
this._selectorMatcher = new SelectorMatcher();
this._directives = directives;
for (var i=0; i<directives.length; i++) {
var selector = CssSelector.parse(directives[i].selector);
var directive = directives[i];
var selector = CssSelector.parse(directive.selector);
this._ensureComponentOnlyHasElementSelector(selector, directive);
this._selectorMatcher.addSelectables(selector, i);
}
}
_ensureComponentOnlyHasElementSelector(selector, directive) {
var isElementSelector = selector.length === 1 && selector[0].isElementSelector();
if (! isElementSelector && directive.type === DirectiveMetadata.COMPONENT_TYPE) {
throw new BaseException(`Component '${directive.id}' can only have an element selector, but had '${directive.selector}'`);
}
}
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
var attrs = current.attrs();
var classList = current.classList();

View File

@ -69,6 +69,13 @@ export class CssSelector {
this.notSelector = null;
}
isElementSelector():boolean {
return isPresent(this.element) &&
ListWrapper.isEmpty(this.classNames) &&
ListWrapper.isEmpty(this.attrs) &&
isBlank(this.notSelector);
}
setElement(element:string = null) {
if (isPresent(element)) {
element = element.toLowerCase();

View File

@ -11,7 +11,6 @@ import {RenderViewHydrator} from './view/view_hydrator';
import {Compiler} from './compiler/compiler';
import {ShadowDomStrategy} from './shadow_dom/shadow_dom_strategy';
import {ProtoViewBuilder} from './view/proto_view_builder';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {ViewContainer} from './view/view_container';
function _resolveViewContainer(vc:api.RenderViewContainerRef) {
@ -80,15 +79,8 @@ export class DirectDomRenderer extends api.Renderer {
this._shadowDomStrategy = shadowDomStrategy;
}
createHostProtoView(componentId):Promise<api.ProtoViewDto> {
var rootElement = DOM.createElement('div');
var hostProtoViewBuilder = new ProtoViewBuilder(rootElement);
var elBinder = hostProtoViewBuilder.bindElement(rootElement, 'root element');
elBinder.setComponentId(componentId);
elBinder.bindDirective(0);
this._shadowDomStrategy.processElement(null, componentId, rootElement);
return PromiseWrapper.resolve(hostProtoViewBuilder.build());
createHostProtoView(directiveMetadata:api.DirectiveMetadata):Promise<api.ProtoViewDto> {
return this._compiler.compileHost(directiveMetadata);
}
createImperativeComponentProtoView(rendererId):Promise<api.ProtoViewDto> {
@ -97,10 +89,10 @@ export class DirectDomRenderer extends api.Renderer {
return PromiseWrapper.resolve(protoViewBuilder.build());
}
compile(template:api.ViewDefinition):Promise<api.ProtoViewDto> {
compile(view:api.ViewDefinition):Promise<api.ProtoViewDto> {
// Note: compiler already uses a DirectDomProtoViewRef, so we don't
// need to do anything here
return this._compiler.compile(template);
return this._compiler.compile(view);
}
mergeChildComponentProtoViews(protoViewRef:api.ProtoViewRef, protoViewRefs:List<api.ProtoViewRef>) {