Home > front end >  How to trigger http call inside switchMap when BehaviorSubject value is emitted
How to trigger http call inside switchMap when BehaviorSubject value is emitted

Time:05-25

I'm learning to write angular applications in a declarative and I'm not sure what the best approach is when calling POST requests.

I have a login form with email and password forms which when a user enters and clicks submit will call the subject.next()

onLogin() {
    if (this.loginForm?.valid) {
      this.userService.loginUserSubject.next(this.loginForm?.value)
    }
  }

Inside my user.service class I have following implemented:

 loginUserSubject = new BehaviorSubject<IUser | null>(null);

  loginInfo$ = this.loginUserSubject.asObservable();

  $login = this.loginInfo$.pipe(
    switchMap(user => this.http.put<IUser>('/user/login', user).pipe(
      tap(response => localStorage.setItem('token', response.email)),
      catchError(error => throwError(error))
      )
    )
 )

Bu then the user clicks submit nothing will happen, the form.value will emit to the subject but the HTTP call won't be executed because there is no subscription happening for the login$ Observable. Is there a way I can call the HTTP POST request when the subject gets the value without subscribing to the Observable in my component or using the async pipe?

CodePudding user response:

I'm not sure why you'd need the BehaviorSubject here. IMO, you could make do without it.

As for why it isn't working for you at the moment, most probably you haven't subscribed to the $login observable.

Service

public login(user: IUser): Observable<any> {
  return this.http.put<IUser>('/user/login', user).pipe(
    tap(response => localStorage.setItem('token', response.email)),
    catchError(error => throwError(error))
  );
}

Component

onLogin() {
  if (this.loginForm?.valid) {
    this.userService.login(this.loginForm?.value).subscribe({
      next: (response: any) => { },
      error: (error: any) => { }
    });
  }
}

CodePudding user response:

Just because you doesn't subscribe your Subject. The code should be like.

loginUserSubject = new BehaviorSubject<IUser>({} as IUser);
loginInfo$ = this.loginUserSubject.asObservable();

$login = this.loginUserSubject.pipe(
  filter((user: IUser) => (Object.keys(user).length > 0)), // prevent object init triggered.
  switchMap(user => this.http.put<IUser>('/user/login', user)
    .pipe(
      tap(response => localStorage.setItem('token', response.email)),
      catchError(error => throwError(error))
    )
  )
).subscribe(() => {
  console.log('Im subscribing');
  // logic might need to be here.....
});
  • Related