fix(ivy): support directive outputs on ng-template (#25717)

Compiler part of #25698
Fixes #25697

PR Close #25717
This commit is contained in:
Pawel Kozlowski
2018-08-29 12:26:24 +02:00
committed by Misko Hevery
parent 34be51898d
commit 6def18a95e
3 changed files with 75 additions and 23 deletions

View File

@ -516,28 +516,9 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
// Generate Listeners (outputs)
element.outputs.forEach((outputAst: t.BoundEvent) => {
const elName = sanitizeIdentifier(element.name);
const evName = sanitizeIdentifier(outputAst.name);
const functionName = `${this.templateName}_${elName}_${evName}_listener`;
this.creationInstruction(outputAst.sourceSpan, R3.listener, () => {
const listenerScope = this._bindingScope.nestedScope(this._bindingScope.bindingLevel);
const bindingExpr = convertActionBinding(
listenerScope, implicit, outputAst.handler, 'b',
() => error('Unexpected interpolation'));
const statements = [
...listenerScope.restoreViewStatement(), ...listenerScope.variableDeclarations(),
...bindingExpr.render3Stmts
];
const handler = o.fn(
[new o.FnParam('$event', o.DYNAMIC_TYPE)], statements, o.INFERRED_TYPE, null,
functionName);
return [o.literal(outputAst.name), handler];
});
this.creationInstruction(
outputAst.sourceSpan, R3.listener,
this.prepareListenerParameter(element.name, outputAst));
});
}
@ -736,6 +717,13 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
o.literal(templateVisitor.getVarCount()));
return trimTrailingNulls(parameters);
});
// Generate listeners for directive output
template.outputs.forEach((outputAst: t.BoundEvent) => {
this.creationInstruction(
outputAst.sourceSpan, R3.listener,
this.prepareListenerParameter('ng_template', outputAst));
});
}
// These should be handled in the template or element directly.
@ -906,6 +894,31 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
return this.constantPool.getConstLiteral(asLiteral(refsParam), true);
}
private prepareListenerParameter(tagName: string, outputAst: t.BoundEvent): () => o.Expression[] {
const evName = sanitizeIdentifier(outputAst.name);
const functionName = `${this.templateName}_${tagName}_${evName}_listener`;
return () => {
const listenerScope = this._bindingScope.nestedScope(this._bindingScope.bindingLevel);
const bindingExpr = convertActionBinding(
listenerScope, o.variable(CONTEXT_NAME), outputAst.handler, 'b',
() => error('Unexpected interpolation'));
const statements = [
...listenerScope.restoreViewStatement(), ...listenerScope.variableDeclarations(),
...bindingExpr.render3Stmts
];
const handler = o.fn(
[new o.FnParam('$event', o.DYNAMIC_TYPE)], statements, o.INFERRED_TYPE, null,
functionName);
return [o.literal(outputAst.name), handler];
};
}
}
export class ValueConverter extends AstMemoryEfficientTransformer {