char m
char m

Reputation: 8336

Why only last character of the string in Angular async pipe binding is shown?

component.html:

<div *ngIf="!isWaiting">
  <h2>LOGIN</h2>
  <p>{{ message | async }}</p>
  <div *ngIf="!(isLoggedIn | async)">
    <button (click)="login()">{{'StrLogin' | translate}}</button>
  </div>
  <div *ngIf="(isLoggedIn | async)">
    <button (click)="logout()">{{'StrLogout' | translate}}</button>
  </div>
</div>
<div *ngIf="isWaiting">
  <p>initializing</p>
</div>

component.ts

  message: Observable<string>;

  login(name : string, password : string): void {
    this.message = this.tokenService.login(name, password)
    .pipe(
      map((token) => {
        console.debug('login succeeded: %s', JSON.stringify(token));
        return 'success';
      }),
      catchError(err => {
        console.debug('login failed: %s', JSON.stringify(err));
        return 'failed';
      })
    );
  }

When this fails only the letter 'd' (of the 'failed') is displayed. If I change it to:

      catchError(err => {
        console.debug('login failed: %s', JSON.stringify(err));
        return '123';
      })

it displays 3.

Upvotes: 6

Views: 740

Answers (1)

Reactgular
Reactgular

Reputation: 54771

The catchError() operator expects the callback function to return an observable. I'm not sure why it renders 3 but most likely the string was converted into an observable array that emits each character in sequence.

https://github.com/ReactiveX/rxjs/blob/master/src/internal/operators/catchError.ts#L90

      catchError(err => {
        console.debug('login failed: %s', JSON.stringify(err));
        return of('failed');
      })

https://www.learnrxjs.io/operators/error_handling/catch.html

When using the async pipe in templates. Keep in mind that it will call subscribe if the DOM is mutated by a *ngIf higher up. So if the observable is sourced from an HTTP request, then add a shareReplay(1) operator and only use the same object reference in the template.

Upvotes: 10

Related Questions