将 formControlName 用于反应形式的自定义输入组件 [英] use formControlName for custom input component in reactive form

查看:40
本文介绍了将 formControlName 用于反应形式的自定义输入组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个自定义输入组件,它以带有验证的反应形式使用:

@Component({moduleId: module.id.toString(),选择器:'自定义选择',templateUrl: 'custom-select.component.html',styleUrls: ['custom-select.component.css']})导出类 CustomSelectComponent {@Input() 公共项:SelectModel[];公共模型:SelectModel;构造函数(私有自定义选择服务:自定义选择服务){this.customSelectService.Selected.subscribe((data: SelectModel) => {this.model = 数据;});}公共新选择(选择:SelectModel):无效{this.customSelectService.updateSelected(select);}}

工作正常,我在反应形式中使用 custom-select 并想像下面一样验证它:

</custom-select><div *ngIf=" myFrom.controls['country'].invalid && (myFrom.controls['country'].dirty||myFrom.controls['country'].touched) " class="ha-control-alert"><div *ngIf="myFrom.controls['country'].hasError('required')">国家/地区为必填项

这就是我在组件中声明表单的方式

this.myFrom = this.formBuilder.group({国家:[null,Validators.required],})

但是当我添加 formControlName 进行验证时,它会收到错误消息,显示没有名称的表单控件的值访问器:'国家'.我该如何处理?

解决方案

STEPS

  1. 在装饰器中添加 NG_VALUE_ACCESSOR 的提供者
  2. 在类中实现 ControlValueAccessor
  3. 像这样创建 onChange 函数 onChange = (value: boolean) =>{};
  4. 添加 ControlValueAccessor 接口的 registerOnChange、writeValue 和 registerOnTouched 方法
  5. 在更改select值的方法中,调用onChange函数,将select的值作为参数传递.

 导入 ...从@angular/core"导入 { Component, forwardRef };从@angular/forms"导入 { ControlValueAccessor, NG_VALUE_ACCESSOR };@成分({moduleId: module.id.toString(),选择器:'自定义选择',templateUrl: 'custom-select.component.html',styleUrls: ['custom-select.component.css'],//第1步提供者:[{提供:NG_VALUE_ACCESSOR,多:真实,useExisting: forwardRef(() => CustomSelectComponent)}]})//第2步导出类 CustomSelectComponent 实现 ControlValueAccessor {//第 3 步onChange = (value: SelectModel) =>{};@Input() 公共项:SelectModel[];公共模型:SelectModel;构造函数(私有 customSelectService:CustomSelectService){this.customSelectService.Selected.subscribe((data: SelectModel) => {this.model = 数据;});}公共新选择(选择:SelectModel):无效{//第 5 步this.onChange(选择);this.customSelectService.updateSelected(select);}//第四步registerOnChange(fn: (value: SelectModel) => void): void {this.onChange = fn;}写值(){}registerOnTouched(){}}

不要忘记在选择器中添加 formControlName.

There is a custom input component and it is used in a reactive form with validation:

@Component({
    moduleId: module.id.toString(),
    selector: 'custom-select',
    templateUrl: 'custom-select.component.html',
    styleUrls: ['custom-select.component.css']
})
export class CustomSelectComponent {
    @Input() public items: SelectModel[];
    public model: SelectModel;
    constructor(private customSelectService: CustomSelectService) {
        this.customSelectService.Selected.subscribe((data: SelectModel) => {
            this.model = data;
        });
    }
    public newSelect(select: SelectModel): void {
        this.customSelectService.updateSelected(select);
    }
}

which works fine, I am using custom-select in a reactive form and want to validate it like below:

<custom-select id="country" [items]="selectItems" formControlName="country"></custom-select>
<div *ngIf=" myFrom.controls['country'].invalid && (myFrom.controls['country'].dirty 
             || myFrom.controls['country'].touched) " class="ha-control-alert">
    <div *ngIf="myFrom.controls['country'].hasError('required')">Country is required</div>
</div>

this is how I declare the form in component

this.myFrom = this.formBuilder.group({
    country: [null, Validators.required],
})

but when I add formControlName for validations, it gets error which says No value accessor for form control with name: 'country'. How should I handle this?

解决方案

STEPS

  1. Add the provider for NG_VALUE_ACCESSOR in the decorator
  2. Implement the ControlValueAccessor in the class
  3. Create the onChange function like this onChange = (value: boolean) => {};
  4. Add the registerOnChange, writeValue and registerOnTouched methods of the ControlValueAccessor interface
  5. In the method that will be changed the value of select, call the onChange function passing as parameter the value of select.

        import ...
        import { Component, forwardRef } from '@angular/core';
        import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
        
    
        @Component({
            moduleId: module.id.toString(),
            selector: 'custom-select',
            templateUrl: 'custom-select.component.html',
            styleUrls: ['custom-select.component.css'],
            // STEP 1
            providers: [{
              provide: NG_VALUE_ACCESSOR,
              multi: true,
              useExisting: forwardRef(() => CustomSelectComponent)
            }]
        })
        // STEP 2
        export class CustomSelectComponent implements ControlValueAccessor {
            // STEP 3
            onChange = (value: SelectModel) => {};
            @Input() public items: SelectModel[];
            public model: SelectModel;
            constructor(private customSelectService: CustomSelectService) {
                this.customSelectService.Selected.subscribe((data: SelectModel) => {
                    this.model = data;
                });
            }
            public newSelect(select: SelectModel): void {
                // STEP 5
                this.onChange(select);
                this.customSelectService.updateSelected(select);
            }
            // STEP 4
            registerOnChange(fn: (value: SelectModel) => void): void {
                this.onChange = fn;
            }
            writeValue() {}
            registerOnTouched(){}
        }

Don't forget to add the formControlName in the selector.

这篇关于将 formControlName 用于反应形式的自定义输入组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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