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

@ -9,7 +9,7 @@
import '@angular/core/test/bundling/util/src/reflect_metadata';
import {CommonModule} from '@angular/common';
import {Component, Directive, ElementRef, HostBinding, NgModule, ɵPlayState as PlayState, ɵPlayer as Player, ɵPlayerHandler as PlayerHandler, ɵaddPlayer as addPlayer, ɵbindPlayerFactory as bindPlayerFactory, ɵmarkDirty as markDirty, ɵrenderComponent as renderComponent} from '@angular/core';
import {Component, Directive, ElementRef, HostBinding, HostListener, NgModule, ɵPlayState as PlayState, ɵPlayer as Player, ɵPlayerHandler as PlayerHandler, ɵaddPlayer as addPlayer, ɵbindPlayerFactory as bindPlayerFactory, ɵmarkDirty as markDirty, ɵrenderComponent as renderComponent} from '@angular/core';
@Directive({
selector: '[make-color-grey]',
@ -33,6 +33,36 @@ class MakeColorGreyDirective {
toggle() { this._backgroundColor ? this.off() : this.on(); }
}
@Component({selector: 'box-with-overridden-styles', template: '...'})
class BoxWithOverriddenStylesComponent {
public active = false;
@HostBinding('style')
styles = {};
constructor() { this.onInActive(); }
@HostListener('click', ['$event'])
toggle() {
if (this.active) {
this.onInActive();
} else {
this.onActive();
}
markDirty(this);
}
onActive() {
this.active = true;
this.styles = {height: '500px', 'font-size': '200px', background: 'red'};
}
onInActive() {
this.active = false;
this.styles = {width: '200px', height: '500px', border: '10px solid black', background: 'grey'};
}
}
@Component({
selector: 'animation-world',
template: `
@ -48,7 +78,7 @@ class MakeColorGreyDirective {
class="record"
[style.transform]="item.active ? 'scale(1.5)' : 'none'"
[class]="makeClass(item)"
style="border-radius: 10px"
style="border-radius: 10px"
[style]="styles"
[style.color]="item.value == 4 ? 'red' : null"
[style.background-color]="item.value == 4 ? 'white' : null"
@ -56,6 +86,13 @@ class MakeColorGreyDirective {
{{ item.value }}
</div>
</div>
<hr>
<box-with-overridden-styles
style="display:block"
[style]="{'border-radius':'50px', 'border': '50px solid teal'}" [ngStyle]="{transform:'rotate(50deg)'}">
</box-with-overridden-styles>
`,
})
class AnimationWorldComponent {
@ -93,8 +130,10 @@ class AnimationWorldComponent {
}
}
@NgModule(
{declarations: [AnimationWorldComponent, MakeColorGreyDirective], imports: [CommonModule]})
@NgModule({
declarations: [AnimationWorldComponent, MakeColorGreyDirective, BoxWithOverriddenStylesComponent],
imports: [CommonModule]
})
class AnimationWorldModule {
}

View File

@ -170,6 +170,9 @@
{
"name": "allocStylingContext"
},
{
"name": "allocateDirectiveIntoContext"
},
{
"name": "appendChild"
},
@ -335,6 +338,9 @@
{
"name": "getInitialClassNameValue"
},
{
"name": "getInitialStyleStringValue"
},
{
"name": "getInjectorIndex"
},
@ -407,6 +413,9 @@
{
"name": "hasParentInjector"
},
{
"name": "hasStyleInput"
},
{
"name": "hasStyling"
},
@ -555,7 +564,10 @@
"name": "renderEmbeddedTemplate"
},
{
"name": "renderInitialStylesAndClasses"
"name": "renderInitialClasses"
},
{
"name": "renderInitialStyles"
},
{
"name": "renderInitialStylingValues"

View File

@ -44,9 +44,6 @@
{
"name": "HOST"
},
{
"name": "T_HOST"
},
{
"name": "INJECTOR"
},
@ -107,6 +104,9 @@
{
"name": "TVIEW"
},
{
"name": "T_HOST"
},
{
"name": "UnsubscriptionErrorImpl"
},

View File

@ -362,9 +362,6 @@
{
"name": "_symbolIterator"
},
{
"name": "_updateSingleStylingValue"
},
{
"name": "addComponentLogic"
},
@ -386,6 +383,9 @@
{
"name": "allocStylingContext"
},
{
"name": "allocateDirectiveIntoContext"
},
{
"name": "allowValueChange"
},
@ -419,6 +419,9 @@
{
"name": "bloomHashBitOrFactory"
},
{
"name": "booleanOrNull"
},
{
"name": "cacheMatchingLocalNames"
},
@ -689,6 +692,9 @@
{
"name": "getInitialIndex"
},
{
"name": "getInitialStyleStringValue"
},
{
"name": "getInitialStylingValuesIndexOf"
},
@ -720,7 +726,7 @@
"name": "getMultiOrSingleIndex"
},
{
"name": "getMultiStartIndex"
"name": "getMultiStylesStartIndex"
},
{
"name": "getNativeAnchorNode"
@ -839,6 +845,9 @@
{
"name": "hasPlayerBuilderChanged"
},
{
"name": "hasStyleInput"
},
{
"name": "hasStyling"
},
@ -848,12 +857,21 @@
{
"name": "hasValueChanged"
},
{
"name": "hyphenate"
},
{
"name": "hyphenateEntries"
},
{
"name": "includeViewProviders"
},
{
"name": "increaseElementDepthCount"
},
{
"name": "initElementStyling"
},
{
"name": "initNodeFlags"
},
@ -965,9 +983,6 @@
{
"name": "leaveView"
},
{
"name": "limitToSingleClasses"
},
{
"name": "listener"
},
@ -1104,7 +1119,10 @@
"name": "renderEmbeddedTemplate"
},
{
"name": "renderInitialStylesAndClasses"
"name": "renderInitialClasses"
},
{
"name": "renderInitialStyles"
},
{
"name": "renderInitialStylingValues"
@ -1256,6 +1274,9 @@
{
"name": "updateContextWithBindings"
},
{
"name": "updateSingleStylingValue"
},
{
"name": "valueExists"
},