I have an update method in a component which calls another function for some validation and then executes the updates if validation is successful. However the validation logic itself depends on a some values that are fetched using http.get. My issue is that validate logic completes before the subscription returns and the update happen before the errors get a chance to be populated.
I have simulated this in the following Stackblitz: https://stackblitz.com/edit/angular-jwnq3h?file=src/app/hello.component.ts
How do I ensure that the validation methods waits for subscription to complete before returning its own Observable? I feel like this should be simple in the rxjs world, but coming from a Java background, it all seems like magic.
Component code for reference from the above Stackblitz:
import { Component, Input } from "@angular/core";
import { Observable, of, from } from "rxjs";
@Component({
selector: "hello",
template: `
<h1>Demo</h1>
<p><button (click)="updateValues()">Update</button></p>
<p><button (click)="updateValues(true)">Invalid Update</button></p>
<p>{{ updateMessage }}</p>
`,
styles: [
`
h1 {
font-family: Lato;
}
`
]
})
export class HelloComponent {
@Input() name: string;
updateMessage: string = "Not updated";
updateValues(withErrors: boolean) {
this.validate(withErrors).subscribe(validation => {
if (validation.isValid) {
let confirmation = confirm("Confirm update");
if (confirmation) {
this.doUpdate();
}
} else {
alert(
"Invalid: \n" +
validation.errors.reduce((message, error) => message + "\n" + error)
);
}
});
}
validate(withErrors: boolean): Observable<any> {
let validation: any = {};
validation.isValid = true;
validation.errors = [];
let showError3: boolean = false;
if (withErrors) {
validation.errors.push("Error 1");
validation.errors.push("Error 2");
this.fetchValues().subscribe(values => {
setTimeout(function() {
console.log("Execute after delay");
let confirmation = confirm("values fetched" + values);
if (confirmation) {
showError3 = true;
} else {
showError3 = false;
}
if (showError3) {
validation.errors.push("Error 3");
}
}, 5000);
});
}
validation.isValid = validation.errors.length == 0;
return of(validation);
}
doUpdate() {
this.updateMessage = "Updated";
}
fetchValues(): Observable<any> {
let values = Array.from(Array(20), (e, i) => i + 1);
return of(values);
}
}