简体   繁体   English

Angular 5中的嵌套表单

[英]Nested Forms in Angular 5

I'm trying to create components which may have nested forms. 我正在尝试创建可能具有嵌套表格的组件。 I'm nesting them because I'd like validation at multiple stages, even though I'll save only once. 我嵌套它们是因为我希望在多个阶段进行验证,即使我只保存一次。 Maybe there's another solution to my problem, but right now my code looks a bit like this: 也许有另一个解决方案可以解决我的问题,但是现在我的代码看起来像这样:

<form (submit)="save()" #form1="ngForm">
    <form (submit)="accept()" #form2="ngForm">
        <!-- #form2 fields -->
        <button id="submit2" type="submit" />
    </form>
    <!-- #form1 fields -->
    <button id="submit1" type="submit" />
</form>

When I click #submit2 button, it submits my #form1 form, which I did not expect. 当我单击#submit2按钮时,它将提交我没有想到的#form1表单。 How could this be solved? 如何解决呢?

UPDATE: 更新:

I found out that I can specify the form in the button's attributes: 我发现可以在按钮的属性中指定表单:

<button id="submit1" type="submit" form="form1" />

This works exactly like I expected it. 这完全符合我的预期。

Nesting forms the way you do is not an ideal scenario. 嵌套以您的方式形成不是一个理想的方案。 There are better ways to achieve this. 有更好的方法可以实现这一目标。 One of these is using Reactive Forms. 其中之一是使用反应形式。 Let's start with an example. 让我们从一个例子开始。

my-custom-address.component.ts my-custom-address.component.ts

@Component({
 selector: 'my-custom-address'
 template: `
  <label>Street</label>
  <input type="text" [formControl]="group.controls.street" />

  <label>City</label>
  <input type="text" [formControl]="form.controls.city" /> 
 `
})
export class MyCustomAddressComponent {
 @Input() group: FormGroup;
}

We have a custom component that holds the nested part of our form. 我们有一个自定义组件,用于保存表单的嵌套部分。 The component receives a part of the form that we built using the FormBuilder provided by Angular. 该组件接收我们使用Angular提供的FormBuilder构建的一部分表单。

app.component.ts app.component.ts

@Component({
 selector: 'app-component'
 template: `
   <form (submit)="save()">
   <label>First name</label>
   <input type="text" [formControl]="form.controls.firstName" />

   <label>Last name</label>
   <input type="text" [formControl]="form.controls.lastName" />

   <my-custom-address [group]="form.controls.address"></my-custom-address> 
  </form>
 `
})
export class AppComponent {
  form: FormGroup = this.fb.group({
   firstName: [null],
   lastName: [null],
   address: this.fb.group(
    {
      street: [null, [Validators.required]],
      city: [null]
    },
    {
     validators: [CUSTOM_GROUP_VALIDATOR]
    } 
   )
  });

 constructor(private fb: FormBuilder) {}
}

The app components holds our complete form configuration. 应用程序组件包含我们完整的表单配置。 If you look closely you can that the address control of our form has a nested structure which holds both the street and city. 如果您仔细观察,可以发现我们表单的地址控件具有嵌套的结构,既可以容纳街道又可以容纳城市。 The interesting thing about this approach is that you can assign custom validators to a group of those controls (see CUSTOM_GROUP_VALIDATOR). 这种方法的有趣之处在于,您可以将自定义验证器分配给这些控件的组(请参阅CUSTOM_GROUP_VALIDATOR)。 This way you can decide how the validation should work and kinda controls when it happens. 这样,您可以决定验证的工作方式并在验证发生时进行控制。

If you were to check if the form as a whole is valid you can use this.form.valid which returns a boolean. 如果要检查整个表单是否有效,则可以使用this.form.valid ,它返回一个布尔值。

As this example can be quit overwhelming make sure to check out the documentation of Angular about Reactive Forms and custom form validators. 由于此示例可能会让人不知所措,因此请务必查看Angular有关反应性表单和自定义表单验证器的文档。 Using the documentation and my example you should be guided into the right direction ;). 使用文档和我的示例,您应该被引导至正确的方向;)。

Reactive Forms: https://angular.io/guide/reactive-forms 反应形式: https : //angular.io/guide/reactive-forms

Custom Form Validators: https://angular.io/guide/form-validation#cross-field-validation 自定义表单验证器: https//angular.io/guide/form-validation#cross-field-validation

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

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