1
votes

I'm using Angular Material "^6.4.7" and Angular "^6.1.9". I done some routing to navigate through a menu filled with observables (to navigate by id of these observables). Now I have to add an autocomplete to filter this menu (to help the user to find a particular option), but I have some trouble to achieve this.

My html

    <mat-form-field>
        <mat-label>Find datasource...</mat-label>
        <input matInput name="datasource filter" [formControl]="searchForm" [ngModel]="dataSourceFilterInput">
    </mat-form-field>

    <div *ngFor="let datasource of dataSourceFiltered$ | async">
        <div [routerLink]="[datasource.id]">
            <h6>{{datasource.name}}</h6>
        </div>
    </div>

My ts:

export class DataSourceSelectorComponent implements OnInit {

dataSourceFiltered$: Observable<IDataSourceDefinition[]>;
dataSource$: Observable<IDataSourceDefinition[]>;
dataSourceList: IDataSourceDefinition[] = [];
searchForm: FormControl = new FormControl();

constructor(private _datasourceService: DataSourceConfigurationService, private _route: ActivatedRoute) {
}

ngOnInit() {
    this.dataSourceFiltered$ = this._route.paramMap.pipe(
        switchMap(params => {
            this.selectedId = +params.get("id");
            this.dataSource$ = this._datasourceService.getAllDataSources();
            this.dataSource$.subscribe(ds => (this.dataSourceList = ds));
            return this.dataSource$;
        })
    );
}

}

Where IDataSourceDefinition is my interface with the property "name".

I think that inside the ngOnInit I have to add the filter (as suggested in Angular Material using a form control (searchForm in this case) and the "valueChanges.pipe()"), but all the methods like "map" or "startWith" or "filter" cannot be used with Observables.

I cannot just filter the subscription of the Observable, I need that the filter returns an Observable, otherwise the routing will break.

Any suggestion?

1
Welcome to Stack Overflow. Will you please clarify this: but all the methods like "map" or "startWith" or "filter" cannot be used with Observables. Are you saying they won't work, or do you get errors using them?Cobus Kruger
Hi, they are not a property of Observables, so I cannot use themE.Tiake

1 Answers

0
votes

The way you call operators like map or filter has changed in RxJs 6, which is used by Angular 6. Google will find you plenty of guides that will explain all the changes, but this will get you started.

You already use switchMap the right way and need to just keep doing that.

In RxJs 5 you would call the operators directly, like this:

someObservable
  .map(item => doSomethingWith(item))
  .filter(item => isThisItemValid(item));

And so on.

As of RxJs 6, you pipe them all. So my pseudo-code above turns into:

someObservable
  .pipe(map(item => doSomethingWith(item)))
  .pipe(filter(item => isThisItemValid(item)));

Exactly the same code, just wrap them in pipe calls.

The other relevant change is where you import them from. All the operators (maybe just most?) are imported from rxjs/operators, so to use map, switchMap and filter, you'll include this at the top of your file:

import { map, switchMap, filter } from 'rxjs/operators';

I don't know exactly what you wanted to do in your example code, but you can just add additional pipe calls to the end of what you have:

ngOnInit() {
    this.dataSourceFiltered$ = this._route.paramMap.pipe(
        switchMap(params => {
            this.selectedId = +params.get("id");
            this.dataSource$ = this._datasourceService.getAllDataSources();
            this.dataSource$.subscribe(ds => (this.dataSourceList = ds));
            return this.dataSource$;
        })
    )
    .pipe(filter(item => filterItHere(item)))
    .pipe(map(item => mapItHere(item)));
}