fix(core): trigger host animations for elements that are removed. (#15251)
Fixes #14813 Fixes #15193
This commit is contained in:
parent
28ce68a13d
commit
0d3e314df0
|
@ -1030,9 +1030,9 @@ function elementBindingDef(inputAst: BoundElementPropertyAst, dirAst: DirectiveA
|
||||||
o.literal(inputAst.securityContext)
|
o.literal(inputAst.securityContext)
|
||||||
]);
|
]);
|
||||||
case PropertyBindingType.Animation:
|
case PropertyBindingType.Animation:
|
||||||
const bindingType = dirAst && dirAst.directive.isComponent ?
|
const bindingType = BindingFlags.TypeProperty |
|
||||||
BindingFlags.TypeProperty | BindingFlags.SyntheticComponentHostProperty :
|
(dirAst && dirAst.directive.isComponent ? BindingFlags.SyntheticHostProperty :
|
||||||
BindingFlags.TypeProperty;
|
BindingFlags.SyntheticProperty);
|
||||||
return o.literalArr([
|
return o.literalArr([
|
||||||
o.literal(bindingType), o.literal('@' + inputAst.name), o.literal(inputAst.securityContext)
|
o.literal(bindingType), o.literal('@' + inputAst.name), o.literal(inputAst.securityContext)
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -238,8 +238,10 @@ function checkAndUpdateElementValue(view: ViewData, def: NodeDef, bindingIdx: nu
|
||||||
setElementStyle(view, binding, renderNode, name, value);
|
setElementStyle(view, binding, renderNode, name, value);
|
||||||
break;
|
break;
|
||||||
case BindingFlags.TypeProperty:
|
case BindingFlags.TypeProperty:
|
||||||
const bindView =
|
const bindView = (def.flags & NodeFlags.ComponentView &&
|
||||||
binding.flags & BindingFlags.SyntheticComponentHostProperty ? elData.componentView : view;
|
binding.flags & BindingFlags.SyntheticHostProperty) ?
|
||||||
|
elData.componentView :
|
||||||
|
view;
|
||||||
setElementProperty(bindView, binding, renderNode, name, value);
|
setElementProperty(bindView, binding, renderNode, name, value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,7 +195,9 @@ export const enum BindingFlags {
|
||||||
TypeElementClass = 1 << 1,
|
TypeElementClass = 1 << 1,
|
||||||
TypeElementStyle = 1 << 2,
|
TypeElementStyle = 1 << 2,
|
||||||
TypeProperty = 1 << 3,
|
TypeProperty = 1 << 3,
|
||||||
SyntheticComponentHostProperty = 1 << 4,
|
SyntheticProperty = 1 << 4,
|
||||||
|
SyntheticHostProperty = 1 << 5,
|
||||||
|
CatSyntheticProperty = SyntheticProperty | SyntheticHostProperty,
|
||||||
|
|
||||||
// mutually exclusive values...
|
// mutually exclusive values...
|
||||||
Types = TypeElementAttribute | TypeElementClass | TypeElementStyle | TypeProperty
|
Types = TypeElementAttribute | TypeElementClass | TypeElementStyle | TypeProperty
|
||||||
|
|
|
@ -230,12 +230,7 @@ export function rootRenderNodes(view: ViewData): any[] {
|
||||||
return renderNodes;
|
return renderNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum RenderNodeAction {
|
export const enum RenderNodeAction {Collect, AppendChild, InsertBefore, RemoveChild}
|
||||||
Collect,
|
|
||||||
AppendChild,
|
|
||||||
InsertBefore,
|
|
||||||
RemoveChild
|
|
||||||
}
|
|
||||||
|
|
||||||
export function visitRootRenderNodes(
|
export function visitRootRenderNodes(
|
||||||
view: ViewData, action: RenderNodeAction, parentNode: any, nextSibling: any, target: any[]) {
|
view: ViewData, action: RenderNodeAction, parentNode: any, nextSibling: any, target: any[]) {
|
||||||
|
@ -298,7 +293,19 @@ function visitRenderNode(
|
||||||
view, nodeDef.ngContent.index, action, parentNode, nextSibling, target);
|
view, nodeDef.ngContent.index, action, parentNode, nextSibling, target);
|
||||||
} else {
|
} else {
|
||||||
const rn = renderNode(view, nodeDef);
|
const rn = renderNode(view, nodeDef);
|
||||||
execRenderNodeAction(view, rn, action, parentNode, nextSibling, target);
|
if (action === RenderNodeAction.RemoveChild && (nodeDef.flags & NodeFlags.ComponentView) &&
|
||||||
|
(nodeDef.bindingFlags & BindingFlags.CatSyntheticProperty)) {
|
||||||
|
// Note: we might need to do both actions.
|
||||||
|
if (nodeDef.bindingFlags & (BindingFlags.SyntheticProperty)) {
|
||||||
|
execRenderNodeAction(view, rn, action, parentNode, nextSibling, target);
|
||||||
|
}
|
||||||
|
if (nodeDef.bindingFlags & (BindingFlags.SyntheticHostProperty)) {
|
||||||
|
const compView = asElementData(view, nodeDef.index).componentView;
|
||||||
|
execRenderNodeAction(compView, rn, action, parentNode, nextSibling, target);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
execRenderNodeAction(view, rn, action, parentNode, nextSibling, target);
|
||||||
|
}
|
||||||
if (nodeDef.flags & NodeFlags.EmbeddedViews) {
|
if (nodeDef.flags & NodeFlags.EmbeddedViews) {
|
||||||
const embeddedViews = asElementData(view, nodeDef.index).viewContainer._embeddedViews;
|
const embeddedViews = asElementData(view, nodeDef.index).viewContainer._embeddedViews;
|
||||||
for (let k = 0; k < embeddedViews.length; k++) {
|
for (let k = 0; k < embeddedViews.length; k++) {
|
||||||
|
|
|
@ -90,7 +90,15 @@ export class AnimationRenderer implements Renderer2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
removeChild(parent: any, oldChild: any): void {
|
removeChild(parent: any, oldChild: any): void {
|
||||||
this._engine.onRemove(oldChild, () => this.delegate.removeChild(parent, oldChild));
|
this._engine.onRemove(oldChild, () => {
|
||||||
|
// Note: if an component element has a leave animation, and the component
|
||||||
|
// a host leave animation, the view engine will call `removeChild` for the parent
|
||||||
|
// component renderer as well as for the child component renderer.
|
||||||
|
// Therefore, we need to check if we already removed the element.
|
||||||
|
if (this.delegate.parentNode(oldChild)) {
|
||||||
|
this.delegate.removeChild(parent, oldChild);
|
||||||
|
}
|
||||||
|
});
|
||||||
this._queueFlush();
|
this._queueFlush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue