Material autocomplete not displaying list on click

Viewed 11900

I have a material autocomplete.

I am making an ngrx call to pull the data.

 //parentcomponent.ts
 this.store.select(fromStore.getSearchFormStateMessageTypeListData).subscribe(msgTypeList => {
  if (msgTypeList.length > 0) {
    console.log('msgtypelist ='+msgTypeList)
    for (var i = 0; i < msgTypeList.length; i++) {
      this.messageTypeList.push(msgTypeList[i]);
    }
  }
  else {
    this.store.dispatch(new fromStore.GetGlobalSearchMessageTypeList({}));
  }
})


//parentcomponent.html

 <mat-card style="margin: 1px;">
    <search-form [messageTypeList]="messageTypeList"  (onSearchData)="searchButtonClick($event)" [rowData]="rowData | async">
   </search-form>
</mat-card>

From the parent I am passing the msgTypeList to the child.

In the child, I am binding the autocomplete to the list but the list is not displaying anything when we click inside.

It only displays options when we type something in the input box ( which filters the options )

 //childcomponent.html
 <form [formGroup]="searchForm" id="searchForm" style="width:100%;height:70%" (ngSubmit)="onSubmit()">
<tr>
<td class="input-form" style="padding-right:4%;width:10%">
   <mat-form-field>
     <input type="text" placeholder="Message Type" aria-label="Assignee"  formControlName="msgType" matInput [matAutocomplete]="autoMsgType">
     <mat-autocomplete #autoMsgType="matAutocomplete" placeholder="Message Type" [displayWith]="displayMessageTypeFn">
          <mat-option *ngFor="let messageType of filteredMessageTypeList | async | sort:'msgType'" [value]="messageType">{{messageType.msgType}}</mat-option>
       </mat-autocomplete>
  </mat-form-field>
 </td>
</tr>
</form>

Below is the child.ts file

   //childcomponent.ts
searchForm: FormGroup;

  ngOnInit() {
this.searchForm = this.formBuilder.group({
      direction: [null],
      msgType: [null, Validators.nullValidator],
     });
    this.filterMessageTypeLists();
     }



filterMessageTypeLists() {
    this.filteredMessageTypeList = this.searchForm.controls['msgType'].valueChanges.pipe(
      startWith<string | any>(''),
      map(value => typeof value === 'string' ? value : value.msgType),
      map(msgType => msgType ? this._msg_filter(msgType, this.messageTypeList) : this.messageTypeList.slice())
    );
  }


     private _msg_filter(msgType: string, lists: any[]): any[] {
    const filterValue = msgType.toLowerCase();
    return lists.filter(option => option.msgType.toLowerCase().includes(msgType.toLowerCase()))
      }

  displayMessageTypeFn(field?: any): string | undefined {
return field ? field.msgType : undefined;;
 }

Issue is if I click in the autocomplete input, it should open the list but nothing displays

No list is shown

However if we enter anything in the input box, the options are then displayed List is shown

5 Answers

I had the same problem.

Make sure this.messageTypeList has values in it during the map() call

My issue was that didn't have anything in my array so it showed as blank.

ngOnInit() {
// I subscribed to messageTypeList; 
// Then I did my control.onValueChanged( map... map...);
}

It should be

ngOnInit() {
  ObservableList.subscribe(array => {
     messageTypeList = array;
     control.onValueChanged( // do your mapping filter stuff);
  });
}

As long as you have values in your list it should show up.

You simply need to call the form.valueChanges just after get your data instead of execute it in init function like this :

this.data1.getArticleS().subscribe(a => {
        this.tabArticle = a;
        console.log(a);
        this.filteredArticles = this.stockForm.get('article').valueChanges //erreur angular qui fonctionne bug interpreter ?
            .pipe(
                startWith(''),
                map(value => typeof value === 'string' ? value : value.name),
                map(name => name ? this._filter(name) : this.tabArticle.slice()));

    });

you can simply set the value for searchForm in ngAfterViewInit lifecycle hook

ngAfterViewInit(): void { this.searchForm .setValue(''); }

Bind a click event on input in your html and call a function on the click event. Something like this:

<input type="text" placeholder="Message Type" aria-label="Assignee"  formControlName="msgType" 
    matInput [matAutocomplete]="autoMsgType" (click)="myFunc()" >

and in your ts file, declare a boolean variable and set it to false initially. Let's say the variable is bool.

Now write the function myFunc() and simply toggle that variable like:

this.bool = !this.bool;

Now in your matautocomplete tag , just set the panelOpen property to the bool variable like this:

<mat-autocomplete #autoMsgType="matAutocomplete" placeholder="Message Type" [displayWith]="displayMessageTypeFn" 
     panelOpen="bool">

You can set the bool variable back to false on some later function in order for it to work properly.

I was using

<mat-option *ngFor="let option of filteredRecipients | async" ...

with

ngOnInit(): void {
    this.filteredRecipients = this.myControl.valueChanges
      .pipe(
        startWith(''),
        map(value => this.chatService.filterForAutoComplete(value))
      );
 }

The problem was that my view (and consequently this.filteredRecipients) was being rendered before the this.chatService actually recieved the list of recipients that the map function is trying to grab. So instead I used the following that makes sure the recipients is populated before the map function runs.

In my service:

private vAllRecipientsPopulatedSubject = new Subject<any>();
public allRecipientsPopulated$ = this.vAllRecipientsPopulatedSubject.asObservable();
public setRecipients(rcpts: RecipientModel[]) {
    const callback = () => {
      this.vAllRecipientsPopulatedSubject.next();
    };
    this.vAllRecipients = [];
    let itemsProcessed = 0;
    rcpts.forEach(element => {
      this.vAllRecipients.push(element);
      itemsProcessed++;
      if (itemsProcessed === rcpts.length) {
        callback();
      }
    });
}

In my controller

this.filteredRecipients = combineLatest([this.myControl.valueChanges.pipe(startWith('')), this.chatService.allRecipientsPopulated$])
  .pipe(
    map(([changes, notused]) => this.chatService.filterForAutoComplete(changes))
  );
Related