Reputation: 521
I have this code from the front-end (Angular)
private _baseUrl = "http://localhost:8080/api/v1/professor/";
getProfessor(id: string): Observable<Professor> {
const professor = this.http.get<Professor>(this._baseUrl + id);
return professor;
}
addProfessorRating(id: string, rating: Object): void {
// get the professor, then modify the ratings of them, and make a put request
this.getProfessor(id).subscribe(professor => {
let ratings = professor['ratings'];
ratings.push(rating);
professor['ratings'] = ratings;
return this.http.put<void>(this._baseUrl + id, professor, {
headers: new HttpHeaders({
'content-type': 'application/json'
})
})
});
}
And this endpoint from the backend (Spring boot):
@PutMapping(path = "/{id}")
public String updateProf(@PathVariable("id") String id, @Valid @NotNull @RequestBody Professor professor) {
logger.info("updating professor");
professorService.updateProfessor(id, professor);
return "Updated professor with id: " + id;
}
However, the endpoint is not invoking as the logger doesn't log anything in the console. I tried with Postman and it did make call to the endpoint. Am I doing anything wrong, I would also provide any info if this post is not specific enough.
UPDATE: I called the addProfessorRating by the onSubmit function from Angular form:
onSubmit(rating: Object) {
const id = this.route.snapshot.paramMap.get('id');
this.professorService.addProfessorRating(id, rating);
}
I would appreciate any help.
Upvotes: 0
Views: 95
Reputation: 31125
You need to use a RxJS higher order mapping operator (eg. switchMap
) to map from one observable (this.getProfessor()
) to another (this.http.put()
).
Try the following
private _baseUrl = "http://localhost:8080/api/v1/professor/";
addProfessorRating(id: string, rating: Object): void {
this.getProfessor(id).pipe( // get the professor, then modify the ratings of them, and make a put request
switchMap(professor => {
let ratings = professor['ratings'];
ratings.push(rating);
professor['ratings'] = ratings;
return this.http.put < void > (this._baseUrl + id, professor, {
headers: new HttpHeaders({
'content-type': 'application/json'
})
});
})
).subscribe(
res => console.log(res),
err => console.log(err)
);
}
Good practice is to return the observable from all functions and subscribe to it in the base function. This allows you to retain the async nature of the calls and use the emitted value from the observable.
addProfessorRating(id: string, rating: Object): Observable<any> { // <-- return the observable
return this.getProfessor(id).pipe( // get the professor, then modify the ratings of them, and make a put request
switchMap(professor => {
let ratings = professor['ratings'];
ratings.push(rating);
professor['ratings'] = ratings;
return this.http.put < void > (this._baseUrl + id, professor, {
headers: new HttpHeaders({
'content-type': 'application/json'
})
});
})
); // <-- don't subscribe yet
}
onSubmit(rating: Object) {
const id = this.route.snapshot.paramMap.get('id');
this.professorService.addProfessorRating(id, rating).subscribe( // <-- subscribe here
res => {
console.log(res);
// other statements that depend on `res`
},
err => {
// also good practice to handle error notifications from HTTP observables
}
);
}
Other types of RxJS higher order mapping operators are mergeMap
, concatMap
and exhaustMap
. You could find brief differences between them here.
Upvotes: 2