Michael Joshua
Michael Joshua

Reputation: 47

How to check if observable countdown timer has completed?

I have a simple countdown timer in angular 4

import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/timer';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/take';

countDown;
counter = 60;
enableButton:boolean = false;

this.countDown = Observable.timer(0,1000).take(this.counter).map(() => --
 this.counter);

I want to make enableButton boolean true when this observable has been completed.

How should I write that code? Please Help

Here is a plunker link, which I am using in my project https://plnkr.co/edit/TWMIEd1UykUdUC37qyFK?p=preview

Upvotes: 4

Views: 3931

Answers (3)

Vega
Vega

Reputation: 28738

In the view:

<button [disabled]="counter !== 0">OK</button>

and in the class:

  countDown;
  counter = 10; // change accordingly
  tick = 1000;
  constructor() {
  this.countDown = Observable.timer(0, this.tick)
      .take(this.counter)
      .map(() => --this.counter)
  }

plunker

Upvotes: 4

Naftali
Naftali

Reputation: 146350

You can utilize scan and async to your advantage:

@Component({
  selector: 'my-app',
  template: ` 
    <div>
      <h1>Countdown timer</h1>
      <h2>{{countDown | async}}</h2>
      
      <button [disabled]="(countDown | async) === 0">My button</button>
    </div>
  `,
})
export class App {
  
  countDown;
  counter = 10;
  
  constructor() {
    
    this.countDown = Observable.timer(0,1000)
      .scan((current, next) => this.counter - next)
      .takeWhile(counter => counter >= 0);
  }
}

Here is the live version: https://plnkr.co/edit/bKESzNK1wqbtPmQk4TUT?p=preview

So instead of updating the global counter you use scan to keep count of a local version (as the timer returns numbers in sequence)

OLD ANSWER

You can utilize the .takeWhile operator

this.countDown = Observable.timer(0,1000)
    .take(this.counter)
    .map(() => --this.counter)
    .takeWhile(counter => counter >= 0);

Here is the updated plnkr: https://plnkr.co/edit/Z6K5Yt2tDS4MKbgIoujc?p=preview

You actually do not need the .take and can just do this:

this.countDown = Observable.timer(0,1000)
  .map(() => this.counter--)
  .takeWhile(counter => counter >= 0);

https://plnkr.co/edit/L38t3LYON9DszW5N2MjA?p=preview

Upvotes: 2

Lyubimov Roman
Lyubimov Roman

Reputation: 1269

http://reactivex.io/documentation/operators/subscribe.html third argument

You may do it like this:

this.countDown = Observable
  .timer(0, 1000)
  .take(this.counter)
  .map(() => --this.counter);

this.countDown.subscribe(() => {}, () => {}, () => (this.enableButton = true))

Or like this:

<button *ngIf="!(countDown | async)"><button>
<button *ngIf="this.counter"><button>

Upvotes: -1

Related Questions