Daniel
Daniel

Reputation: 45

Wait for subscription of void method

I'm fairly new to rxjs and i'm having troubles with observables.

Before navigating to the next page i need to validate that the total has not changed, usually the method calculateTotal is called asynchronously as you add items. But before continuing to the next page i want to make sure the current transaction total is correct.

This is not exactly the code but more or less represents what i want to do.

public navigateToNextStep() {
    if (isTransactionValid()) {
        this.router.navigate([CodeClient.RoutingToDetailsPage]);
    }
}
private isTransactionValid() {
    let total = this.transaction.Total;

    this.calculateTotal(); //need to wait for this to finish

    if (total == this.transaction.Total) {
        return true;
    }
    return false;
}

The problem is that i need to find a way to wair for calculateTotal() to finish before going to the next step.

private calculateTotal() {
    this.transactionService.calculateTotal(this.transaction).subscribe(
        (result) => {
            this.transaction.Total = result.Total;
            }
    );
}

transactionService

public calculateTotal(trans: Trans): Observable<TotalResult> {
    return this.http.post<TotalResult>(this.api_url, Trans);
}

Thank you.

Upvotes: 1

Views: 3568

Answers (2)

Yanis-git
Yanis-git

Reputation: 7875

hello @Daniel your behavior is really close to promise approch, you can do something like this, is not the cleanest way but is just simple sample to show you how you can deal with full home made Observable.

import { Component, OnInit} from '@angular/core';
import { Observable } from 'rxjs/Observable';
import {Subscriber} from 'rxjs/Subscriber';

@Component({
    selector: 'my-app',
    templateUrl: './app.component.html',
    styleUrls: [ './app.component.css' ]
})
export class AppComponent  implements OnInit {

    obs: Subscriber<number>;
    calculate$: Observable<number>;

    price: number = null;
    quantity: number = null;

    ngOnInit() {
        //We craft home made observable.
        this.calculate$ = Observable.create((obs) => {
            //We keep reference of Observer as attribut of class.
            this.obs = obs; 
            //We init first value as null.
            this.obs.next(null);    
        });  
    }

    private validate() {
        //We assume we consider as valid, any value differente than null.
        if (this.price !== null && this.quantity !== null) 
        {
            //We next new data.
            this.obs.next(this.price * this.quantity);
            //We complete this observable because we don't need it anymore.
            this.obs.complete();
        }
    }

    onPriceHandler() 
    {
        // Possible case of validation.
        this.validate();
    }

    onQuantityHandler() 
    {
        // Possible case of validation.
        this.validate();
    }
}

Html side :

<p>Price :</p>
<input type="number" name="price" [(ngModel)]="price" (change)="onPriceHandler()">
<br>
<p>Quantity :</p>
<input type="number" name="quantity" [(ngModel)]="quantity" (change)="onQuantityHandler()">
<br>
<!-- We don't display "go to next step" button until we have not validate -->
<button *ngIf="(calculate$ | async) !== null"> go next step</button>

Live sample

_ EDIT 1 _

On my case, is better to use BehaviorSubject, small update have to be done :

price: number = null;
quantity: number = null;
isValid$ : BehaviorSubject<boolean>;

ngOnInit() {
    // We init our observable by false, by default is not valid.
    this.isValid$ = new BehaviorSubject(false);
}

private validate() {
    //We assume we consider as valid, any value differente than null.
    if (this.price !== null && this.quantity !== null) 
    {
        //We next new data.
        this.isValid$.next(true);
        //We complete this observable because we don't need it anymore.
        this.isValid$.complete();
    }
}

Html side : go next step

Live sample

Upvotes: 1

ranjeet8082
ranjeet8082

Reputation: 2359

Check the condition in subscribe method.

public navigateToNextStep() {
    let total = this.transaction.Total;
    this.transactionService.calculateTotal(this.transaction).subscribe(
        (result) => {
            this.transaction.Total = result.Total;
            if (total == this.transaction.Total) {
                this.router.navigate([CodeClient.RoutingToDetailsPage]);
            }

        }
    );
}

Upvotes: 1

Related Questions