Preselecting multiple values for mat-select - Angular 6

41,589

Solution 1

I believe that the easiest way is to use [(ngModel)] directive (or a one-way binding, I'll cover it shortly later) to manipulate the value of mat-select: you can bind a variable, which contains elements you want to preselect, something like this:

<mat-select placeholder="participants" formControlName="participants" multiple [(ngModel)]="selection">
  <mat-option *ngFor="let participant of participants" [value]="participant">{{participant}}</mat-option>
</mat-select>

And then you can just filter your initial array of items and get only those, which you want to select by default (it should be stored in selection class property in provided case).

I have created a STACKBLITZ to demonstrate, that it's possible. In this example, I filter items at even indexes, and finally we get "1'st, 3'rd, 5'th, ..." items selected.

Notice, that you can split [(ngModel)] into 2 separate directives if you want to use only a one-way binding: [ngModel] or (ngModelChange). For more info, take a look at angular template syntax guide.

Solution 2

With Angular6+ there is a deprecation warning when you have both a formControl and [(ngModel)]

It looks like you're using ngModel on the same form field as formControl. Support for using the ngModel input property and ngModelChange event with reactive form directives has been deprecated in Angular v6 and will be removed in Angular v7.

Option 1 using [ngModel] without FormControl

As the first answer suggests, split [ngModel] and (ngModelChange) like this.

<mat-select 
  [(ngModel)]="selectedFoods" 
  (ngModelChange)="selectedFoods" name="selectedFoods" 
  placeholder="Favorite food" multiple>
  <mat-option *ngFor="let food of allfoods" [value]="food.value">
      {{food.viewValue}}
  </mat-option>
</mat-select>

And for the ts.

  allfoods: Food[] = [
    {value: 'steak-0', viewValue: 'Steak'},
    {value: 'pizza-1', viewValue: 'Pizza'},
    {value: 'tacos-2', viewValue: 'Tacos'},
    {value: 'pasta-3', viewValue: 'Pasta'}
  ];
  selectedFoods = [
     'steak-0', 'pasta-3'
  ];

https://stackblitz.com/edit/angular-mat-select-with-ngmodel?embed=1&file=app/select-overview-example.ts

Option 2 using [formControl] without [ngModel]

<mat-form-field>
    <mat-select [formControl]="foodForm" placeholder="Favorite food" multiple>
        <mat-option *ngFor="let food of allfoods" [value]="food.value">
            {{food.viewValue}}
        </mat-option>
    </mat-select>
</mat-form-field>

In this case, the selection is initialised in the FormControl's constructor.

 allfoods: Food[] = [
    {value: 'steak-0', viewValue: 'Steak'},
    {value: 'pizza-1', viewValue: 'Pizza'},
    {value: 'tacos-2', viewValue: 'Tacos'},
    {value: 'pasta-3', viewValue: 'Pasta'}
    ];
 myselectedFoods = ['pasta-3', 'steak-0'];
 foodForm: FormControl = new FormControl(this.myselectedFoods);

https://stackblitz.com/edit/angular-mat-select-multi-with-formcontrol

Share:
41,589
Rana
Author by

Rana

I am a full-time student in Software Engineering. I'm either doing an internship or taking courses. My main interest is in game programming and mobile application.

Updated on July 18, 2021

Comments

  • Rana
    Rana almost 3 years

    I'm trying to preselect multiple options in a mat-select. So far I'm not able to achieve this.

    Here is the HTML file:

    <mat-dialog-content [formGroup]="form">
       <mat-form-field>
         <mat-select placeholder="participants" formControlName="participants"  multiple>
             <mat-option *ngFor="let participant of participants" [value]="participant">{{participant}}</mat-option>
         </mat-select>
        </mat-form-field>
    </mat-dialog-content>
    

    Here is the controller:

    export class EventViewModalComponent implements OnInit {
      form: FormGroup;
      calendarEvent: CalendarEvent;
      participants = [];
    
      constructor(private fb: FormBuilder,
        private participantService: ParticipantService,
        @Inject(MAT_DIALOG_DATA) event: CalendarEvent) 
        { 
        this.form = fb.group({
          title: [event.title, Validators.required],
          location: [event.meta.location, Validators.required],
          description: [event.meta.description, Validators.required],
          start: [event.start, Validators.required],
          end: [event.end, Validators.required],
          participants: [this.participants, Validators.required]
        });
        this.calendarEvent = event;
      }
    
      ngOnInit() {
        this.participantService.getAll().subscribe(data =>{
          for(let i = 0; i < data['length']; i++){
            this.participants.push(data[i]['name']);
          }
        })
      }
    }
    

    This currently selects all the values per default. Here's a screenshot of how it looks currently: enter image description here

    What I'm trying to achieve is having only Cindy and Jim preselected like this:

    enter image description here

    How can I achieve this? I've read through several SO questions and wasn't successful. Any help is appreciated