用验证器包装角度反应形式组件 [英] Wrapping angular reactive form component with validator

查看:22
本文介绍了用验证器包装角度反应形式组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 angular 7 和 Bootstrap 4,我想将 bootstrap 4 输入包装在自定义组件中,以减少模板中的样板.

我希望最终的主要组件看起来像:

<app-form-control label="Lastname" placeholder="Lastname" formControlName="lastName"></app-form-control><app-form-control label="Firstname" placeholder="Firstname" formControlName="firstName"></app-form-control><button class="pull-right" type="submit">提交<按钮(点击)="reset()">重启</表单>

我的 formGroup 是这样创建的:

public createFormGroup() {返回 this.fb.group({firstName: [null, Validators.required],姓氏:[null,Validators.required],});}

app-form-control 的模板应该是这样的:

<label class="col-2 col-form-label">{{label}}</label><div class="col-10"><input class="form-control" placeholder="{{placeholder}}" [formControlName]="formControlName" autocomplete="nope"/>

但我不知道如何编写组件(在 TypeScript 中).如何将外部 formControlName 属性绑定到内部输入字段?如何进行验证?

解决方案

关键"是使用 viewProvider.您使用 @Input 集为 formControl 赋值,请参阅 堆叠闪电战.神奇"在于,如果相等,则引用子项"中的 formControl 或父项中的 form.get('input1')

@Component({选择器:'app-form-control',模板:`<div class="form-group row"><label class="col-2 col-form-label">{{label}}</label><div class="col-10"><input class="form-control" placeholder="{{placeholder}}"[formControl]="formControl" autocomplete="nope"/>

<!--可以控制formControl的属性-->{{formControl.valid}}{{formControl.touched}}}`,viewProviders: [{ 提供: ControlContainer, useExisting: FormGroupDirective }]})导出类 HelloComponent {表单控件:表单控件;构造函数(私有 parentF:FormGroupDirective){}@输入()设置控件名称(值){this.formControl = this.parentF.form.get(value) as FormControl}@Input() 标签:字符串;@Input() 占位符:字符串;}

并以这种方式调用组件:

<app-form-control label="Lastname" placeholder="Lastname" controlName="lastName"></app-form-control></表单>

更新好吧,(一年后)考虑到 stackblitz 是错误的.当您(单击)按钮创建一个新表单时:

 this.form=this.createForm({note:'llll'})

这破坏"了组件和表单之间的关系,因为关系是关于旧表单的 - 只有在更改@InputnameControl"时才会更改.所以正确的做法是使用 setValue 为表单赋予一个新值.

Working with angular 7 and Bootstrap 4, I want to wrap my bootstrap 4 inputs in a custom component in order to reduce the boilerplate in my templates.

I want that the final main component look like:

<form [formGroup]="myForm" (submit)="submit(myForm.value)">

    <app-form-control label="Lastname" placeholder="Lastname" formControlName="lastName"></app-form-control>
    <app-form-control label="Firstname" placeholder="Firstname" formControlName="firstName"></app-form-control>

    <button class="pull-right" type="submit">
        SUBMIT
    </button>
    <button (click)="reset()">
        RESET
    </button>
</form>

Where my formGroup is created like this:

public createFormGroup() {
    return this.fb.group({
        firstName: [null, Validators.required],
        lastName: [null, Validators.required],
    });
}

The template of app-form-control should look like this:

<div class="form-group row">
  <label class="col-2 col-form-label">{{label}}</label>
  <div class="col-10">
    <input class="form-control" placeholder="{{placeholder}}" [formControlName]="formControlName" autocomplete="nope"/>
  </div>
</div>

But I don't know how to write the component (in TypeScript). How do I bind the outer formControlName attribute to the inner input field? How to make validation work?

解决方案

The "key" is using viewProvider. You use a @Input set to give value to a formControl, see stackblitz. The "magic" is that if equal refered to formControl in the "children" or form.get('input1') in the parent

@Component({
  selector: 'app-form-control',
  template: `
  <div class="form-group row">
  <label class="col-2 col-form-label">{{label}}</label>
  <div class="col-10">
    <input class="form-control" placeholder="{{placeholder}}"
    [formControl]="formControl" autocomplete="nope"/>
  </div>
  </div>
  <!--you can control the properties of formControl-->
  {{formControl.valid}}{{formControl.touched}}}
`,
viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }]})
export class HelloComponent {

  formControl: FormControl;

  constructor(private parentF: FormGroupDirective) { }

  @Input() 
  set controlName(value) {
    this.formControl = this.parentF.form.get(value) as FormControl
  }

  @Input() label: string;
  @Input() placeholder: string;

}

And call the component this way:

<form [formGroup]="myForm" (submit)="submit(myForm.value)">
    <app-form-control label="Lastname" placeholder="Lastname" controlName="lastName"></app-form-control>
</form>

Update well, (after a year) take account the stackblitz was erroneous. when you (click) in buttons create a new Form:

 this.form=this.createForm({note:'lll'})

This "break" the relationship between the component and the form because the relation is about the older form -only change if change the @Input "nameControl". So the correct is use a setValue to give a new value to the form.

这篇关于用验证器包装角度反应形式组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆