Angular Async Pipe on a getter

user2622344

I have a basic component for my question:

export class AppComponent {
  id = 1;

  private _dataSource$ = new Subject<any>();
  /*
  private _dataSource$ = new BehaviorSubject<any>({
    name: 'Firstname Lastname',
    id: 1,
    city: 'New York'
  });
  */

  constructor() {
    this.dataSource$.subscribe(a => {
      console.log(a);
    });
  }

  get dataSource$(): Observable<any> {
    return this._dataSource$.asObservable();
  }

  changeObj() {
    console.log('changeObj');

    this._dataSource$.next({
      name: 'Firstname Lastname',
      id: ++this.id,
      city: 'Los Angeles'
    });
  }
}

template:

<button (click)="changeObj()">change obj</button>
<div>
  {{dataSource$ | async | json}}
</div>

But when the changeObj-method is called (by the click on the button) the new value of the dataSource won't be emitted by the async pipe (But the new value will be displayed on the console by the extra subscription). If I change the type from Subject to BehaviorSubject, the async pipe works as expected.

Furthermore if I use the _dataSource$ directly (without the private accessor) instead of the

  get dataSource$(): Observable<any> {
    return this._dataSource$.asObservable();
  }

it works, too.

I literally have no clue why this is the case. I thought that both should work identically for upcoming dataSource changes.

Here is a stackblitz example for it: https://stackblitz.com/edit/angular-pt2scn?file=src%2Fapp%2Fapp.component.html

Igor

You need to return a single instance of the Observable instance instead of returning a new instance with every call to the getter.

  dsAsObservable$: Observable<any> = this._dataSource$.asObservable(); // <-- Instance created once
  get dataSource$(): Observable<any> {
    return this.dsAsObservable$;
  }

The above will solve that problem. You have to take change detection into consideration and change detection will retrieve this._dataSource$.asObservable() every time that dataSource$ is called. By setting it to a single instance initially and returning that same instance the template will now function as you expect it should.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related