【问题标题】:Angular 2/4 Edit Form Populate FormArray ControlsAngular 2/4 编辑表单填充 FormArray 控件
【发布时间】:2017-09-25 23:28:37
【问题描述】:

我正在尝试为具有嵌套属性 (FormArray) 的模型实现编辑表单。我的语法有问题,我不确定我是否走在正确的轨道上。主表单的属性工作,这是我遇到问题的嵌套表单。这是我目前所拥有的。

这里我启动表单组:

private initForm() {
  this.subscription = this.expenseService.getExpense(this.id)
    .subscribe(
      expense => {
        this.expense = expense;
        this.patchForm();
      }
    );
  this.expenseEditForm = this.fb.group({
    date: '',
    amount: '',
    check_number: '',
    debit: '',
    payee_id: '',
    notes: '',
    expense_expense_categories_attributes:[]
  });
}

在这里,我修补表单以设置从我的后端 API 检索到的对象的值。

private patchForm() {
  this.expenseEditForm.setValue({
    date: '',
    amount: this.expense.amount_cents,
    check_number: this.expense.check_number,
    debit: this.expense.debit,
    payee_id: '',
    notes: this.expense.notes,
    expense_expense_categories_attributes:  this.fb.array([
      this.setExpenseCategories(),
    ])
  });
}

这就是我卡住的地方。如何推送到 FormArray。如果我尝试推送,我会收到一条错误消息,指出推送它在 FormArray 上不存在。

private setExpenseCategories() {
  for ( let expenseCategories of this.expense.expense_expense_categories){
    this.fb.array.push([
       this.fb.group({
        expense_category_id: [expenseCategories.expense_category_id, Validators.required],
        amount: [expenseCategories.amount_cents]
      ])
    });
  }
}

以防万一。这是我的html。

<div
  *ngFor="let expensecategoriesCtl of expenseEditForm.controls.expense_expense_categories_attributes.controls let i = index"
  [formGroupName]="i"
  style="margin-top: 10px;">

  <md-card>
    <md-select class="full-width-input"
               placeholder="Expense Category"
               id="expense_category_id"
               formControlName="expense_category_id"
    >

      <md-option *ngFor="let expenseCategory of expenseCategories" value="{{expenseCategory.id}}">
        {{expenseCategory.category}}
      </md-option>
    </md-select>

    <md-input-container class="full-width-input">
      <input
        mdInput placeholder="Amount"
        type="number"
        formControlName="amount">
    </md-input-container>
  </md-card>
</div>

【问题讨论】:

    标签: angular typescript angular2-formbuilder


    【解决方案1】:

    对 DeborahK 的回答进行了一些更改,因为 expense.expense_expense_categories 不包含原始类型,而是对象。因此我们不能按原样分配值,但每个对象都需要包装在 FormGroup 中,就像您尝试的那样。

    这里我有你的代码的缩短版本:

    构建表单:

    ngOnInit() {
      this.expenseEditForm = this.fb.group({
        notes: [''],
        // notice below change, we need to mark it as an formArray
        expense_expense_categories_attributes: this.fb.array([])
    })
    

    然后我们在回调中调用patchForm,就像你一样。那个函数看起来像这样,注意,我们在外面调用this.setExpenseCategories

    patchForm() {
      this.expenseEditForm.patchValue({
        notes: this.expense.notes,
      })
      this.setExpenseCategories()
    }
    

    然后是您现有代码的最大变化,我们首先将 FormArray 分配给变量 control 然后我们迭代从后端接收的数组,为每个对象创建一个 FormGroup 并将对象推送到每个FormGroup

    setExpenseCategories(){
      let control = <FormArray>this.expenseEditForm.controls.expense_expense_categories_attributes;
      this.expense.expense_expense_categories.forEach(x => {
        control.push(this.fb.group(x));
      })
    }
    

    然后到模板,这个例子是没有Angular Material的:

    <form [formGroup]="expenseEditForm">
      <label>Notes: </label>
      <input formControlName="notes" /><br>
      <!-- Declare formArrayName -->
      <div formArrayName="expense_expense_categories_attributes">
        <!-- iterate formArray -->
        <div *ngFor="let d of expenseEditForm.get('expense_expense_categories_attributes').controls; let i=index"> 
          <!-- Use the index for each formGroup inside the formArray -->
          <div [formGroupName]="i">
          <label>Amount: </label>
            <input formControlName="amount" />
          </div>
        </div>
      </div>
    </form>
    

    终于来了

    Demo

    【讨论】:

    • 哪种方法最好? Deborah 链接的 APM-Updated 演示是更好的解决方案吗?我应该转换对象并实例化一个费用类别类,还是我尝试的方法更好?您的演示不会使用值填充金额字段。你能更新演示来说明这一点吗?
    • @Alex 我遵循了这个解决方案,发现 FormArray 中的 FormGroup 每次都会被推送,导致显示的 FormGroup 比需要的多。
    • @20B2 回答这个问题已经有一段时间了:D 但我不明白为什么这个解决方案会导致这样的问题。你能否提供一个关于你的问题的堆栈闪电战,我很乐意看看:)
    • @Alex 我已经在模态中使用了您的解决方案。我第一次打开模态,结果很好。但是当我关闭模态并重新打开同一个模态或打开另一个模态时,FormGroup 会被推送到先前推送的数组,从而导致更多的 FormGroups。我通过传递布尔参数解决了这个问题。每当模态关闭时,我将 false 作为参数传递并清除控件数组。目前我正在寻找更好的解决方案,但它现在工作正常。
    • @20B2 您正在进行某种不同的设置,因为对于这种情况和手头的问题,此解决方案可以解决问题。但是您使用的是模式,所以这是一个不同的场景,并且似乎它确实像您说的那样将新的表单组推送到现有的表单数组,这将是预期的行为。所以是的,我想你需要清除它。很难说别的,因为没有代码可以看:)
    【解决方案2】:

    如果我正确理解你的问题,你可能需要这样的东西:

        // Update the data on the form
        this.productForm.patchValue({
            productName: this.product.productName,
            productCode: this.product.productCode,
            starRating: this.product.starRating,
            description: this.product.description
        });
        this.productForm.setControl('tags', this.fb.array(this.product.tags || []));
    

    您可以在此处查看完整示例:https://github.com/DeborahK/Angular2-ReactiveForms 在 APM - 更新文件夹中。

    【讨论】:

    • 酷。我查看了示例应用程序,明天我将尝试实现它。 CRUD 操作占我编程工作的 95%。
    • 试试这个:this.tags.at(index).patchValue(text);
    猜你喜欢
    • 2022-08-23
    • 2017-09-27
    • 2018-11-15
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    • 2022-10-20
    • 2018-12-11
    • 2018-06-04
    相关资源
    最近更新 更多