[Angular] Update FormArray with patchValue
Currently, patchValue doesn't support update FormArray.
The workarround is you need to empty the form array first, then add items back.
import {ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, Output, SimpleChanges} from '@angular/core'; import {FormBuilder, FormArray, FormGroup, FormControl, Validators} from '@angular/forms'; import {Meal} from '../../../shared/services/meals/meals.service'; @Component({ selector: 'meal-form', changeDetection: ChangeDetectionStrategy.OnPush, styleUrls: ['meal-form.component.scss'], template: ` <div class="meal-form"> <form [formGroup]="form"> <div class="meal-form__name"> <label> <h3>Meal name</h3> <input type="text" formControlName="name" placeholder="e.g. English Breakfast"> <div class="error" *ngIf="required"> Workout name is required </div> </label> </div> <div class="meal-form__food"> <div class="meal-form__subtitle"> <h3>Food</h3> <button type="button" (click)="addIngredient()" class="meal-form__add"> <img src="/img/add-white.svg" alt="Add food"> Add food </button> </div> <div formArrayName="ingredients"> <label *ngFor="let c of ingredients.controls; index as i;"> <input type="text" [formControlName]="i" placeholder="e.g Eggs"> <span class="meal-form__remove" (click)="removeIngredient(i)" ></span> </label> </div> <div class="meal-form__submit"> <div> <button *ngIf="!exists" type="button" class="button" (click)="createMeal()"> Create Meal </button> <button *ngIf="exists" type="button" class="button" (click)="updateMeal()"> Save </button> <a [routerLink]="['../']" class="button button--cancel"> Cancel </a> </div> <div class="meal-form__delete" *ngIf="exists"> <div *ngIf="toggled"> <p>Delete item?</p> <button class="confirm" type="button" (click)="removeMeal()"> Yes </button> <button class="cancel" type="button" (click)="toggle()"> No </button> </div> <button class="button button--delete" type="button" (click)="toggle()"> Delete </button> </div> </div> </div> </form> </div> ` }) export class MealFormComponent implements OnChanges { toggled = false; exists = false; @Input() meal: Meal; @Output() create = new EventEmitter<Meal>(); @Output() update = new EventEmitter<Meal>(); @Output() remove = new EventEmitter<Meal>(); form = this.fb.group({ name: ['', Validators.required], ingredients: this.fb.array(['']) }); get ingredients() { // Type check for ingredients, mark as FormArray // Therefore when we use 'ingredients', // We can get auto complete return this.form.get('ingredients') as FormArray; } get required() { return ( this.form.get('name').hasError('required') && this.form.get('name').touched ); } constructor(private fb: FormBuilder) { } ngOnChanges(changes: SimpleChanges): void { if (this.meal && this.meal.name) { this.exists = true; this.emptyIngredients(); const value = this.meal; this.form.patchValue(value); if (value.ingredients) { for (const item of value.ingredients) { this.ingredients.push(new FormControl(item)); } } } } emptyIngredients() { while (this.ingredients.controls.length > 0) { this.ingredients.removeAt(0); } } createMeal() { if (this.form.valid) { this.create.emit(this.form.value); } } updateMeal() { if (this.form.valid) { this.update.emit(this.form.value); } } removeMeal() { this.remove.emit(this.form.value); } addIngredient() { // Add a new FormControl to FormArray this.ingredients.push(new FormControl('')); } removeIngredient(i: number) { this.ingredients.removeAt(i); } toggle() { this.toggled = !this.toggled; } }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
2016-08-17 [Webpack] Use the Webpack Dashboard to Monitor Webpack Operations
2016-08-17 [RxJS] AsyncSubject