【问题标题】:Angular Reactive Forms, way to bind data object with every object of FormArrayAngular Reactive Forms,将数据对象与 FormArray 的每个对象绑定的方法
【发布时间】:2023-04-11 03:36:01
【问题描述】:

我正在构建如下图所示的反应形式-

如图所示,每个文件(代码中称为附件)中都有多个议程。议程可以添加、更新和删除

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

  ])
});

从 web 服务获取表单数据并以这种方式创建表单模型-

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)而不是两个数组(Form 数组和提交对象)来构建模板,否则如果一个更改直到其他更改控制台将抛出错误。但是如何只使用FormArray,我在提交对象中有一些数据?有没有办法将提交对象与 FormArray 绑定?

我厌倦了https://github.com/angular/angular/issues/13845,但没有成功,因为我正在使用表单构建并且不知道如何使用表单构建器来完成这个技巧

【问题讨论】:

  • 你能在 plunker 或 stackblitz 中给出你的整个代码吗?
  • 您的 buildForms() 方法在您的帖子中是否完整?

标签: angular angular-reactive-forms reactive-forms


【解决方案1】:

如果您首先考虑获得的数据,会更容易。我想你会得到一些喜欢

[{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>

好吧,最后一步是创建函数add、delete和addAgenda

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看到“丑陋”的结果

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-24
    • 2021-05-30
    • 2022-12-27
    • 1970-01-01
    • 2018-10-13
    • 1970-01-01
    相关资源
    最近更新 更多