Here is some working code:
Stackblitz: https://stackblitz.com/edit/angular-ivy-tt9vjd?file=src/app/app.component.ts
app.component.html
<button (click)='swap()'>Swap object</button>
<div @div *ngIf='object'>{{ object.data }}</div>
app.component.css
div {
width: 100px;
height: 100px;
background: purple;
display: flex;
align-items: center;
justify-content: center;
color: antiquewhite;
}
app.component.ts
import { animate, style, transition, trigger } from "@angular/animations";
import { Component } from "@angular/core";
import { interval } from "rxjs";
import { first } from "rxjs/operators";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
animations: [
trigger("div", [
transition(":enter", [
style({ transform: "scale(0)" }),
animate("250ms 0ms ease-out", style({ transform: "scale(1)" }))
]),
transition(":leave", [
style({ transform: "scale(1)" }),
animate("250ms 0ms ease-in", style({ transform: "scale(0)" }))
])
])
]
})
export class AppComponent {
object: any = { data: "DIV_1" };
swap() {
this.object = null;
interval(0)
.pipe(first())
.subscribe(() => {
this.object = { data: "DIV_2" };
});
// DESIRED CODE INSTEAD OF THE ABOVE
// this.object = { data: "DIV_2" };
}
}
The issue with this code is that an intermediary null state had to be introduced. Thus I am mixing presentation code with logic in order "to make it work". This is violating good encapsulation practices and adds unnecessary complexity to the code.
How can the same results be achieved using code exclusively in the animations property in the decorator?
requirements
- Detect a change in the object reference.
- React to the object reference change akin to how
:enterand:leavework; First animateDIV_1out, then animateDIV_2in. - Encapsulate anything regarding the animation in the
animationscode. So the swap function should be:swap(){this.object = { data: "DIV_2" };}