fix(ivy): ensure falsy styling is not applied during creation mode (#26793)
PR Close #26793
This commit is contained in:
@ -1161,8 +1161,9 @@ export function elementStyling(
|
||||
*/
|
||||
export function elementStylingApply(index: number): void {
|
||||
const viewData = getViewData();
|
||||
const totalPlayersQueued =
|
||||
renderStyleAndClassBindings(getStylingContext(index, viewData), getRenderer(), viewData);
|
||||
const isFirstRender = (viewData[FLAGS] & LViewFlags.CreationMode) !== 0;
|
||||
const totalPlayersQueued = renderStyleAndClassBindings(
|
||||
getStylingContext(index, viewData), getRenderer(), viewData, isFirstRender);
|
||||
if (totalPlayersQueued > 0) {
|
||||
const rootContext = getRootContext(viewData);
|
||||
scheduleTick(rootContext, RootContextFlags.FlushPlayers);
|
||||
|
@ -21,8 +21,8 @@ export interface Player {
|
||||
|
||||
export const enum BindingType {
|
||||
Unset = 0,
|
||||
Class = 2,
|
||||
Style = 3,
|
||||
Class = 1,
|
||||
Style = 2,
|
||||
}
|
||||
|
||||
export interface BindingStore { setValue(prop: string, value: any): void; }
|
||||
@ -35,7 +35,7 @@ export interface BindingStore { setValue(prop: string, value: any): void; }
|
||||
* to be used with `PlayerFactory`.
|
||||
*/
|
||||
export interface PlayerFactoryBuildFn {
|
||||
(element: HTMLElement, type: BindingType, values: {[key: string]: any},
|
||||
(element: HTMLElement, type: BindingType, values: {[key: string]: any}, isFirstRender: boolean,
|
||||
currentPlayer: Player|null): Player|null;
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ export interface PlayerFactoryBuildFn {
|
||||
export interface PlayerFactory { '__brand__': 'Brand for PlayerFactory that nothing will match'; }
|
||||
|
||||
export interface PlayerBuilder extends BindingStore {
|
||||
buildPlayer(currentPlayer: Player|null): Player|undefined|null;
|
||||
buildPlayer(currentPlayer: Player|null, isFirstRender: boolean): Player|undefined|null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -196,7 +196,7 @@ export const enum StylingFlags {
|
||||
// The max amount of bits used to represent these configuration values
|
||||
BitCountSize = 5,
|
||||
// There are only five bits here
|
||||
BitMask = 0b1111
|
||||
BitMask = 0b11111
|
||||
}
|
||||
|
||||
/** Used as numeric pointer values to determine what cells to update in the `StylingContext` */
|
||||
|
@ -480,8 +480,10 @@ export function updateClassProp(
|
||||
*/
|
||||
export function renderStyleAndClassBindings(
|
||||
context: StylingContext, renderer: Renderer3, rootOrView: RootContext | LViewData,
|
||||
classesStore?: BindingStore | null, stylesStore?: BindingStore | null): number {
|
||||
isFirstRender: boolean, classesStore?: BindingStore | null,
|
||||
stylesStore?: BindingStore | null): number {
|
||||
let totalPlayersQueued = 0;
|
||||
|
||||
if (isContextDirty(context)) {
|
||||
const flushPlayerBuilders: any =
|
||||
context[StylingIndex.MasterFlagPosition] & StylingFlags.PlayerBuildersDirty;
|
||||
@ -523,15 +525,23 @@ export function renderStyleAndClassBindings(
|
||||
valueToApply = getInitialValue(context, flag);
|
||||
}
|
||||
|
||||
if (isClassBased) {
|
||||
setClass(
|
||||
native, prop, valueToApply ? true : false, renderer, classesStore, playerBuilder);
|
||||
} else {
|
||||
const sanitizer = (flag & StylingFlags.Sanitize) ? styleSanitizer : null;
|
||||
setStyle(
|
||||
native, prop, valueToApply as string | null, renderer, sanitizer, stylesStore,
|
||||
playerBuilder);
|
||||
// if the first render is true then we do not want to start applying falsy
|
||||
// values to the DOM element's styling. Otherwise then we know there has
|
||||
// been a change and even if it's falsy then it's removing something that
|
||||
// was truthy before.
|
||||
const doApplyValue = isFirstRender ? valueToApply : true;
|
||||
if (doApplyValue) {
|
||||
if (isClassBased) {
|
||||
setClass(
|
||||
native, prop, valueToApply ? true : false, renderer, classesStore, playerBuilder);
|
||||
} else {
|
||||
const sanitizer = (flag & StylingFlags.Sanitize) ? styleSanitizer : null;
|
||||
setStyle(
|
||||
native, prop, valueToApply as string | null, renderer, sanitizer, stylesStore,
|
||||
playerBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
setDirty(context, i, false);
|
||||
}
|
||||
}
|
||||
@ -547,7 +557,7 @@ export function renderStyleAndClassBindings(
|
||||
const playerInsertionIndex = i + PlayerIndex.PlayerOffsetPosition;
|
||||
const oldPlayer = playerContext[playerInsertionIndex] as Player | null;
|
||||
if (builder) {
|
||||
const player = builder.buildPlayer(oldPlayer);
|
||||
const player = builder.buildPlayer(oldPlayer, isFirstRender);
|
||||
if (player !== undefined) {
|
||||
if (player != null) {
|
||||
const wasQueued = addPlayerInternal(
|
||||
@ -924,13 +934,13 @@ export class ClassAndStylePlayerBuilder<T> implements PlayerBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
buildPlayer(currentPlayer?: Player|null): Player|undefined|null {
|
||||
buildPlayer(currentPlayer: Player|null, isFirstRender: boolean): Player|undefined|null {
|
||||
// if no values have been set here then this means the binding didn't
|
||||
// change and therefore the binding values were not updated through
|
||||
// `setValue` which means no new player will be provided.
|
||||
if (this._dirty) {
|
||||
const player =
|
||||
this._factory.fn(this._element, this._type, this._values !, currentPlayer || null);
|
||||
const player = this._factory.fn(
|
||||
this._element, this._type, this._values !, isFirstRender, currentPlayer || null);
|
||||
this._values = {};
|
||||
this._dirty = false;
|
||||
return player;
|
||||
|
Reference in New Issue
Block a user