fix(ivy): setting up animation properties correctly (FW-643) (#27496)
Prior to this change, animation properties were defined as element attributes, which caused errors at runtime. Now all animation-related attributes are defined as element properties. Also as a part of this update, we start to account for bindings used in animations, which was previously missing. PR Close #27496
This commit is contained in:

committed by
Igor Minar

parent
4da739a970
commit
c71d7b5633
@ -39,7 +39,7 @@ import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector
|
||||
import {decreaseElementDepthCount, enterView, getBindingsEnabled, getCheckNoChangesMode, getContextLView, getCreationMode, getCurrentDirectiveDef, getElementDepthCount, getFirstTemplatePass, getIsParent, getLView, getPreviousOrParentTNode, increaseElementDepthCount, leaveView, nextContextImpl, resetComponentState, setBindingRoot, setCheckNoChangesMode, setCurrentDirectiveDef, setFirstTemplatePass, setIsParent, setPreviousOrParentTNode} from './state';
|
||||
import {createStylingContextTemplate, renderStyleAndClassBindings, setStyle, updateClassProp as updateElementClassProp, updateStyleProp as updateElementStyleProp, updateStylingMap} from './styling/class_and_style_bindings';
|
||||
import {BoundPlayerFactory} from './styling/player_factory';
|
||||
import {getStylingContext} from './styling/util';
|
||||
import {getStylingContext, isAnimationProp} from './styling/util';
|
||||
import {NO_CHANGE} from './tokens';
|
||||
import {getComponentViewByIndex, getNativeByIndex, getNativeByTNode, getRootContext, getRootView, getTNode, isComponent, isComponentDef, loadInternal, readElementValue, readPatchedLView, stringify} from './util';
|
||||
|
||||
@ -745,10 +745,16 @@ function setUpAttributes(native: RElement, attrs: TAttributes): void {
|
||||
} else {
|
||||
// Standard attributes
|
||||
const attrVal = attrs[i + 1];
|
||||
isProc ?
|
||||
(renderer as ProceduralRenderer3)
|
||||
.setAttribute(native, attrName as string, attrVal as string) :
|
||||
native.setAttribute(attrName as string, attrVal as string);
|
||||
if (isAnimationProp(attrName)) {
|
||||
if (isProc) {
|
||||
(renderer as ProceduralRenderer3).setProperty(native, attrName, attrVal);
|
||||
}
|
||||
} else {
|
||||
isProc ?
|
||||
(renderer as ProceduralRenderer3)
|
||||
.setAttribute(native, attrName as string, attrVal as string) :
|
||||
native.setAttribute(attrName as string, attrVal as string);
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
@ -967,10 +973,12 @@ export function elementProperty<T>(
|
||||
// is risky, so sanitization can be done without further checks.
|
||||
value = sanitizer != null ? (sanitizer(value) as any) : value;
|
||||
ngDevMode && ngDevMode.rendererSetProperty++;
|
||||
isProceduralRenderer(renderer) ?
|
||||
renderer.setProperty(element as RElement, propName, value) :
|
||||
((element as RElement).setProperty ? (element as any).setProperty(propName, value) :
|
||||
(element as any)[propName] = value);
|
||||
if (isProceduralRenderer(renderer)) {
|
||||
renderer.setProperty(element as RElement, propName, value);
|
||||
} else if (!isAnimationProp(propName)) {
|
||||
(element as RElement).setProperty ? (element as any).setProperty(propName, value) :
|
||||
(element as any)[propName] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,8 @@ import {getTNode} from '../util';
|
||||
|
||||
import {CorePlayerHandler} from './core_player_handler';
|
||||
|
||||
const ANIMATION_PROP_PREFIX = '@';
|
||||
|
||||
export function createEmptyStylingContext(
|
||||
element?: RElement | null, sanitizer?: StyleSanitizeFn | null,
|
||||
initialStylingValues?: InitialStyles): StylingContext {
|
||||
@ -91,6 +93,10 @@ export function isStylingContext(value: any): value is StylingContext {
|
||||
typeof value[ACTIVE_INDEX] !== 'number';
|
||||
}
|
||||
|
||||
export function isAnimationProp(name: string): boolean {
|
||||
return name[0] === ANIMATION_PROP_PREFIX;
|
||||
}
|
||||
|
||||
export function addPlayerInternal(
|
||||
playerContext: PlayerContext, rootContext: RootContext, element: HTMLElement,
|
||||
player: Player | null, playerContextIndex: number, ref?: any): boolean {
|
||||
|
@ -2,6 +2,9 @@
|
||||
{
|
||||
"name": "ACTIVE_INDEX"
|
||||
},
|
||||
{
|
||||
"name": "ANIMATION_PROP_PREFIX"
|
||||
},
|
||||
{
|
||||
"name": "BINDING_INDEX"
|
||||
},
|
||||
@ -344,6 +347,9 @@
|
||||
{
|
||||
"name": "invertObject"
|
||||
},
|
||||
{
|
||||
"name": "isAnimationProp"
|
||||
},
|
||||
{
|
||||
"name": "isComponentDef"
|
||||
},
|
||||
|
@ -2,6 +2,9 @@
|
||||
{
|
||||
"name": "ACTIVE_INDEX"
|
||||
},
|
||||
{
|
||||
"name": "ANIMATION_PROP_PREFIX"
|
||||
},
|
||||
{
|
||||
"name": "BINDING_INDEX"
|
||||
},
|
||||
@ -875,6 +878,9 @@
|
||||
{
|
||||
"name": "invokeDirectivesHostBindings"
|
||||
},
|
||||
{
|
||||
"name": "isAnimationProp"
|
||||
},
|
||||
{
|
||||
"name": "isComponent"
|
||||
},
|
||||
|
@ -1784,7 +1784,7 @@ describe('render3 integration test', () => {
|
||||
consts: 0,
|
||||
vars: 0,
|
||||
data: {
|
||||
animations: [
|
||||
animation: [
|
||||
animA,
|
||||
animB,
|
||||
],
|
||||
@ -1797,7 +1797,7 @@ describe('render3 integration test', () => {
|
||||
const rendererFactory = new ProxyRenderer3Factory();
|
||||
new ComponentFixture(AnimComp, {rendererFactory});
|
||||
|
||||
const capturedAnimations = rendererFactory.lastCapturedType !.data !['animations'];
|
||||
const capturedAnimations = rendererFactory.lastCapturedType !.data !['animation'];
|
||||
expect(Array.isArray(capturedAnimations)).toBeTruthy();
|
||||
expect(capturedAnimations.length).toEqual(2);
|
||||
expect(capturedAnimations).toContain(animA);
|
||||
@ -1811,7 +1811,7 @@ describe('render3 integration test', () => {
|
||||
consts: 0,
|
||||
vars: 0,
|
||||
data: {
|
||||
animations: [],
|
||||
animation: [],
|
||||
},
|
||||
selectors: [['foo']],
|
||||
factory: () => new AnimComp(),
|
||||
@ -1821,7 +1821,7 @@ describe('render3 integration test', () => {
|
||||
const rendererFactory = new ProxyRenderer3Factory();
|
||||
new ComponentFixture(AnimComp, {rendererFactory});
|
||||
const data = rendererFactory.lastCapturedType !.data;
|
||||
expect(data.animations).toEqual([]);
|
||||
expect(data.animation).toEqual([]);
|
||||
});
|
||||
|
||||
it('should allow [@trigger] bindings to be picked up by the underlying renderer', () => {
|
||||
@ -1876,13 +1876,13 @@ describe('render3 integration test', () => {
|
||||
});
|
||||
}
|
||||
|
||||
const rendererFactory = new MockRendererFactory(['setAttribute']);
|
||||
const rendererFactory = new MockRendererFactory(['setProperty']);
|
||||
const fixture = new ComponentFixture(AnimComp, {rendererFactory});
|
||||
|
||||
const renderer = rendererFactory.lastRenderer !;
|
||||
fixture.update();
|
||||
|
||||
const spy = renderer.spies['setAttribute'];
|
||||
const spy = renderer.spies['setProperty'];
|
||||
const [elm, attr, value] = spy.calls.mostRecent().args;
|
||||
expect(attr).toEqual('@fooAnimation');
|
||||
});
|
||||
|
Reference in New Issue
Block a user