Angular 2 - Countdown timer

2019-02-10 06:37发布

I am willing to do a countdown timer in Angular 2 that start from 60 (i.e 59, 58,57, etc...)

For that I have the following:

constructor(){
  Observable.timer(0,1000).subscribe(timer=>{
  this.counter = timer;
});
}

The above, ticks every second, which is fine; however, it goes in an ascending order to an unlimited number. I am not sure if there is a way to tweak it so I can have a countdown timer.

2条回答
冷血范
2楼-- · 2019-02-10 07:14

Import into Component:

import { Observable } from "rxjs/Observable";
import "rxjs/add/observable/timer";
import "rxjs/add/operator/finally";
import "rxjs/add/operator/takeUntil";
import "rxjs/add/operator/map";

Function CountDown:

countdown: number;
 startCountdownTimer() {
    const interval = 1000;
    const duration = 10 * 1000;
    const stream$ = Observable.timer(0, interval)
      .finally(() => console.log("All done!"))
      .takeUntil(Observable.timer(duration + interval))
      .map(value => duration - value * interval);
    stream$.subscribe(value => this.countdown = value);
  }

Html :

<div class="panel panel-default">
  <div class="panel-heading">
    <h2 class="panel-title">Countdown timer</h2>
  </div>
  <div class="panel-body">
    <div>
      <label>value: </label> {{countdown}}
    </div>
    <div>
      <button (click)="startCountdownTimer()" class="btn btn-success">Start</button>
    </div>
  </div>
</div>
查看更多
够拽才男人
3楼-- · 2019-02-10 07:38

There are many way to achieve this, a basic example is to use the take operator

import { Observable, timer } from 'rxjs';
import { take, map } from 'rxjs/operators';

@Component({
   selector: 'my-app',
   template: `<h2>{{countDown | async}}</h2>`
})
export class App {
   counter$: Observable<number>;
   count = 60;

   constructor() {
     this.counter$ = timer(0,1000).pipe(
       take(this.count),
       map(() => --this.count)
     );
   }
}

Here is a live plnkr

Update

A better way! create a counter directive

import { Directive, Input, Output, EventEmitter, OnChanges, OnDestroy } from '@angular/core';

import { Subject, Observable, SubscriptionLike, timer } from 'rxjs';
import { switchMap, take, tap } from 'rxjs/operators';

@Directive({
  selector: '[counter]'
})
export class CounterDirective implements OnChanges, OnDestroy {

  private counter$ = new Subject<any>();
  private countSub$: SubscriptionLike;

  @Input() counter: number;
  @Input() interval: number;
  @Output() value = new EventEmitter<number>();

  constructor() {

    this.countSub$ = this.counter$.pipe(
      switchMap((options: any) =>
        timer(0, options.interval).pipe(
          take(options.count),
          tap(() => this.value.emit(--options.count))
        )
      )
    ).subscribe();
  }

  ngOnChanges() {
    this.counter$.next({ count: this.counter, interval: this.interval });
  }

  ngOnDestroy() {
    this.countSub$.unsubscribe();
  }

}

Usage:

<ng-container [counter]="60" [interval]="1000" (value)="count = $event">
  <span> {{ count }} </span>
</ng-container>

Here is a live stackblitz

查看更多
登录 后发表回答