Angular10 如何在 FormGroup 中使用 FormArray
How to use a FormArray in a FormGroup in Angular 10
我正在创建一个包含普通输入和一组成分的表单。
用户在填写表格时必须能够自动添加成分。
这是我第一次使用 FormArray 创建表单,但我卡住了。
在控制台上:
这是我试过的方法:
export class RecipeAddComponent implements OnInit {
recipe: IRecipe;
recipeForm: FormGroup;
ingredients: FormArray;
ingredientForm: FormGroup;
validationErrors: string[] = [];
constructor(private recipeService: RecipeService, private fb: FormBuilder, private router: Router) {
}
ngOnInit(): void {
this.intitializeRecipeForm();
}
intitializeRecipeForm() {
this.recipeForm = this.fb.group({
name: ['', Validators.required],
preparationTime: ['', Validators.required],
description: ['', Validators.required],
ingredients: this.fb.array([this.createIngredient()])
});
}
createIngredient(): FormGroup {
return this.fb.group({
name: '',
amount: ''
});
}
addRecipe() {
this.recipeService.addNewRecipe(this.recipeForm.value).subscribe(response => {
this.router.navigateByUrl('/recipes');
}, error => {
this.validationErrors = error;
})
}
addIngredient(): void {
this.ingredients = this.recipeForm.get('ingredients') as FormArray;
this.ingredients.push(this.createIngredient());
}
}
HTML
<div class="container">
<form class="p-5 col-md-5 col-sm-8 formShadow" [formGroup]='recipeForm' (ngSubmit)="recipeForm.valid && addRecipe()"
autocomplete="off">
<p class="h4 mb-4">Add new recipe</p>
<app-text-input [formControl]='recipeForm.controls["name"]' [label]='"Name"'></app-text-input>
<app-text-input [formControl]='recipeForm.controls["preparationTime"]' [label]='"Preparation Time"'
[type]='"number"'>
</app-text-input>
<app-text-input [formControl]='recipeForm.controls["description"]' [label]='"Description"'></app-text-input>
<div class="form-group">
<ng-container formArrayName="ingredients">
<div *ngFor="let ingredient of ingredients.controls; index as i">
<ng-container [formGroupName]="i">
<input formControlName="name" class="form-control" />
<input formControlName="amount" class="form-control" />
</ng-container>
</div>
</ng-container>
</div>
<div class="row mt-5" *ngIf="validationErrors.length > 0">
<ul class="text-danger">
<li *ngFor="let error of validationErrors">
{{error}}
</li>
</ul>
</div>
<div class="form-group text-center">
<button [disabled]="!recipeForm.valid" class="btn btn-outline-dark mr-2" type="submit">Register</button>
<button class="btn outline-light mr-2" (click)="cancel()">Cancel</button>
</div>
</form>
</div>
任何提示都会有所帮助。这是我第一次这样做。
这种情况好像你有一个父类别,并且可以有多个子类别,这些子类别可以称为 sub-categories 表单数组。根据用户要求,将有任意数量的 sub-categories。
所以一个formgroup和formarray可以设计如下:-
constructor(
private formBuilder: FormBuilder
) { }
this.categoryForm = this.formBuilder.group({
name: [undefined, [Validators.required]],
image: [undefined, [Validators.required]],
subCategories: this.formBuilder.array([
]),
});
要按需添加新的子类别,您可以按照
addNewFieldSubCat() {
(<FormArray>this.categoryForm.get("subCategories")).push(this.formBuilder.group({
name: [undefined, [Validators.required]],
image: [undefined, []],
}));
}
要删除 sub-category 的现有行,您可以做的是:-
public removeSubCategory(index) {
(<FormArray>this.categoryForm.get("subCategories")).removeAt(index);
}
我正在创建一个包含普通输入和一组成分的表单。
用户在填写表格时必须能够自动添加成分。
这是我第一次使用 FormArray 创建表单,但我卡住了。
在控制台上:
这是我试过的方法:
export class RecipeAddComponent implements OnInit {
recipe: IRecipe;
recipeForm: FormGroup;
ingredients: FormArray;
ingredientForm: FormGroup;
validationErrors: string[] = [];
constructor(private recipeService: RecipeService, private fb: FormBuilder, private router: Router) {
}
ngOnInit(): void {
this.intitializeRecipeForm();
}
intitializeRecipeForm() {
this.recipeForm = this.fb.group({
name: ['', Validators.required],
preparationTime: ['', Validators.required],
description: ['', Validators.required],
ingredients: this.fb.array([this.createIngredient()])
});
}
createIngredient(): FormGroup {
return this.fb.group({
name: '',
amount: ''
});
}
addRecipe() {
this.recipeService.addNewRecipe(this.recipeForm.value).subscribe(response => {
this.router.navigateByUrl('/recipes');
}, error => {
this.validationErrors = error;
})
}
addIngredient(): void {
this.ingredients = this.recipeForm.get('ingredients') as FormArray;
this.ingredients.push(this.createIngredient());
}
}
HTML
<div class="container">
<form class="p-5 col-md-5 col-sm-8 formShadow" [formGroup]='recipeForm' (ngSubmit)="recipeForm.valid && addRecipe()"
autocomplete="off">
<p class="h4 mb-4">Add new recipe</p>
<app-text-input [formControl]='recipeForm.controls["name"]' [label]='"Name"'></app-text-input>
<app-text-input [formControl]='recipeForm.controls["preparationTime"]' [label]='"Preparation Time"'
[type]='"number"'>
</app-text-input>
<app-text-input [formControl]='recipeForm.controls["description"]' [label]='"Description"'></app-text-input>
<div class="form-group">
<ng-container formArrayName="ingredients">
<div *ngFor="let ingredient of ingredients.controls; index as i">
<ng-container [formGroupName]="i">
<input formControlName="name" class="form-control" />
<input formControlName="amount" class="form-control" />
</ng-container>
</div>
</ng-container>
</div>
<div class="row mt-5" *ngIf="validationErrors.length > 0">
<ul class="text-danger">
<li *ngFor="let error of validationErrors">
{{error}}
</li>
</ul>
</div>
<div class="form-group text-center">
<button [disabled]="!recipeForm.valid" class="btn btn-outline-dark mr-2" type="submit">Register</button>
<button class="btn outline-light mr-2" (click)="cancel()">Cancel</button>
</div>
</form>
</div>
任何提示都会有所帮助。这是我第一次这样做。
这种情况好像你有一个父类别,并且可以有多个子类别,这些子类别可以称为 sub-categories 表单数组。根据用户要求,将有任意数量的 sub-categories。 所以一个formgroup和formarray可以设计如下:-
constructor(
private formBuilder: FormBuilder
) { }
this.categoryForm = this.formBuilder.group({
name: [undefined, [Validators.required]],
image: [undefined, [Validators.required]],
subCategories: this.formBuilder.array([
]),
});
要按需添加新的子类别,您可以按照
addNewFieldSubCat() {
(<FormArray>this.categoryForm.get("subCategories")).push(this.formBuilder.group({
name: [undefined, [Validators.required]],
image: [undefined, []],
}));
}
要删除 sub-category 的现有行,您可以做的是:-
public removeSubCategory(index) {
(<FormArray>this.categoryForm.get("subCategories")).removeAt(index);
}