如何创建自定义响应式表单元素?

Posted

技术标签:

【中文标题】如何创建自定义响应式表单元素?【英文标题】:How do I create a custom Reactive Form Element? 【发布时间】:2019-06-08 18:59:58 【问题描述】:

我正在使用 Angular 中的反应式表单,我正在尝试创建一个自定义表单元素,以便我可以在我的表单中使用按钮。我正在尝试遵循Alligator.io 的教程,但不清楚如何将其集成到我的组件中。目前我收到以下错误。

ERROR Error: No value accessor for form control with name: 'coverage_for_domestic_partners'

以下是我的代码,如果有任何帮助,将不胜感激。

// html

<div class="button-group" [formGroup]="group">
    <button
        *ngFor="let option of config.options"
        class="button button--toggle"
        [ngClass]='"is-active": option.selected'
        (click)="select($event, option)"
        [formControlName]="config.key">
        <div class="button-content">option.key</div>
    </button>
</div>

// 组件

import  Component, OnInit, Input, forwardRef, HostBinding  from '@angular/core';
import  FormGroup, ControlValueAccessor, NG_VALUE_ACCESSOR  from '@angular/forms';

@Component(
 selector: 'z-toggle-group',
 templateUrl: './z-toggle-group.component.html',
 styleUrls: ['./z-toggle-group.component.scss'],
 providers: [

  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => ZToggleGroupComponent),
  multi: true

  ]


 )
export class ZToggleGroupComponent implements OnInit, ControlValueAccessor 

@Input() config;
@Input() group: FormGroup;

@Input() disabled = false;
  @HostBinding('style.opacity')
  get opacity() 
    return this.disabled ? 0.25 : 1;
  

clicked;

onChange = (rating: number) => ;
onTouched = () => ;

constructor()  

ngOnInit() 
    // console.log('form', this.group)
      this.group.get(this.config.key).valueChanges.subscribe(value => 
        console.log('formValue', value);
    )


    writeValue(obj: any): void 
        throw new Error("Method not implemented.");
    
    registerOnChange(fn: any): void 
        throw new Error("Method not implemented.");
    
    registerOnTouched(fn: any): void 
        throw new Error("Method not implemented.");
    
    setDisabledState?(isDisabled: boolean): void 
        throw new Error("Method not implemented.");
    

select($event, option) 
    this.clicked = $event;
    this.group.get(this.config.key).patchValue(option.value, onlySelf: true);

    this.config.options.forEach(option => 
        option.selected = false;
    )

    option.selected = true;



【问题讨论】:

writeValue(obj: any): void registerOnChange(fn: any): void registerOnTouched(fn: any): void 的实现在哪里? 抱歉,我一开始忘记复制粘贴了。我不确定如何将它们集成到我的功能中? 【参考方案1】:

你需要实现ControlValueAccessor接口,要做到这一点,你需要实现这个方法:

interface ControlValueAccessor 
  writeValue(obj: any): void
  registerOnChange(fn: any): void
  registerOnTouched(fn: any): void
  setDisabledState(isDisabled: boolean)?: void

你可以在here看到我的示例实现。

当你的组件的值发生变化时,你必须调用你在 ts 文件中注册的 OnChange 方法。

您可以查看我的通话示例here。

之后,您可以通过其标签选择器(在您的情况下为z-toggle-group)在表单中使用您的组件,并且您将能够使用formControlName

<div class="button-group" [formGroup]="group">
    <button
        *ngFor="let option of config.options"
        class="button button--toggle"
        [ngClass]='"is-active": option.selected'
        (click)="select($event, option)">

        <z-toggle-group [formControlName]="config.key"></z-toggle-group>

        <div class="button-content">option.key</div>
    </button>
</div>

Here 是你的代码工作。

【讨论】:

感谢您的回答,但这有点令人困惑。我想将 添加到自身? 谢谢托马斯!你的回答很透彻。 这是一块埋藏的宝石。非常感谢@ThomazCapra

以上是关于如何创建自定义响应式表单元素?的主要内容,如果未能解决你的问题,请参考以下文章

如何让这个表单和按钮在响应式设计中正确调整大小?

Symfony 2:添加自定义表单元素,而不是在实体中

Angular 11 自定义 ISBN 验证器响应式表单

如何将自定义 CSS 添加到清晰的表单中?

如何让 Marketo 表单在嵌入到响应式 WordPress 网站时做出响应?

如何使用响应式表单将验证器添加到表单控件以从角度材料进行匹配输入