簡體   English   中英

Angular Reactive Forms,將數據對象與 FormArray 的每個對象綁定的方法

[英]Angular Reactive Forms, way to bind data object with every object of FormArray

我正在構建如下圖所示的反應形式-

如圖所示,每個文件(在代碼中稱為附件)都有多個議程。 可以添加、更新和刪除議程

在此處輸入圖片說明

buildForms() {
this.agendaForms = this.formBuilder.group({
  attachements: this.formBuilder.array([

  ])
});

表單數據是從 webservice 中獲取的,表單模型是這樣創建的 -

data => {
    this.submission = data;

    // New blank agenda for all attachements
    if (
      !isNullOrUndefined(this.submission) &&
      !isNullOrUndefined(this.submission.attachments)
    ) {
      this.submission.attachments.forEach(attachment => {
        const agenda = new NLAgenda();
        agenda.dwgNo = attachment.filename;
        agenda.dWGNo = attachment.filename;
        this.submission.agendas.push(agenda);

        if (!isNullOrUndefined(attachment)) {
          attachment.agendas = this.getAgendasForAttachment(attachment);

          if (!isNullOrUndefined(attachment.agendas)) {
            this.attachmentFormArray = this.agendaForms.controls
              .attachements as FormArray;
            this.attachmentFormArray.push(
              this.createAttachmentAgendasControl(attachment.agendas)
            );
          }
        }
      });
    }
  }

模板看起來像這樣

<form [formGroup]="agendaForms">
    <div formArrayName="attachements">
      <div *ngFor="let attachmentFormGroup of attachmentFormArray.controls;
          let attachmentId = index">

        <!-- Attachment header-->
        <div>
          <!-- File Name-->
          <div>
            {{ submission.attachments[attachmentId].filename }}
          </div>

          <!-- Action Buttons-->
          <div>
            <input type="button" value="Link To"/>
          </div>
        </div>

        <!-- Agendas -->
        <div formGroupName="{{ attachmentId }}">
          <div formArrayName="agendas">
            <div *ngFor="let agendaFormGroup of attachmentFormGroup.controls.agendas.controls;
                let agendaId = index">
              <div formGroupName="{{ agendaId }}" >
                <mat-form-field>
                  <input
                    type="text"
                    id="project"
                    placeholder="Sheet No."
                    formControlName="sheetNumber"
                    matInput
                  />
                  <!-- <mat-error>{{ getErrorMessage(f.project) }}</mat-error> -->
                </mat-form-field>
                <mat-form-field>
                  <input
                    type="text"
                    id="project"
                    placeholder="Title"
                    formControlName="title"
                    matInput
                  />
                </mat-form-field>
                <mat-form-field>
                  <input
                    type="text"
                    id="project"
                    placeholder="Description"
                    formControlName="description"
                    matInput
                  />
                </mat-form-field>

                <div>
                  <a
                    matTooltip="Add Agenda"
                    aria-label="Add Agenda"
                    (click)="
                      createOrUpdateAgenda(
                        submission.attachments[attachmentId].agendas[agendaId],
                        attachmentId,
                        agendaId
                      )">
                    <i class="fa fa-check"></i>
                  </a>
                  <a
                    *ngIf="submission.attachments[attachmentId].agendas[agendaId].created != null && submission.attachments[attachmentId].agendas[agendaId].created != undefined"
                    matTooltip="Delete Agenda"
                    aria-label="Delete Agenda"
                    (click)="deleteAgenda(submission.attachments[attachmentId].agendas[agendaId])">
                    <i class="fa fa-remove"></i>
                  </a>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </form>

問題:每當添加或更新議程時,我從服務器重新獲取提交對象數據以顯示文件和議程的更新狀態,提交對象更改並在控制台中出現錯誤,例如“無法讀取未定義的屬性‘議程’”,因為在新的提交對象位置舊對象因新增或刪除而改變

我相信我只需要使用一個數組(FormArray)而不是兩個數組(表單數組和提交對象)來構建模板,否則如果一個更改直到其他更改控制台將拋出錯誤。 但是如何只使用 FormArray,我在提交對象中有一些數據? 有沒有辦法用 FormArray 綁定提交對象?

我厭倦了https://github.com/angular/angular/issues/13845但沒有成功,因為我正在使用表單構建並且不知道如何使用表單構建器來做這個技巧

如果您首先考慮獲得的數據,這會更容易。 我想你得到一些喜歡

[{filename:..,agenda:[
                     {sheetNumber:..,title:...,description...},
                     {sheetNumber:..,title:...,description...}
                          ...
                     ]
  },
  {filename:..,agenda:[
                     {sheetNumber:..,title:...,description...},
                     {sheetNumber:..,title:...,description...}
                          ...
                     ]
  }
  ....
]

你看到你有一個 FormArray,(一系列 FormGroup),它有兩個屬性,“filename”和“agenda”(Agenda 是一個新的 FormArray)

將變量聲明為 formArray

  form: FormArray

並創建兩個函數。

createItemData(data):FormGroup
  {
    data=data|| {} as dataI;
    return new FormGroup(
      {
         filename:new FormControl(data.filename),
         agenda:new FormArray(data.agenda && data.agenda.length?
               data.agenda.map(agenda=>this.createAgendaSheet(agenda)):
               [])
      }
    )

  }
  createAgendaSheet(data):FormGroup{
    data=data|| {} as agendaI;
    return new FormGroup(
      {
        sheetNumber:new FormControl(data.sheetNumber),
        title:new FormControl(data.title),
        description:new FormControl(data.description),

      }
    )
  }

查看此函數如何創建數組元素。 我使用接下來的兩個界面來幫助我創建表單

export interface agendaI {
  sheetNumber: number,
  title: string,
  desription: string
}
export interface dataI {
  filename: string,
  agenda: agendaI[]
}

好吧,創建表單時要小心:

<button (click)="addAgenda()">Add agenda</button>
<form *ngIf="form" [formGroup]="form">
    <!--form is a FormArray, so form.controls will be formGroup-->
    <div *ngFor="let control of form.controls;let i=index">
       <!--in this form group...-->
        <div [formGroup]="control">
            <!--we have a fromControl "filename"-->
            <input formControlName="filename"/><button (click)="add(i)">add</button>
      <!--and a FormArray "agenda"--->
      <div formArrayName="agenda">
        <div *ngFor="let c of control.get('agenda').controls;let j=index" >
          <div [formGroupName]="j">
            <input formControlName="sheetNumber">
            <input formControlName="title">
            <input formControlName="description">
            <button (click)="delete(i,j)">delete</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</form>

好吧,最后一步是創建函數添加、刪除和添加議程

addAgenda()
  {
    this.form.push(this.createItemData(null))
  }
  add(i)
  {
    (this.form.at(i).get('agenda') as FormArray).push(this.createAgendaSheet(null))
  }
  delete(i,j)
  {
    (this.form.at(i).get('agenda') as FormArray).removeAt(j)
  }

並且,在 ngOnInit 中創建表單(我使用了一個常量“數據”)

 ngOnInit() {
    this.form=new FormArray(data.map(d=>this.createItemData(d)));
  }

你可以在stackblitz中看到“丑陋”的結果

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM