问题
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:
You should be creating a FormGroup
instead of individual FormControl
s.
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.
来源:https://stackoverflow.com/questions/52672346/how-to-populate-mat-select-with-angular-material