fix(compiler): Allow components to use any style of selector. Fixes #1602

This commit is contained in:
Jeremy Elbourn
2015-07-28 11:38:40 -07:00
parent 4422819754
commit c20a5d65d8
6 changed files with 67 additions and 20 deletions

View File

@ -20,6 +20,7 @@ import {CompileStepFactory, DefaultStepFactory} from './compile_step_factory';
import {ElementSchemaRegistry} from '../schema/element_schema_registry';
import {Parser} from 'angular2/src/change_detection/change_detection';
import * as pvm from '../view/proto_view_merger';
import {CssSelector} from './selector';
import {DOCUMENT_TOKEN, APP_ID_TOKEN} from '../dom_tokens';
import {Inject} from 'angular2/di';
import {SharedStylesHost} from '../view/shared_styles_host';
@ -50,7 +51,7 @@ export class DomCompiler extends RenderCompiler {
}
compileHost(directiveMetadata: DirectiveMetadata): Promise<ProtoViewDto> {
var hostViewDef = new ViewDefinition({
let hostViewDef = new ViewDefinition({
componentId: directiveMetadata.id,
templateAbsUrl: null, template: null,
styles: null,
@ -58,10 +59,12 @@ export class DomCompiler extends RenderCompiler {
directives: [directiveMetadata],
encapsulation: ViewEncapsulation.NONE
});
return this._compileView(
hostViewDef, new TemplateAndStyles(
`<${directiveMetadata.selector}></${directiveMetadata.selector}>`, []),
ViewType.HOST);
let selector = CssSelector.parse(directiveMetadata.selector)[0];
let hostTemplate = selector.getMatchingElementTemplate();
let templateAndStyles = new TemplateAndStyles(hostTemplate, []);
return this._compileView(hostViewDef, templateAndStyles, ViewType.HOST);
}
mergeProtoViewsRecursively(

View File

@ -24,21 +24,12 @@ export class DirectiveParser implements CompileStep {
for (var i = 0; i < _directives.length; i++) {
var directive = _directives[i];
var selector = CssSelector.parse(directive.selector);
this._ensureComponentOnlyHasElementSelector(selector, directive);
this._selectorMatcher.addSelectables(selector, i);
}
}
processStyle(style: string): string { return style; }
_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}'`);
}
}
processElement(parent: CompileElement, current: CompileElement, control: CompileControl) {
var attrs = current.attrs();
var classList = current.classList();

View File

@ -91,6 +91,21 @@ export class CssSelector {
this.element = element;
}
/** Gets a template string for an element that matches the selector. */
getMatchingElementTemplate(): string {
let tagName = isPresent(this.element) ? this.element : 'div';
let classAttr = this.classNames.length > 0 ? ` class="${this.classNames.join(' ')}"` : '';
let attrs = '';
for (let i = 0; i < this.attrs.length; i += 2) {
let attrName = this.attrs[i];
let attrValue = this.attrs[i + 1] !== '' ? `="${this.attrs[i + 1]}"` : '';
attrs += ` ${attrName}${attrValue}`;
}
return `<${tagName}${classAttr}${attrs}></${tagName}>`;
}
addAttribute(name: string, value: string = _EMPTY_ATTR_VALUE) {
this.attrs.push(name.toLowerCase());
if (isPresent(value)) {