fix(ivy): Add style="{{exp}}" based interpolation (#34202)

Fixes #33575

Add support for interpolation in styles as shown:
```
<div style="color: {{exp1}}; width: {{exp2}};">
```

PR Close #34202
This commit is contained in:
Miško Hevery
2019-11-27 16:57:14 -08:00
parent 66c06eb1ad
commit 2562a3b1b0
16 changed files with 689 additions and 72 deletions

View File

@ -71,6 +71,25 @@ export class Identifiers {
static styleMap: o.ExternalReference = {name: 'ɵɵstyleMap', moduleName: CORE};
static styleMapInterpolate1:
o.ExternalReference = {name: 'ɵɵstyleMapInterpolate1', moduleName: CORE};
static styleMapInterpolate2:
o.ExternalReference = {name: 'ɵɵstyleMapInterpolate2', moduleName: CORE};
static styleMapInterpolate3:
o.ExternalReference = {name: 'ɵɵstyleMapInterpolate3', moduleName: CORE};
static styleMapInterpolate4:
o.ExternalReference = {name: 'ɵɵstyleMapInterpolate4', moduleName: CORE};
static styleMapInterpolate5:
o.ExternalReference = {name: 'ɵɵstyleMapInterpolate5', moduleName: CORE};
static styleMapInterpolate6:
o.ExternalReference = {name: 'ɵɵstyleMapInterpolate6', moduleName: CORE};
static styleMapInterpolate7:
o.ExternalReference = {name: 'ɵɵstyleMapInterpolate7', moduleName: CORE};
static styleMapInterpolate8:
o.ExternalReference = {name: 'ɵɵstyleMapInterpolate8', moduleName: CORE};
static styleMapInterpolateV:
o.ExternalReference = {name: 'ɵɵstyleMapInterpolateV', moduleName: CORE};
static classMap: o.ExternalReference = {name: 'ɵɵclassMap', moduleName: CORE};
static classMapInterpolate1:

View File

@ -81,7 +81,7 @@ export interface StylingInstruction {
export interface StylingInstructionCall {
sourceSpan: ParseSourceSpan|null;
supportsInterpolation?: boolean;
supportsInterpolation: boolean;
allocateBindingSlots: number;
params: ((convertFn: (value: any) => o.Expression | o.Expression[]) => o.Expression[]);
}
@ -372,9 +372,10 @@ export class StylingBuilder {
// pipes can be picked up in time before the template is built
const mapValue = stylingInput.value.visit(valueConverter);
let reference: o.ExternalReference;
if (mapValue instanceof Interpolation && isClassBased) {
if (mapValue instanceof Interpolation) {
totalBindingSlotsRequired += mapValue.expressions.length;
reference = getClassMapInterpolationExpression(mapValue);
reference = isClassBased ? getClassMapInterpolationExpression(mapValue) :
getStyleMapInterpolationExpression(mapValue);
} else {
reference = isClassBased ? R3.classMap : R3.styleMap;
}
@ -382,18 +383,12 @@ export class StylingBuilder {
return {
reference,
calls: [{
supportsInterpolation: isClassBased,
supportsInterpolation: true,
sourceSpan: stylingInput.sourceSpan,
allocateBindingSlots: totalBindingSlotsRequired,
params: (convertFn: (value: any) => o.Expression | o.Expression[]) => {
const convertResult = convertFn(mapValue);
const params = Array.isArray(convertResult) ? convertResult : [convertResult];
// [style] instructions will sanitize all their values. For this reason we
// need to include the sanitizer as a param.
if (!isClassBased) {
params.push(o.importExpr(R3.defaultStyleSanitizer));
}
return params;
}
}]
@ -588,6 +583,35 @@ function getClassMapInterpolationExpression(interpolation: Interpolation): o.Ext
}
}
/**
* Gets the instruction to generate for an interpolated style map.
* @param interpolation An Interpolation AST
*/
function getStyleMapInterpolationExpression(interpolation: Interpolation): o.ExternalReference {
switch (getInterpolationArgsLength(interpolation)) {
case 1:
return R3.styleMap;
case 3:
return R3.styleMapInterpolate1;
case 5:
return R3.styleMapInterpolate2;
case 7:
return R3.styleMapInterpolate3;
case 9:
return R3.styleMapInterpolate4;
case 11:
return R3.styleMapInterpolate5;
case 13:
return R3.styleMapInterpolate6;
case 15:
return R3.styleMapInterpolate7;
case 17:
return R3.styleMapInterpolate8;
default:
return R3.styleMapInterpolateV;
}
}
/**
* Gets the instruction to generate for an interpolated style prop.
* @param interpolation An Interpolation AST