[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;
  }
}
时间: 2025-01-04 14:27:27

[Angular] Update FormArray with patchValue的相关文章

Angular5的new feature

https://blog.angular.io/version-5-0-0-of-angular-now-available-37e414935ced Version 5.0.0 of Angular Now Available We are pleased to announce version 5.0.0 of Angular, pentagonal-donut. This is a major release containing new features and bugfixes. Th

记录项目版本升级angular4 ~ angular5

前言: 在上一篇ng4文章<angular4--实际项目搭建总结>中说过,等到ng5正式发布,并且蚂蚁的NG ZORRO兼容ng5之后,我会对ng4项目进行升级.这篇文章就是大概说下升级的折腾过程吧.下面结语中有最佳实践,整个过程中有自己挖的坑,可以选择忽略,直接看结语. 升级(折腾)过程: ①ng5更新: 访问这个链接是ng的升级导向 https://angular-update-guide.firebaseapp.com/ ,内容如下图(看起来还是很简单的): 复制了导向上的命令,安装的时

深入理解Angular中的$apply()以及$digest()

reference:http://blog.csdn.net/dm_vincent/article/details/38705099 $apply()和$digest()在AngularJS中是两个核心概念,但是有时候它们又让人困惑.而为了了解AngularJS的工作方式,首先需要了解$apply()和$digest()是如何工作的.这篇文章旨在解释$apply()和$digest()是什么,以及在日常的编码中如何应用它们. 探索$apply()和$digest() AngularJS提供了一个

[Angular] USING ZONES IN ANGULAR FOR BETTER PERFORMANCE

Link to the artical. Zone detects any async opreations. Once an async oprations happens in Angular, Zone will notify change detection to kick in. Images we have 5000 svg box displaying on the screen. And each svg elements and three event listener on

vue学习笔记(一)关于事件冒泡和键盘事件 以及与Angular的区别

一.事件冒泡 方法一.使用event.cancelBubble = true来组织冒泡 <div @click="show2()"> <input type="button" value="按钮" @click="show1($event)"> </div> methods:{ show1:function(ev){ console.log(ev); alert(1); ev.cancelB

angular.element()的方法大汇总

addClass()-为每个匹配的元素添加指定的样式类名after()-在匹配元素集合中的每个元素后面插入参数所指定的内容,作为其兄弟节点append()-在每个匹配元素里面的末尾处插入参数内容attr() - 获取匹配的元素集合中的第一个元素的属性的值bind() - 为一个元素绑定一个事件处理程序children() - 获得匹配元素集合中每个元素的子元素,选择器选择性筛选clone()-创建一个匹配的元素集合的深度拷贝副本contents()-获得匹配元素集合中每个元素的子元素,包括文字和

promise和Angular中的 $q, defer

在ES6语法中,新出了promise构造函数, 可用来生成promise实例. Promise对象: 代表了未来某个将要发生的事件(通常是一个异步操作).有了promise对象, 可以将异步操作以同步的流程表达出来, 避免了层层嵌套的回调函数(俗称'回调地狱'). 在Angularjs中,对象deferred 实例也可以暴露派生的Promise 实例.以下将对此作简单描述: 1. $q: $q是Angular的一种内置服务,它可以使你异步地执行函数,并且当函数执行完成时它允许你使用函数的返回值(

再识angular

angular中有三个对象非常重要:directive,service,controller service(服务):它可以称的上一个对象或函数(单例对象),它会被传来传去,保证你(controller,directive)每次访问到都是同一个值(内部的数值),你既可以使用angular内建的服务,也可以自己创建服务. 内建的有:$http,$location,$timeout,$interval... 自己创建服务案例: <div ng-app="myApp" ng-contr

半小时入门Angular 2

本文首发于由电子工业出版社出版<揭秘Angular 2>一书,基于第5章概览改写. 作者简介:广发证券互联网金融技术团队,是Angular早期坚定的践行者.作为全新一代的证券业 IT 研发组织,团队致力于用更新更好的技术打造行业方案.支持业务创新. 责编:陈秋歌,寻求报道或者投稿请发邮件至chenqg#csdn.net,或加微信:Rachel_qg. 了解更多前沿技术资讯,获取深度技术文章推荐,请关注CSDN研发频道微博. Angular 2.0 于去年 9 月正式发布. 尽管同一时间里 Re