feat(ivy): provide support for map-based host bindings for [style] and [class] (#28246)

Up until now, `[style]` and `[class]` bindings (the map-based ones) have only
worked as template bindings and have not been supported at all inside of host
bindings. This patch ensures that multiple host binding sources (components and
directives) all properly assign style values and merge them correctly in terms
of priority.

Jira: FW-882

PR Close #28246
This commit is contained in:
Matias Niemelä
2019-02-08 15:03:54 -08:00
committed by Miško Hevery
parent e5861e1c79
commit fe8301c462
16 changed files with 3104 additions and 1714 deletions

View File

@ -1062,6 +1062,84 @@ describe('compiler compliance: styling', () => {
expectEmit(result.source, template, 'Incorrect template');
});
it('should generate override instructions for only single-level styling bindings when !important is present',
() => {
const files = {
app: {
'spec.ts': `
import {Component, NgModule, HostBinding} from '@angular/core';
@Component({
selector: 'my-component',
template: \`
<div [style!important]="myStyleExp"
[class!important]="myClassExp"
[style.height!important]="myHeightExp"
[class.bar!important]="myBarClassExp"></div>
\`,
host: {
'[style!important]': 'myStyleExp',
'[class!important]': 'myClassExp'
}
})
export class MyComponent {
@HostBinding('class.foo!important')
myFooClassExp = true;
@HostBinding('style.width!important')
myWidthExp = '100px';
myBarClassExp = true;
myHeightExp = '200px';
}
@NgModule({declarations: [MyComponent]})
export class MyModule {}
`
}
};
const template = `
const _c2 = ["bar"];
const _c3 = ["height"];
function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵelementStart(0, "div");
$r3$.ɵelementStyling(_c2, _c3, $r3$.ɵdefaultStyleSanitizer);
$r3$.ɵelementEnd();
}
if (rf & 2) {
$r3$.ɵelementStylingMap(0, ctx.myClassExp, ctx.myStyleExp);
$r3$.ɵelementStyleProp(0, 0, ctx.myHeightExp, null, true);
$r3$.ɵelementClassProp(0, 0, ctx.myBarClassExp, null, true);
$r3$.ɵelementStylingApply(0);
}
},
`;
const hostBindings = `
const _c0 = ["foo"];
const _c1 = ["width"];
hostBindings: function MyComponent_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
$r3$.ɵelementStyling(_c0, _c1, $r3$.ɵdefaultStyleSanitizer, ctx);
}
if (rf & 2) {
$r3$.ɵelementStylingMap(elIndex, ctx.myClassExp, ctx.myStyleExp, ctx);
$r3$.ɵelementStyleProp(elIndex, 0, ctx.myWidthExp, null, ctx, true);
$r3$.ɵelementClassProp(elIndex, 0, ctx.myFooClassExp, ctx, true);
$r3$.ɵelementStylingApply(elIndex, ctx);
}
},
`;
const result = compile(files, angularFiles);
expectEmit(result.source, hostBindings, 'Incorrect template');
expectEmit(result.source, template, 'Incorrect template');
});
it('should generate styling instructions for multiple directives that contain host binding definitions',
() => {
const files = {