角度2模型驱动的嵌套表单组件 [英] angular 2 model driven nested form components

查看:99
本文介绍了角度2模型驱动的嵌套表单组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有什么:

我正在构建一个离子2应用程序并构建了一个包含

I am building an ionic 2 app and have built a basic angular 2 component that contains


  • 输入字段

  • An input field

显示输入标题的标签

显示任何验证错误的标签

A label to display any validation errors

我将此作为我的输入组件引用

I will refer to this as my input component

我有一个页面组件,其上有一个表单,并且当前有文本输入。 1个常规输入(密码)和1个输入包装在我的输入组件(用户名)中。

I have a page component with a form on it, and currently have text inputs. 1 regular input (password) and 1 input wrapped in my input component (username).

这是我的页面组件的相关部分

ngOnInit() {
  this.loginForm = this.formBuilder.group({
    username: ['', Validators.required],
    password: ['', Validators.required]
  });
}

这是页面组件模板

<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">

  <!-- My input component -->
  <aw-input-text id="username" name="Username" [formInput]="loginForm.controls.username"></aw-input-text>

  <!-- A standard input control -->
  <ion-item [class.error]="loginForm.controls.password.errors">
    <ion-label floating>Password</ion-label>
    <ion-input type="text" value="" name="password" formControlName="password"></ion-input>
    <p *ngIf="loginForm.controls.password.errors">This field is required!</p>
  </ion-item>

  <button type="submit" class="custom-button" [disabled]="!loginForm.valid" block>Login</button>

</form>

这是我输入组件的模板

<!-- Component template -->
<form [formGroup]="formGroup">
    <ion-item>
        <ion-label floating>{{inputName}}</ion-label>
        <ion-input type="text" formControlName="inputValue"></ion-input>
        <p *ngIf="!formGroup.controls.inputValue.valid">This field is required!</p>
    </ion-item>
</form>

这是输入组件

import {Component, Input} from '@angular/core';
import {FormBuilder} from '@angular/forms';

@Component({
  selector: 'aw-input-text',
  templateUrl: 'build/shared/aw-input-text/aw-input-text.html'
})
export class AwInputText {

  @Input('formInput')
  public formInput;
  @Input('name')
  public inputName;
  public formGroup;
  constructor(private formBuilder: FormBuilder) {
  }

  ngOnInit() {
     this.formGroup = this.formBuilder.group({
        inputValue: this.formInput
     });
  }

}

组件正确呈现。

问题:

组件内的输入不会更新有效状态它所在的形式。

The input inside the component doesn't update the valid state of the the form it is in.

当我填写用户名时,表格变为有效的密码

When I fill out the username then the password the form becomes valid

当我填写密码时,表单的用户名仍然无效

When I fill out the password then the username the form remains invalid

因此表单可以查看输入组件的有效状态,它是只是输入组件更改有效状态不会触发表单更新。

So the form can see the valid state of the input component, it's just that the input component changing valid state doesn't trigger the form to update.

可能的解决方案1 ​​

如本文所述和plunk

As described in this article and plunk

https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2

https://plnkr.co/edit/clTbNP7MHBbBbrUp20vr?p=preview

我可以修改我的页面组件,用于创建一个表单组,其中包含我想在输入组件中使用的每个表单控件的嵌套表单组

I could modify my page component to create a form group that contains a nested form group for every form control that I want to use inside of my input component

ngOnInit() {
  this.loginForm = this.formBuilder.group({
    username: this.formBuilder.group({
      username: ['', Validators.required],
    }),
    password: ['', Validators.required],
  });
}

此解决方案适合文章中添加输入数组的场景控制,但在我的情况下,我认为这感觉hacky

This solution fits the scenario in the article where they are adding an array of input controls, but in my case I think this feels hacky

可能的解决方案2

我考虑的另一个hacky解决方案是使用输入组件中的@output指令触发页面组件上的事件,每当输入组件更新时刷新表单。

Another hacky solution I have considered is using an @output directive from my input component to trigger an event on the page component that refreshes the form whenever the input component is updated.

更新到输入组件

this.formGroup.controls.inputValue.valueChanges.subscribe(value => {
  this.formUpdated.emit({
    value: value
  })
});

更新页面组件

public onUpdated(value){
  this.loginForm.updateValueAndValidity();
}

并更新页面组件模板

<aw-input-text id="username" name="Username" (updated)="onUpdated($event)" [formInput]="loginForm.controls.username"></aw-input-text>

这确实给了我所需的功能,但我觉得看起来有点hacky有一个事件处理程序在每个表单页面上使输入组件工作。

This does give me the desired functionality, but I think it also seems a bit hacky having an event handler on every form page to make the input component work.

问题

有没有办法让我的组件更新其所在表单的有效状态(请记住,我希望在每种形式中多次重复使用此组件),而无需借助上述解决方案。

Is there a way for me to make my component update the valid state of the form it is in (keeping in mind that I would want to re-use this component multiple times in each form) without resorting to the solution described above.

推荐答案

谢谢你的回答。最后,我们创建了两个组件,一个自定义表单组件和一个自定义输入组件。

Thanks for the answers guys. In the end we created two components, a custom-form component and a custom-input component.

我们在自定义内容中嵌入了尽可能多的自定义输入组件 - 表单组件和自定义表单组件使用@ContentChildren来标识和注册所有子自定义输入组件。

We nest as many custom-input components as we need inside the custom-form component and the custom-form component uses @ContentChildren to identify and register all the child custom-input components.

这样我们就不必将表单传递给每个输入,我们没有为每个输入乱七八糟的嵌套表单组。

This way we don't have to pass the form into every input, and we don't have a mess of nested form groups for every input.

// Each CustomInputText component exposes a FormControl and 
// a control definition which has additional info about the control
@ContentChildren(CustomInputText, {descendants: true})
public customInputComponents: QueryList<CustomInputText>;

private initialised;

public ngAfterContentChecked() {
  // Only initialise the form group once
  if (!this.initialised) {
    this.initialised = true;
    this.customInputComponents.forEach((input)=>{
        this.formGroup.addControl(input.controlDefinition.id, input.formControl); 
    });
  }
}

这篇关于角度2模型驱动的嵌套表单组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆