How to wait for Angular to initialize before triggering an animation?

84 Views Asked by At

In this demo the dashOffset property is used to trigger the dash-offset animation.

So for example if we enter a new percentage in the input field we see the animation is triggered. The code that updates the dashOffset state looks like this:

  @Input({ transform: (p: string) => parseInt(p) })
  set percentage(p: number) {
    this.percentageState = p;
    if (!this.firstAnimation) {
      if (!!p) {
        this.dashOffset = this.calculateDashOffset(this.percentageState);
      } else {
        this.dashOffset = undefined;
      }
    }

If it's not the first animation, then the dashOffset state is calculated and this triggers the animation.

If it is the firstAnimation then dashOffset state is set in ngAfterViewInit like this:

  ngAfterViewInit() {
    if (this.firstAnimation) {
      this.dashOffset = this.calculateDashOffset(this.percentageState);
      this.firstAnimation = false;
      console.log(`The dash offset is ${this.dashOffset}`);
    }
  }

However this does not trigger the animation.

Where in the component lifecycle should we initialize an animation trigger in order to trigger the first animation?

1

There are 1 best solutions below

5
Flo On BEST ANSWER

Some things you can do:

First: You set changeDetection: ChangeDetectionStrategy.OnPush, so you need to push any changes. Do it like this:

svg-cicle.component.ts

  constructor(private ngz: NgZone, private changeRef: ChangeDetectorRef) {}

  private firstAnimation: boolean = true;
  ngAfterViewInit() {
    if (this.firstAnimation) {
          this.dashOffset = this.calculateDashOffset(this.percentageState);
          this.firstAnimation = false;
          this.changeRef.detectChanges();
    }
  }

Then easily set the percent in the main component, which gives the data to the cicle itself:

main.ts

 ngOnInit() {
    this.control.valueChanges.subscribe((percent: any) => {
      console.log(percent);
      percent = parseInt(percent);

      percent = !!percent ? percent : 100;
      percent = isNaN(percent) ? 100 : percent;
      percent = percent < 0 ? 0 : percent;
      percent - percent > 100 ? 100 : percent;
      this.percentage = percent;
    });

    setTimeout(() => {
      this.percentage = 20;
    },1)
  }

The setTimeout add the change into a new render frame and the animation works on start, and on every changing.