How to populate mat-select with angular material?

2019-07-25 11:58发布

Hey I'm trying to use angular material and I'm having an issue. In my project I get movies details such as title,year,genre and so on. I'm trying to make an edit popup and when I got to the genre edit I got a little problem. how can I populate the select line with genres the movie already has?

lets say for example I want the default value to be: "Action,Comedy".

my html:

<mat-select placeholder="Genre" [formControl]="genre" multiple>
    <mat-option *ngFor="let genre of genresList" value="Action,Comedy" >{{genre}}</mat-option>
  </mat-select>
  <mat-error *ngIf="genre.hasError('required')">
      Title is <strong>required</strong>
    </mat-error>
</mat-form-field>

component:

export class MyDialogComponent implements OnInit {

  selectedMovie: MyMovie;


  title:FormControl;
  year:FormControl;
  runtime:FormControl;
  genre:FormControl;
  director:FormControl;


  genresList: string[] = ['Action', 'Comedy', 'Horror', 'Fantasy', 'Drama', 'Romance'];

  constructor(private dataService: DataService) {
    this.selectedMovie = dataService.selectedMovie;

    this.title = new FormControl(this.selectedMovie.Title, [
      Validators.required
    ]);
    this.year = new FormControl(this.selectedMovie.Year, [
      Validators.required
    ]);
    this.runtime = new FormControl(this.selectedMovie.Runtime, [
      Validators.required
    ]);
    this.genre = new FormControl("this.selectedMovie.Genre", [
      Validators.required
    ]);
    this.director = new FormControl(this.selectedMovie.Director, [
      Validators.required
    ]);


  }

Appreciate any help! thanks

update:

this.dataService.getMovie(this.moviesToLoad[i]).subscribe(res => {

        this.movie = {
           id: this.id,
           Title: res.Title,
           Year: res.Year,
           Runtime: res.Runtime,
           Genre: res.Genre.split(","),
           Director: res.Director
          }

res is just string which im trying to change to array, something wrong over since i get only the first element of the array in the default mat-select.. how can i fix that?

1条回答
再贱就再见
2楼-- · 2019-07-25 12:40

You should be creating a FormGroup instead of individual FormControls.

Genre in your Movie is a string but the multiple select list will need an array of string to show multiple values. Also, looks like there's a space between the genres(Action, Crime) which when trimmed will create an extra starting space in Crime. To fix that, you'll need to split by , and then apply map on the array elements to remove the extra space by using trim. This will be done by this like:

genre: [this.selectedMovie.Genre.split(',').map(genre => genre.trim()), [Validators.required]],

So your code will look something like:

import { FormGroup, FormBuilder, Validators } from '@angular/forms';

...
selectedMovie: MyMovie;
movieForm: FormGroup;
genresList = ['Action', 'Comedy', 'Horror', 'Fantasy', 'Drama', 'Romance'];

constructor(
  private fb: FormBuilder,
  private dataService: DataService
) {}

ngOnInit() {

  this.dataService.getMovie('anyIndexHere')
    .subscribe(selectedMovie => {

      this.selectedMovie = {
        id: 'Some ID',
        ...selectedMovie
      }

      this.movieForm = this.fb.group({
        title: [this.selectedMovie.Title, [Validators.required]],
        year: [this.selectedMovie.Year, [Validators.required]],
        runtime: [this.selectedMovie.Runtime, [Validators.required]],
        genre: [this.selectedMovie.Genre.split(',').map(genre => genre.trim()), [Validators.required]],
        director: [this.selectedMovie.Director, [Validators.required]],
      });

    });
}

Since we're already assigning the default value to the genre FormControl, it will be selected by default in your template.

So in your template, you'll now be using the attribute binding syntax([formGroup]="movieForm") to bind to the form. And then for the mat-select since you'll be specifying the formControlName as genre which is the FormControl for the Genre field, you'll see the Genre's selected by default.

So your template would look something like:

<form [formGroup]="movieForm">
  ...
  <mat-form-field>
    <mat-select placeholder="Movie Genre" formControlName="genre" multiple>
      <mat-option *ngFor="let genre of genresList" [value]="genre">
        {{genre}}
      </mat-option>
    </mat-select>
  </mat-form-field>
  ...
</form>

Here's a Sample StackBlitz for your ref.

查看更多
登录 后发表回答