Не удалось исправить данные в FormArray
Невозможно исправить значения для FormArray resultList
.
Кто-нибудь может объяснить мне, чего я не хватает?
TS Файл:
import { Component, OnInit } from '@angular/core';
import { Student } from '../student';
import { FormGroup, FormControl, Validators, FormArray } from '@angular/forms';
@Component({
selector: 'app-container',
templateUrl: './container.component.html',
styleUrls: ['./container.component.css']
})
export class ContainerComponent implements OnInit {
studList: Student[] = [];
myform: FormGroup = new FormGroup({
firstName: new FormControl('', [Validators.required, Validators.minLength(4)]),
lastName: new FormControl(),
gender: new FormControl('male'),
dob: new FormControl(),
qualification: new FormControl(),
resultList: new FormArray([])
});
onSave() {
let stud: Student = new Student();
stud.firstName = this.myform.get('firstName').value;
stud.lastName = this.myform.get('lastName').value;
stud.gender = this.myform.get('gender').value;
stud.dob = this.myform.get('dob').value;
stud.qualification = this.myform.get('qualification').value;
this.studList.push(stud);
this.myform.controls.resultList.patchValue(this.studList);
console.log(JSON.stringify(this.studList));
}
ngOnInit() {
}
}
Модель:
export class Student {
public firstName: String;
public lastName: string;
public gender: string;
public dob: string;
public qualification: string;
}
HTML:
<div class="container">
<h3>Striped Rows</h3>
<table class="table table-striped" formArrayName="resultList">
<thead>
<tr>
<th>Firstname</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of myform.controls.resultList.controls; let i = index" [formGroupName]="i">
<td><p formControlName="firstName"></p></td>
</tr>
</tbody>
</table>
</div>
this.studList JSON:
[
{
"firstName":"santosh",
"lastName":"jadi",
"gender":"male",
"dob":"2018-03-31T18:30:00.000Z",
"qualification":"BE"
},
{
"firstName":"santosh",
"lastName":"jadi",
"gender":"male",
"dob":"2018-03-31T18:30:00.000Z",
"qualification":"BE"
}
]
Ответы
Ответ 1
По вашему вопросу вы хотите добавить нового Student
в resultList
. Прежде всего, вам нужно знать, что FormArray
- это массив AbstractControl. Вы можете добавить к массиву только тип AbstractControl, а не другой. Для упрощения задачи предпочитаете использовать FormBuilder
:
constructor(private fb: FormBuilder) {}
createForm() {
this.myform = this.fb.group({
firstName: ['', [Validators.required, Validators.minLength(4)]],
lastName: [],
gender: ['male'],
dob: [],
qualification: [],
resultList: new FormArray([])
});
}
Как вы можете видеть перед заполнением resultList FormArray
, он сопоставляется с FormGroup:
onSave() {
let stud: Student = new Student();
stud.firstName = 'Hello';
stud.lastName = 'World';
stud.qualification = 'SD';
this.studList.push(stud);
let studFg = this.fb.group({
firstName: [stud.firstName, [Validators.required, Validators.minLength(4)]],
lastName: [stud.lastName],
gender: [stud.gender],
dob: [stud.dob],
qualification: [stud.qualification],
})
let formArray = this.myform.controls['resultList'] as FormArray;
formArray.push(studFg);
console.log(formArray.value)
}
FormBuilder - создает AbstractControl из пользовательской конфигурации.
Это, по сути, синтаксический сахар, который сокращает новый FormGroup(), новый FormControl() и новый шаблон FormArray(), который может накапливаться в больших формах.
Кроме того, в html formControlName привязан к элементу <p>
, это не вход, и вы не можете привязываться к не формировать такие элементы, как div/p/span...:
<tbody>
<tr *ngFor="let item of myform.controls.resultList.controls; let i = index" [formGroupName]="i">
<td><p formControlName="firstName"></p></td> <==== Wrong element
</tr>
</tbody>
Итак, я думаю, вы просто хотите показать добавленных учеников в таблице. Затем перебираем шаблон studList и показываем его значение в таблице:
<tbody>
<tr *ngFor="let item of studList; let i = index" [formGroupName]=i>
<td>
<p> {{item.firstName}} </p>
</td>
</tr>
</tbody>
Значение исправления
Соблюдайте осторожность при установке массива. Поскольку patchValue FormArray исправляет значения по индексу:
patchValue(value: any[], options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {
value.forEach((newValue: any, index: number) => {
if (this.at(index)) {
this.at(index).patchValue(newValue, {onlySelf: true, emitEvent: options.emitEvent});
}
});
this.updateValueAndValidity(options);
}
Итак, код под ним исправляет элемент по индексу = 0: Первое индексированное значение this.myform.controls['resultList'] as FormArray
будет заменено на:
let stud1 = new Student();
stud1.firstName = 'FirstName';
stud1.lastName = 'LastName';
stud1.qualification = 'FFF';
formArray.patchValue([stud1]);
Ваш случай не работает, потому что patchValue требует некоторых элементов управления в массиве. В вашем случае в массиве нет элементов управления. Посмотрите исходный код.
Демо-версия StackBlitz
Ответ 2
Сначала попробуйте выполнить эти шаги и убедитесь, что вы на правильном пути
Потому что в вашем сценарии вы исправляете объект в formArray, поэтому вы должны сначала проанализировать этот объект и проверить, импортировали ли вы ReactiveFormsModule в ваш app.module.ts.
Ответ 3
вы должны это сделать, код берется из angular.io, вам нужно сделать setcontrol, который будет делать или идти, хотя ссылка есть код для того же самого он делает использование массива адресов
this.setAddresses(this.hero.addresses);
setAddresses(addresses: Address[]) {
const addressFGs = addresses.map(address => this.fb.group(address));
const addressFormArray = this.fb.array(addressFGs);
this.heroForm.setControl('secretLairs', addressFormArray);
}
Ответ 4
Я бы предпочел использовать FormBuilder
для создания формы.
export class ComponentName implements OnInit {
form: FormGroup;
constructor(private fb: FormBuilder){}
ngOnInit() {
this.buildForm();
}
buildForm() {
this.form = this.fb.group({
firstName: '',
lastName: '',
...
resultList: this.fb.array([])
});
}
}
Я полагаю, что список студентов будет получен через вызов API как наблюдаемый, а не статический массив. Предположим, мы данные следующим образом.
resultModel =
{
firstName: "John",
lastName: "Doe",
....
resultList: [
{
prop1: value1,
prop2: value2,
prop3: value3
},
{
prop1: value1,
prop2: value2,
prop3: value3
}
...
]
}
Как только данные станут доступны, мы можем исправить значения следующим образом:
patchForm(): void {
this.form.patchValue({
firstName: this.model.firstName,
lastName: this.model.lastName,
...
});
// Provided the FormControlName and Object Property are same
// All the FormControls can be patched using JS spread operator as
this.form.patchValue({
...this.model
});
// The FormArray can be patched right here, I prefer to do in a separate method
this.patchResultList();
}
// this method patches FormArray
patchResultList() {
let control = this.form.get('resultList') as FormArray;
// Following is also correct
// let control = <FormArray>this.form.controls['resultList'];
this.resultModel.resultList.forEach(x=>{
control.push(this.fb.group({
prop1: x.prop1,
prop2: x.prop2,
prop3: x.prop3,
}));
});
}
Ответ 5
Массив не содержит метода patchValue
. Вы должны перебирать элементы управления и patchValue
каждый из них отдельно.
Ответ 6
Я использую formgroup
в formarray
как:
this.formGroup = new FormGroup({
clientCode: new FormControl('', []),
clientName: new FormControl('', [Validators.required, Validators.pattern(/^[a-zA-Z0-9 _-]{0,50}$/)]),
type: new FormControl('', [Validators.required]),
description: new FormControl('', []),
industry: new FormControl('', []),
website: new FormControl('', [Validators.required, Validators.pattern(this.settings.regex.website)]),
businessEmail: new FormControl('', [Validators.pattern(this.settings.regex.email)]),
clients: this._formBuilder.array([this._formBuilder.group({
contactPerson: new FormControl('', [Validators.required]),
contactTitle: new FormControl('', [Validators.required]),
phoneNumber: new FormControl('', [Validators.required, Validators.pattern(this.settings.regex.phone)]),
emailId: new FormControl('', [Validators.required, Validators.pattern(this.settings.regex.email)]),
timeZone: new FormControl('', [Validators.required, Validators.pattern(this.settings.zipCode), Validators.minLength(5), Validators.maxLength(12)])
})])
})
Для значения патча я использую метод ниже:
let control = _this.formGroup.get('clients') as FormArray
clients.forEach(ele => {
control.push(_this._formBuilder.group({
contactPerson: new FormControl(ele.client_name, [Validators.required]),
contactTitle: new FormControl(ele.contact_title, [Validators.required]),
phoneNumber: new FormControl(ele.phone_number, [Validators.required, Validators.pattern(_this.settings.regex.phone)]),
emailId: new FormControl(ele.email_id, [Validators.required, Validators.pattern(_this.settings.regex.email)]),
timeZone: new FormControl(ele.timezone, [Validators.required, Validators.pattern(_this.settings.zipCode), Validators.minLength(5), Validators.maxLength(12)])
}))
});
Используя этот метод, мы также можем проверить вложенное поле.
Надеюсь, что это может помочь.