fix(compiler): support events on a template element that are consumed via a direct expression
Closes #4883
This commit is contained in:
parent
56a9b020d4
commit
3118d5cebb
|
@ -58,6 +58,7 @@ class ProtoViewVisitor implements TemplateAstVisitor {
|
|||
|
||||
visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any {
|
||||
this.boundElementCount++;
|
||||
templateVisitAll(this, ast.outputs);
|
||||
for (var i = 0; i < ast.directives.length; i++) {
|
||||
ast.directives[i].visit(this, i);
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ export class ElementAst implements TemplateAst {
|
|||
}
|
||||
|
||||
export class EmbeddedTemplateAst implements TemplateAst {
|
||||
constructor(public attrs: AttrAst[], public vars: VariableAst[],
|
||||
constructor(public attrs: AttrAst[], public outputs: BoundEventAst[], public vars: VariableAst[],
|
||||
public directives: DirectiveAst[], public children: TemplateAst[],
|
||||
public ngContentIndex: number, public sourceInfo: string) {}
|
||||
visit(visitor: TemplateAstVisitor, context: any): any {
|
||||
|
|
|
@ -223,7 +223,7 @@ class TemplateParseVisitor implements HtmlAstVisitor {
|
|||
this._assertAllEventsPublishedByDirectives(directives, events, element.sourceInfo);
|
||||
this._assertNoComponentsNorElementBindingsOnTemplate(directives, elementProps,
|
||||
element.sourceInfo);
|
||||
parsedElement = new EmbeddedTemplateAst(attrs, vars, directives, children,
|
||||
parsedElement = new EmbeddedTemplateAst(attrs, events, vars, directives, children,
|
||||
elementNgContentIndex, element.sourceInfo);
|
||||
} else {
|
||||
this._assertOnlyOneComponent(directives, element.sourceInfo);
|
||||
|
@ -241,9 +241,9 @@ class TemplateParseVisitor implements HtmlAstVisitor {
|
|||
element.name, templateElementOrDirectiveProps, templateDirectives);
|
||||
this._assertNoComponentsNorElementBindingsOnTemplate(templateDirectives, templateElementProps,
|
||||
element.sourceInfo);
|
||||
parsedElement = new EmbeddedTemplateAst([], templateVars, templateDirectives, [parsedElement],
|
||||
component.findNgContentIndex(templateCssSelector),
|
||||
element.sourceInfo);
|
||||
parsedElement = new EmbeddedTemplateAst(
|
||||
[], [], templateVars, templateDirectives, [parsedElement],
|
||||
component.findNgContentIndex(templateCssSelector), element.sourceInfo);
|
||||
}
|
||||
return parsedElement;
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ export function main() {
|
|||
expect(dispatcher.log).toEqual(['textNode(null)=someValue']);
|
||||
});
|
||||
|
||||
it('should handle events', () => {
|
||||
it('should handle events on regular elements', () => {
|
||||
var changeDetector = createChangeDetector('<div on-click="onEvent($event)">', [], 0);
|
||||
|
||||
eventLocals.set('$event', 'click');
|
||||
|
@ -98,6 +98,20 @@ export function main() {
|
|||
expect(context.eventLog).toEqual(['click']);
|
||||
});
|
||||
|
||||
it('should handle events on template elements', () => {
|
||||
var dirMeta = CompileDirectiveMetadata.create({
|
||||
type: new CompileTypeMetadata({name: 'SomeDir'}),
|
||||
selector: 'template',
|
||||
outputs: ['click']
|
||||
});
|
||||
var changeDetector =
|
||||
createChangeDetector('<template on-click="onEvent($event)">', [dirMeta], 0);
|
||||
|
||||
eventLocals.set('$event', 'click');
|
||||
changeDetector.handleEvent('click', 0, eventLocals);
|
||||
expect(context.eventLog).toEqual(['click']);
|
||||
});
|
||||
|
||||
it('should handle events with targets', () => {
|
||||
var changeDetector = createChangeDetector('<div (window:click)="onEvent($event)">', [], 0);
|
||||
|
||||
|
|
|
@ -277,6 +277,7 @@ export function main() {
|
|||
expect(humanizeTemplateAsts(parse('<template (e)="f"></template>', [dirA])))
|
||||
.toEqual([
|
||||
[EmbeddedTemplateAst, 'TestComp > template:nth-child(0)'],
|
||||
[BoundEventAst, 'e', null, 'f', 'TestComp > template:nth-child(0)[(e)=f]'],
|
||||
[DirectiveAst, dirA, 'TestComp > template:nth-child(0)'],
|
||||
]);
|
||||
});
|
||||
|
@ -978,6 +979,7 @@ class TemplateHumanizer implements TemplateAstVisitor {
|
|||
visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any {
|
||||
this.result.push([EmbeddedTemplateAst, ast.sourceInfo]);
|
||||
templateVisitAll(this, ast.attrs);
|
||||
templateVisitAll(this, ast.outputs);
|
||||
templateVisitAll(this, ast.vars);
|
||||
templateVisitAll(this, ast.directives);
|
||||
templateVisitAll(this, ast.children);
|
||||
|
|
|
@ -827,22 +827,26 @@ 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]
|
||||
}))
|
||||
tcb.overrideView(
|
||||
MyComp, new ViewMetadata({
|
||||
template: '<template emitter listener (event)="ctxProp=$event"></template>',
|
||||
directives: [DirectiveEmitingEvent, DirectiveListeningEvent]
|
||||
}))
|
||||
|
||||
.createAsync(MyComp)
|
||||
.then((rootTC) => {
|
||||
|
||||
var tc = rootTC.debugElement.componentViewChildren[0];
|
||||
var emitter = tc.inject(DirectiveEmitingEvent);
|
||||
var myComp = tc.inject(MyComp);
|
||||
var listener = tc.inject(DirectiveListeningEvent);
|
||||
|
||||
myComp.ctxProp = '';
|
||||
expect(listener.msg).toEqual('');
|
||||
|
||||
ObservableWrapper.subscribe(emitter.event, (_) => {
|
||||
expect(listener.msg).toEqual('fired !');
|
||||
expect(myComp.ctxProp).toEqual('fired !');
|
||||
async.done();
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue