Search code examples
htmlangularmulti-selectselect-options

How to add a search filter to a select option in angular


I'm trying to add to add a search filter in my select option list because there are many options and I think that without a search, it will not be easy for the user to find the option that he wants to select.

I hope you will understand me because I'm not good at English.

Here's my code (it's just a part of my table)

<ng-container *ngFor="let menaceProcessus of menaceProcessusTab">
    <tr>
         <td colspan="4" bgcolor="#f1f1f1"><b>{{menaceProcessus?.processus?.nom}}</b></td>
    </tr>
    <ng-container *ngFor="let actif of menaceProcessus?.actifs">
        <tr>
            <td [rowSpan]="actif?.menaces?.length+1">{{actif?.actif?.nom}}</td>
        </tr>
     <ng-container *ngFor="let mnVuln of actif?.menaces">
        <tr>
             <td>{{mnVuln?.vulnerabilite?.nom}}</td>
             <td>
                 <select class="form-control" 
                  (change)="mnVuln?.menaceActif?.menace.id = $event.target.value; 
                            updateMenaceProcessus()">
                      <option></option>
                      <option *ngFor="let menace of menaces" 
                          [value]="menace.id" 
                          [selected]="menace.id === mnVuln?.menaceActif?.menace.id">
                        {{menace.nom}}</option>
                  </select>
              </td>
              <td>
                 <input class="form-control" 
                    type="text" [value]="mnVuln?.menaceActif?.probabilite"> 
              </td>
          </tr>
      </ng-container>
    </ng-container>
 </ng-container>

Solution

  • If you want to filter your array menaces by typing on the first letter, then it is possible to filter your array like this:

    HTML:

    <select class="form-control" 
         (change)="mnVuln?.menaceActif?.menace.id = $event.target.value; 
                   updateMenaceProcessus();
                   filterMenaces($event)">
        <option></option>
        <option *ngFor="let menace of menaces" 
            [value]="menace.id" 
            [selected]="menace.id === mnVuln?.menaceActif?.menace.id">
            {{menace.nom}}</option>
    </select>
    

    TypeScript:

    origMenaces = [];
    
    methodAPIToGetMenaces() {
       this.yourService()
           .subscribe(s=> {
               this.menaces = s;
               this.origMenaces = s;
           });
    }
    
    filterMenaces(str: string) {
        if (typeof str === 'string') {
            this.menaces = this.origMenaces.filter(a => a.toLowerCase()
                                                 .startsWith(str.toLowerCase())); 
        }
    }
    

    UPDATE 1:

    If you want to filter by input value:

    HTML:

    <input type="text"         
        (ngModelChange)="filterItem($event)" 
        [(ngModel)]="filterText">
        <br>
    <select 
         #selectList
         [(ngModel)]="myDropDown" 
        (ngModelChange)="onChangeofOptions($event)">
        <option value="empty"></option>
        <option *ngFor="let item of items">         
            {{item}}
        </option>    
    </select>
    <p>items {{ items | json }}</p>
    

    TypeScript:

    import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  {
      name = 'Angular 4';
      myDropDown : string;
      items = ['one', 'two', 'three'];
      origItems = ['one', 'two', 'three'];
      @ViewChild('selectList', { static: false }) selectList: ElementRef;
    
      onChangeofOptions(newGov) {
         console.log(newGov);
      }
    
      filterItem(event){
          if(!event){
              this.items = this.origItems;
          } // when nothing has typed*/   
          if (typeof event === 'string') {
              console.log(event);
              this.items = this.origItems.filter(a => a.toLowerCase()
                                                 .startsWith(event.toLowerCase())); 
          }
          console.log(this.items.length);
          this.selectList.nativeElement.size = this.items.length + 1 ;       
       }      
    }
    

    Please, see work example at stackblitz