问题
I want to init my mat chips input with input data but when I have two chips, it forms only one form :
*.component.ts
@Component({
selector: 'app-pps-dialog',
templateUrl: './pps-dialog.component.html',
})
export class PPSDialogComponent implements OnInit {
patientid: string;
ppsForm: FormGroup;
ppssToDisplay;
visible: boolean = true;
selectable: boolean = true;
removable: boolean = true;
addOnBlur: boolean = true;
// Enter, comma
separatorKeysCodes = [ENTER, COMMA];
constructor(
private route: ActivatedRoute,
private ppssService:PPSsService,
private _changeDetectorRef: ChangeDetectorRef,
private location: Location,
private router: Router,
public dialog: MatDialog,
private formBuilder: FormBuilder,
public dialogRef: MatDialogRef<PPSDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any)
{ this.initForm(); }
ngOnInit(): void {
this.ppssToDisplay = this.ppssService.getSinglePPS(this.key)
.subscribe(res => {
this.ppssToDisplay = res;
this.ppsForm.controls['requirements'].setValue(Array(this.ppssToDisplay.effetsind));
console.log(this.ppssToDisplay.effetsind));
});
add(event: MatChipInputEvent): void {
let input = event.input;
let value = event.value;
// Add our requirement
if ((value || '').trim()) {
this.requirements = this.ppsForm.get('requirements') as FormArray;
this.requirements.push(this.formBuilder.control(value.trim()));
}
// Reset the input value
if (input) {
input.value = '';
}
}
remove(index: number): void {
const requirements = this.ppsForm.get('requirements') as FormArray;
if (index >= 0) {
requirements.removeAt(index);
}
}
initForm(): void {
this.ppsForm = this.formBuilder.group({
requirements: this.formBuilder.array(['']),
// I don't know why, but I must init my form with empty chips if I want to receive data from service.
});
}
get formData() {
return <FormArray>this.ppsForm.get('requirements');
}
*ppss.service
import { Injectable } from '@angular/core';
import { Patient } from '../models/patient.model';
import { PPS } from '../models/pps.model';
import { AngularFireDatabase, AngularFireList, AngularFireObject} from 'angularfire2/database';
import { Observable } from 'rxjs/Observable';
import {switchMap, map} from 'rxjs/operators';
import * as firebase from 'firebase';
import DataSnapshot = firebase.database.DataSnapshot;
@Injectable({
providedIn: 'root'
})
export class PPSsService {
ppss: AngularFireList<any>;
constructor(private database: AngularFireDatabase) {this.ppss = database.list('ppss');}
getSinglePPS(key: string){
return this.database.object('ppss/' + key).valueChanges();
}
}
console.log(this.ppssToDisplay.effetsind):
(2) ["Troubles de la vessie", "Troubles de l'érection"]
I've used the example of Angular Material:
*.component.html
<mat-form-field style="width:50%" appearance="outline">
<mat-label>Description du traitement</mat-label>
<textarea matInput formControlName="description"></textarea>
</mat-form-field>
<mat-form-field style="width:50%" appearance="outline">
<mat-label>Effets indésirables du traitement</mat-label>
<mat-chip-list #chipList>
<mat-chip *ngFor="let requirement of formData.controls; let i = index;" [selectable]="selectable"
[removable]="removable" (removed)="remove(i)">
{{requirement.value}}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
<input placeholder="Nouvel effet indésirable..."
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event)"/>
</mat-chip-list>
</mat-form-field>
ERROR Error: Must supply a value for form control at index: 0:
> core.js:1598 ERROR Error: Must supply a value for form control at index: 0.
at forms.js:4304
at forms.js:4274
at Array.forEach (<anonymous>)
at FormArray.push../node_modules/@angular/forms/fesm5/forms.js.FormArray._forEachChild (forms.js:4274)
at FormArray.push../node_modules/@angular/forms/fesm5/forms.js.FormArray._checkAllValuesPresent (forms.js:4302)
at FormArray.push../node_modules/@angular/forms/fesm5/forms.js.FormArray.setValu
I have the same problem if I init my form with :["Troubles de la vessie", "Troubles de l'érection",...]
回答1:
Reactive FormArray
are pretty tricky to use. Check this minimal and valid example:
import {Component, OnInit} from '@angular/core';
import {COMMA, ENTER} from '@angular/cdk/keycodes';
import {FormArray, FormBuilder, FormGroup} from '@angular/forms';
import {MatChipInputEvent} from '@angular/material';
@Component({
selector: 'app',
template: `
<mat-form-field [formGroup]="formData">
<mat-label>Effets indésirables du traitement</mat-label>
<mat-chip-list #chipList>
<mat-chip *ngFor="let requirement of formData.get('requirements').value; let i = index;"
[selectable]="selectable"
[removable]="removable"
(removed)="remove(i)">
{{requirement}}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
<input
placeholder="Nouvel effet indésirable..."
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event)"/>
</mat-chip-list>
</mat-form-field>
`
})
export class AppComponent implements OnInit {
formData: FormGroup;
selectable = true;
removable = true;
addOnBlur = true;
readonly separatorKeysCodes: number[] = [ENTER, COMMA];
constructor(private formBuilder: FormBuilder) {}
ngOnInit() {
this.initForm();
this.ppssToDisplay();
}
initForm(): void {
this.formData = this.formBuilder.group({
requirements: this.formBuilder.array([]),
})
}
ppssToDisplay() {
// Simulate your async call to ppssService
setTimeout(() => {
const control = <FormArray>this.formData.controls.requirements;
['Troubles de la vessie', 'Troubles de l\'érection'].map(x =>
control.push(this.formBuilder.control(x))
);
}, 300)
}
add(e: MatChipInputEvent) {
const input = e.input;
const value = e.value;
if ((value || '').trim()) {
const control = <FormArray>this.formData.controls.requirements;
control.push(this.formBuilder.control(value.trim()));
}
if (input) {
input.value = '';
}
}
remove(i: number) {
let control = <FormArray>this.formData.controls.requirements;
control.removeAt(i);
}
}
来源:https://stackoverflow.com/questions/52061184/input-material-chips-init-form-array