3

This is used in this code example https://stackblitz.com/angular/jdamnnmgrae?file=app%2Fautocomplete-overview-example.ts.

The code snippet in question is:

<mat-option *ngFor="let state of filteredStates | async" [value]="state.name">

I've not yet seen this syntax so I'm puzzled as to what it does. When I remove the async call, the code no longer works so I need to understand it.

My belief is that this code is creating a list of Observables that is being sent to the async pipe but I haven't seen where this is documented in Angular's docs. If you know please respond.

import {map} from 'rxjs/operators/map';

export class AutocompleteOverviewExample {
// . . . other stuff omitted
  filteredStates: Observable<any[]>;

  constructor() {
    this.filteredStates = this.stateCtrl.valueChanges
    .pipe(
      startWith(''),
      map(state => state ? this.filterStates(state) : this.states.slice())
   );

So, the for loop likely looping over Observables because the Async pipe takes a Promise or Observable, and it's not a Promise. :-)

Useful links:

I haven't been able to find how pipe is used from FormControl.valueChanges, but hopefully this will become clear when this question is answered.

(Q) Can someone point me to some Angular documentation that explains what the "*ngFor | async" syntax means? or provide an explaination.

Searches for answer showed these results

2
  • Not seeing what's hard to understand. You've clearly found the AsyncPipe documentation, so what else do you need? Commented Mar 29, 2018 at 1:48
  • 1
    It means filteredStates is an promise or observable that is not initialised/defined at component initialization time and will be resolved at some unknown time asynchronously. and when ever it does the for loop will run and show the template unlike other iterables like array which will throw an error during component initialisation if the array is undefined or not available Commented Mar 29, 2018 at 2:38

1 Answer 1

4

The let state of filteredStates | async syntax can be thought of as this:

let state of (filteredStates | async)

The async pipe is applied to the filteredStates variable and not the whole for loop.

I think it should be obvious after looking at all of the other resources you looked at, but the async pipe is useful because it will subscribe to the observable for you (and additionally clean up the subscription so you don't need to worry about unsubscribing).

So, what is going on is that Angular is subscribing to your filteredStates observable. Each time a new list is streamed from your observable, the Angular *ngFor directive will loop over that list that was streamed.

Without the async pipe you would just have to subscribe to your filteredStates observable in your component and store the list as a property on your component (which you would then loop over in place of the filteredStates | async). Note: There are a couple ways of how to handle the unsubscribing, this is just one way.

<mat-option *ngFor="let state of filteredStates" [value]="state.name">
class AutocompleteOverviewExample {
    filteredStates: State[] = [];
    subscription: Subscription = null;

    constructor() {
        this.subscription = this.stateCtrl.valueChanges
        .pipe(
            startWith(''),
            map(state => state ? this.filterStates(state) : this.states.slice())
        )
        .subscribe(states => this.filteredStates = states);
    }

    ngOnDestroy() {
        if (this.subscription) {
            this.subscription.unsubscribe();
            this.subscription = null;
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.