Search code examples
angularangular-materialdropdown

Angular Material: issue with mat-select


Im using a simple dropdown from Angular Material with the purpose of triggering an event/function on selection (this case an api call). I have tried almost everything, saw plenty of posts and still im missing something

The HTML:

<mat-form-field>
  <mat-label>Choose a camera</mat-label>
  <mat-select [(ngModel)]="selected"  (ngModelChange)="test()">
    <mat-option  *ngFor="let c of cameras" [value]="c.name">
      {{c.name}} 
    </mat-option>
  </mat-select>
</mat-form-field>

The ts:

export class MoviesComponent implements OnInit {
  selected:string;

  test() { 
    console.log(this.selected);
  }
}

This is very simple, and one of plenty of aproaches, but nothing is working! Any ideas?


Solution

  • You have 2 options. Either a model form or a reactive form.

    Option 1: Model form

    Controller

    export class MoviesComponent implements OnInit {
      selected:string;
      
      test() {
        // API call here
        console.log(this.selected) 
      }
    }
    

    Template

    <mat-form-field>
      <mat-label>Choose a camera</mat-label>
      <mat-select [(value)]="selected" (selectionChange)="test()">
      <!-- OR <mat-select [(ngModel)]="selected" (ngModelChange)="test()"> -->
        <mat-option *ngFor="let c of cameras" [value]="c.name">
          {{c.name}}
        </mat-option>
      </mat-select>
    </mat-form-field>
    

    Option 2: Reactive form

    Controller

    export class MoviesComponent implements OnInit, OnDestroy {
      completed$ = new Subject<any>();
      selected: string;
      selectedControl = new FormControl(this.selected);
      
      ngOnInit() {
        this.selectedControl.valueChanges.pipe(
          takeUntil(this.completed$),
          switchMap(selected => {
            console.log(selected);
            // return API call here
          })
        ).subscribe(
          response => {
            // handle respone from API
          },
          error => {
            // handle error from API
          }
        );
      }
    
      ngOnDestroy() {
        this.completed$.next();
        this.completed$.complete();
      }
    }
    

    Template

    <mat-form-field>
      <mat-label>Choose a camera</mat-label>
      <mat-select [formControl]="selectedControl">
        <mat-option *ngFor="let c of cameras" [value]="c.name">
          {{c.name}}
        </mat-option>
      </mat-select>
    </mat-form-field>