X Tutup
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions modules/angular2/src/core/compiler/template_parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ class TemplateParseVisitor implements HtmlAstVisitor {
parsedElement =
new NgContentAst(this.ngContentCount++, elementNgContentIndex, element.sourceInfo);
} else if (isTemplateElement) {
this._assertNoComponentsNorElementBindingsOnTemplate(directives, elementProps, events,
this._assertAllEventsPublishedByDirectives(directives, events, element.sourceInfo);
this._assertNoComponentsNorElementBindingsOnTemplate(directives, elementProps,
element.sourceInfo);
parsedElement = new EmbeddedTemplateAst(attrs, vars, directives, children,
elementNgContentIndex, element.sourceInfo);
Expand All @@ -231,7 +232,7 @@ class TemplateParseVisitor implements HtmlAstVisitor {
var templateElementProps: BoundElementPropertyAst[] = this._createElementPropertyAsts(
element.name, templateElementOrDirectiveProps, templateDirectives);
this._assertNoComponentsNorElementBindingsOnTemplate(templateDirectives, templateElementProps,
[], element.sourceInfo);
element.sourceInfo);
parsedElement = new EmbeddedTemplateAst([], templateVars, templateDirectives, [parsedElement],
component.findNgContentIndex(templateCssSelector),
element.sourceInfo);
Expand Down Expand Up @@ -559,7 +560,6 @@ class TemplateParseVisitor implements HtmlAstVisitor {

private _assertNoComponentsNorElementBindingsOnTemplate(directives: DirectiveAst[],
elementProps: BoundElementPropertyAst[],
events: BoundEventAst[],
sourceInfo: string) {
var componentTypeNames: string[] = this._findComponentDirectiveNames(directives);
if (componentTypeNames.length > 0) {
Expand All @@ -570,9 +570,20 @@ class TemplateParseVisitor implements HtmlAstVisitor {
this._reportError(
`Property binding ${prop.name} not used by any directive on an embedded template in ${prop.sourceInfo}`);
});
}

private _assertAllEventsPublishedByDirectives(directives: DirectiveAst[], events: BoundEventAst[],
sourceInfo: string) {
var allDirectiveEvents = new Set<string>();
directives.forEach(directive => {
StringMapWrapper.forEach(directive.directive.outputs,
(eventName, _) => { allDirectiveEvents.add(eventName); });
});
events.forEach(event => {
this._reportError(
`Event binding ${event.name} on an embedded template in ${event.sourceInfo}`);
if (isPresent(event.target) || !SetWrapper.has(allDirectiveEvents, event.name)) {
this._reportError(
`Event binding ${event.fullName} not emitted by any directive on an embedded template in ${sourceInfo}`);
}
});
}
}
Expand Down
19 changes: 16 additions & 3 deletions modules/angular2/test/core/compiler/template_parser_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,19 @@ export function main() {
]);
});

it('should allow events on explicit embedded templates that are emitted by a directive',
() => {
var dirA = CompileDirectiveMetadata.create({
selector: 'template',
outputs: ['e'],
type: new CompileTypeMetadata({name: 'DirA'})
});
expect(humanizeTemplateAsts(parse('<template (e)="f"></template>', [dirA])))
.toEqual([
[EmbeddedTemplateAst, 'TestComp > template:nth-child(0)'],
[DirectiveAst, dirA, 'TestComp > template:nth-child(0)'],
]);
});
});

describe('bindon', () => {
Expand Down Expand Up @@ -804,7 +817,7 @@ Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp > div:nth-ch
More than one component: DirB,DirA in TestComp > div:nth-child(0)`);
});

it('should not allow components or element nor event bindings on explicit embedded templates',
it('should not allow components or element bindings nor dom events on explicit embedded templates',
() => {
var dirA = CompileDirectiveMetadata.create({
selector: '[a]',
Expand All @@ -814,9 +827,9 @@ More than one component: DirB,DirA in TestComp > div:nth-child(0)`);
});
expect(() => parse('<template [a]="b" (e)="f"></template>', [dirA]))
.toThrowError(`Template parse errors:
Event binding e not emitted by any directive on an embedded template in TestComp > template:nth-child(0)
Components on an embedded template: DirA in TestComp > template:nth-child(0)
Property binding a not used by any directive on an embedded template in TestComp > template:nth-child(0)[[a]=b]
Event binding e on an embedded template in TestComp > template:nth-child(0)[(e)=f]`);
Property binding a not used by any directive on an embedded template in TestComp > template:nth-child(0)[[a]=b]`);
});

it('should not allow components or element bindings on inline embedded templates', () => {
Expand Down
27 changes: 26 additions & 1 deletion modules/angular2/test/core/linker/integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,7 @@ export function main() {
});
}));

it('should support events via EventEmitter',
it('should support events via EventEmitter on regular elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new ViewMetadata({
template: '<div emitter listener></div>',
Expand All @@ -825,6 +825,31 @@ export function main() {
});
}));

it('should support events via EventEmitter on template elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new ViewMetadata({
template: '<template emitter listener></template>',
directives: [DirectiveEmitingEvent, DirectiveListeningEvent]
}))

.createAsync(MyComp)
.then((rootTC) => {

var tc = rootTC.debugElement.componentViewChildren[0];
var emitter = tc.inject(DirectiveEmitingEvent);
var listener = tc.inject(DirectiveListeningEvent);

expect(listener.msg).toEqual('');

ObservableWrapper.subscribe(emitter.event, (_) => {
expect(listener.msg).toEqual('fired !');
async.done();
});

emitter.fireEvent('fired !');
});
}));

it('should support [()] syntax',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new ViewMetadata({
Expand Down
X Tutup