Search code examples
angularautocompleterxjs6rxjs-pipeable-operators

Angular autocomplete async dont filter


I am doing an auto-complete search box and the problem I have is that when I write a word in the input, the service return very well the list of the items result. The service return if there are elements that match or empty if there are not, but the problems is that the list of my component doesn't update with the service values and I don't know why. I was following an example, and mine doesn't work. I hope someone can help me.

This is the service request.

searchNewsInList2(filterValue:any):Observable<New[]>{
    return this.httpClient.get<New[]>(this.basePath)
    .pipe(
            tap((response:any)=>{
                response=response
                .filter(news=>news.title.includes(filterValue))
            return response;
            })

        );

    }

This is the request in the component, the list doesn't update with the service return data.

constructor(private notificationService:NotificationsService,private newsService: NewsService, private router: Router,private tost:ToastrService) {

    this.notificationRequest=new Notification();
    this.newsSelected=new New();
    this.newsCntrlToAdd = new FormControl();

    }

    ngOnInit() {
    this.filteredNews=this.newsCntrlToAdd.valueChanges
        .pipe(
            debounceTime(300),
            startWith(''),
            switchMap(value =>this.newsService.searchNewsInList2( value))
        );
    }

    displayFn(newFound: New) {
        if (newFound) {
            return newFound.title;
        }
    }

This is the view.

<mat-form-field class="example-full-width">
    <input matInput placeholder="Specify a news to add"[formControl]="newsCntrlToAdd"
    [matAutocomplete]="auto" required minlength="4">
    </mat-form-field>
        <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
            <mat-option *ngFor="let newFound of (filteredNews | async)" [value]="newFound">
            <span>{{ newFound.title }}</span>
            <!--small> | ID: {{newFound.id}}</small-->
            </mat-option>
        </mat-autocomplete>

Solution

  • It looks to me like in your service you are making an API request, and then in your pipe filtering out any values that don't match. If that is the case, problem here is that the tap operator does not actually modify they value of the observable.
    The purpose of this operator is to perform any side effects (logging for example) without affecting the output. See the docs for more information.
    I think what you are really looking for is the map operator (docs). The map operator "maps" the emitted value to the value you return.

    Your service code would then look like this:

    searchNewsInList2(filterValue:any):Observable<New[]>{
        return this.httpClient.get<New[]>(this.basePath)
          .pipe(
              map((response:any)=>{
                 response=response.filter(news=>news.title.includes(filterValue));
                 return response;
             })
          );
    }