Reputation: 45
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
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>
_ 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
Upvotes: 1
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