简体   繁体   English

如何将 FormArray 与 Angular 反应式 forms 的 FormGroups 一起使用?

[英]How can I use FormArray with FormGroups with Angular reactive forms?

I am trying to mimic my model in my reactive form.我试图以我的反应形式模仿我的 model。 I've set up a few FormGroups to "nest" things that make sense according to my model. I'm having trouble setting up my component to read the values--which suggests that I likely don't have my template set up correctly either.我已经设置了一些 FormGroups 来“嵌套”根据我的 model 有意义的东西。我在设置我的组件以读取值时遇到了问题——这表明我可能没有正确设置我的模板任何一个。

Depending if I am editing an existing location or creating a new one,取决于我是在编辑现有位置还是创建新位置,

@Input() location: ILocation;

could be undefined .可能是undefined的。 Currently I am only focused on working with an existing location, so I know location has a value.目前我只专注于使用现有位置,所以我知道location是有价值的。

// location.model.ts

name: string;
...
messaging: [
    {
        email: {
            fromName: string;
            fromAddress: string;
        };
    }
];
...
createdAt?: string;
updatedAt?: string;
deletedAt?: string;

In my template I am using ngClass to give the user validation feedback:在我的模板中,我使用ngClass为用户提供验证反馈:

// location.commponent.html

<div formGroupName="messaging">
    <div formGroupName="email">
        ...
        <div [ngClass]="form.get(['messaging', 'email', 'fromName'])!.errors && (form.get(['messaging', 'email', 'fromName'])!.dirty || form.get(['messaging', 'email', 'fromName'])!.touched) ? 'red' : 'green'">
            <input name="fromName"/>
        </div>
        <!-- fromAddress -->
    </div>
</div>

In my component, I am passing the model in with input binding, then setting up my form goup(s) and form fields like this:在我的组件中,我通过输入绑定传递 model,然后设置我的表单组和表单字段,如下所示:

// location.component.ts

@Input() location: ILocation; 

form: FormGroup;

...

ngOnInit(): void {
    this.form = new FormGroup({name: new FormControl(this.location.name, [Validators.required]),
    messaging: new FormGroup({
    email: new FormGroup({
        fromName: new FormControl(this.location.messaging[0].email.fromName, [Validators.required]),
        fromAddress: new FormControl(this.location.messaging[0].email.fromAddress, [Validators.required]),
        }),
    }),
}

The error I am seeing is:我看到的错误是:

Cannot read properties of undefined (reading 'email')无法读取未定义的属性(读取“电子邮件”)

If I log out what is in the component:如果我注销组件中的内容:

console.log('messaging: ', this.location.messaging);

// email: {fromName: 'No Reply <noreply@example.com>', fromAddress: 'noreply@example.com'}

I've tried various methods of messaging['email'] or messaging.email messaging[0] but I can't seem to find the correct path.我尝试了各种messaging['email']messaging.email messaging[0]方法,但我似乎找不到正确的路径。

I am also not sure if I am using the get() method correctly in my template.我也不确定我是否在我的模板中正确使用了get()方法。

How can I set up my form to read/present the data correctly?如何设置我的表单以正确读取/显示数据?

Update:更新:

Not surprisingly, a big problem I was having was sending the wrong shape of data back.毫不奇怪,我遇到的一个大问题是发回错误形状的数据。

In the end, this is the JSON I am trying to create:最后,这是我要创建的 JSON:

[{"email":{"fromName":"No Reply <noreply@example.com>","fromAddress":"noreply@example.com"}}]

It looks like I need to use FormArray to send the proper shape:看起来我需要使用FormArray来发送正确的形状:

messaging: new FormArray([
    new FormGroup({
        email: new FormGroup({
            fromName: new FormControl(this.location.messaging[0].email.fromName, [Validators.required]),
            fromAddress: new FormControl(this.location.messaging[0].email.fromAddress, [Validators.required]),
        }),
    }),
]),

This is causing some trouble in my template as I'm currently doing this: form.get('messaging[0].email.fromAddress')这在我的模板中造成了一些麻烦,因为我目前正在这样做: form.get('messaging[0].email.fromAddress')

Resulting in:导致:

Error: Cannot find control with path: 'messaging -> email'错误:找不到路径为“消息传递 -> 电子邮件”的控件

I think I need to somehow loop through the FormArray .我想我需要以某种方式循环遍历FormArray This really isn't a dynamic array though.不过,这确实不是动态数组。 I'll always have email and only fromName and fromAddress .我将始终拥有email并且只有fromNamefromAddress

Yes, you need the FormArray as the messaging is an array.是的,您需要FormArray ,因为messaging是一个数组。

You need to iterate every element in FormArray via *ngFor and provide the index ( i ):您需要通过*ngFor迭代FormArray中的每个元素并提供索引( i ):

form.get(['messaging', i, 'email', 'fromName'])

The complete flow of your template form from parent FormGroup to fromName FormControl would be:从父 FormGroup 到fromName FormControl的模板表单的完整流程是:

form ( FormGroup ) --> messaging ( FormArray ) --> i ( FormGroup ) --> email ( FormGroup ) --> fromName ( FormControl )表单 ( FormGroup ) --> 消息 ( FormArray ) --> i ( FormGroup ) --> email( FormGroup ) --> fromName( FormControl )

The HTML template should be: HTML 模板应该是:

<div [formGroup]="form">
  <div
    formArrayName="messaging"
    *ngFor="let control of messaging.controls; let i = index"
  >
    <ng-container [formGroupName]="i">
      <div formGroupName="email">
        ...
        <div
          [ngClass]="
            form.get(['messaging', i, 'email', 'fromName'])!.errors &&
            (form.get(['messaging', i, 'email', 'fromName'])!.dirty ||
              form.get(['messaging', i, 'email', 'fromName'])!.touched)
              ? 'red'
              : 'green'
          "
        >
          <input formControlName="fromName" />
        </div>
        <div>
          <!-- fromAddress -->
          <input formControlName="fromAddress" />
        </div>
      </div>
    </ng-container>
  </div>
</div>
get messaging(): FormArray {
  return this.form.get('messaging') as FormArray;
}

Demo @ StackBlitz 演示 @ StackBlitz

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM