inorganik / ngx-countUp

Animates a numerical value by counting to it - for Angular
MIT License
138 stars 25 forks source link

Animate from an existing value #22

Closed boar-is closed 5 years ago

boar-is commented 5 years ago

I want to animate countUp from an existing value. For example, I have 100 and I want to animate it to 200. Then I want to animate 200 to 300 an so on. For now, it always animates from 0.

wescopeland commented 5 years ago

You can do this with a combination of ngOnChanges and [options]="{ startVal: previousValue }"

boar-is commented 5 years ago

@wescopeland, could you clarify, please? I have the following code: HTML: <span [countUp]="value" [options]="countUpOptions"></span> Component:

@Component({
  selector: 'app-page',
  templateUrl: './page.component.html',
  styleUrls: ['./page.component.scss']
})
export class PageComponent implements OnChanges {
    value = 100;

    countUpOptions = {
        startVal: this.value
    };

    ngOnChanges(changes: SimpleChanges): void {
        this.countUpOptions = {
            startVal: this.value
        };
    }
}

Now it animates from 100, but not from 200, 300 and so on... Still doesn't work as expected.

wescopeland commented 5 years ago

I've stripped a lot of proprietary code but this should illustrate the idea.

<p 
  *ngIf="previousJackpotValue" 
  class="data-element__content"
  [countUp]="content"
  [options]="{ startVal: previousJackpotValue }">
</p>
export class DataElementComponent implements OnInit, OnChanges {
  @Input() content: string;
  @Input() leaderPoints: number;

  public previousJackpotValue = 1;
  public previousLeaderValue: number;

  constructor() { }

  ngOnInit() { }

  ngOnChanges(e) {
    if (!e.content.firstChange) {
      this.previousJackpotValue = e.content.previousValue;
    }
  }
}

EDIT: Fixed ngOnChanges to contain the right stuff.

boar-is commented 5 years ago

@wescopeland, it gives me an error: Cannot read property 'firstChange' of undefined Seems like e.content is undefined.

inorganik commented 5 years ago

@BorisZubchenko ngOnChanges is for handling value changes of @Input()s. If you don't have inputs, it won't fire.

@wescopeland is right, you use options like he demonstrated to set a starting value other than zero. But if you just want to keep updating the number it counts to, you just need to make sure you bind to your value, and then change it whenever you want it to count to that number.

html:

<span [countUp]="value" [options]="countUpOptions"></span>
boar-is commented 5 years ago

Here's a wrapper directive I've created:

import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-count-up',
  templateUrl: './count-up.component.html',
  styleUrls: ['./count-up.component.scss']
})
export class CountUpComponent implements OnInit, OnChanges {

  @Input() value: number;
  previousValue = 0;

  @Input() options;

  ngOnInit(): void {
    this.options.startVal = this.previousValue;
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (!changes.value.firstChange) {
      this.previousValue = changes.value.previousValue;
      this.options.startVal = this.previousValue;
    }
  }

}
inorganik commented 5 years ago

@BorisZubchenko if you would like to PR this change into the wrapper directive in this lib, I would merge it! Otherwise I can do it. I think you would just need a check in there:

    if (!this.options || !this.options.startVal) {
        this.options = {
          ...this.options,
          startVal: this.previousEndVal
        }
      }

you could remove the ngOnInit() because ngOnChanges will overwrite it

inorganik commented 5 years ago

@BorisZubchenko I went ahead and made this change in 7.1