文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Angular如何使用ControlValueAccessor实现自定义表单控件

2023-06-14 21:25

关注

这篇文章主要介绍了Angular如何使用ControlValueAccessor实现自定义表单控件,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

本篇文章给大家介绍一下Angular使用ControlValueAccessor实现自定义表单控件的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

Angular: [ControlValueAccessor] 自定义表单控件


我们在实际开发中,通常会遇到各种各样的定制化功能,会遇到有些组件会与 Angular 的表单进行交互,这时候我们一般会从外部传入一个 FormGroup 对象,然后在组件的内部写相应的逻辑对 Angular 表单进行操作。如果我们只是对表单中的一个项进行定制,将整个表单对象传入显然不合适,并且组件也会显得臃肿。

<form [formGroup]="simpleForm">                                  <other-component [form]="simpleForm"></other-component>        </form>

那么,我们能不能像原生表单一样去使用这些自定义组件呢?目前,开源组件 ng-zorro-antd 表单组件能和原生表单一样使用 formControlName 这个属性,这类组件就叫自定义表单组件。

如何实现自定义表单控件

在 Angular 中,使用 ControlValueAccessor 可以实现组件与外层包裹的 form 关联起来。

ControlValueAccessor是用于处理以下内容的接口:

ControlValueAccessor

ControlValueAccessor 接口定义了四个方法:

writeValue(obj: any): voidregisterOnChange(fn: any): voidregisterOnTouched(fn: any): voidsetDisabledState(isDisabled: boolean)?: void

writeValue(obj:any):将表单模型中的新值写入视图或DOM属性(如果需要)的方法,它将来自外部的数据写入到内部的数据模型。数据流向: form model -> component。

registerOnChange(fn:any):一种注册处理程序的方法,当视图中的某些内容发生更改时应调用该处理程序。它具有一个告诉其他表单指令和表单控件以更新其值的函数。通常在 registerOnChange 中需要保存该事件触发函数,在数据改变的时候,可以通过调用事件触发函数通知外部数据变了,同时可以将修改后的数据作为参数传递出去。数据流向: component -> form model。

registerOnTouched(fn: any):注册 onTouched 事件,基本同 registerOnChange ,只是该函数用于通知表单组件已经处于 touched 状态,改变绑定的 FormControl 的内部状态。状态变更: component -> form model。

setDisabledState(isDisabled: boolean):当调用 FormControl 变更状态的 API 时得表单状态变为 Disabled 时调用 setDisabledState() 方法,以通知自定义表单组件当前表单的读写状态。状态变更: form model -> component。

如何使用 ControlValueAccessor

搭建控件框架

@Component({  selector: 'app-test-control-value-accessor',  templateUrl: './test-control-value-accessor.component.html',  providers: [{    provide: NG_VALUE_ACCESSOR,    useExisting: forwardRef(() => TestControlValueAccessorComponent),    multi: true  }]})export class TestControlValueAccessorComponent implements ControlValueAccessor {  _counterValue = 0;   private onChange = (_: any) => {};  constructor() { }  get counterValue() {    return this._counterValue;  }  set counterValue(value) {    this._counterValue = value;    // 触发 onChange,component 内部的值同步到 form model    this.onChange(this._counterValue);  }  increment() {    this.counterValue++;  }  decrement() {    this.counterValue--;  }  // form model 的值同步到 component 内部  writeValue(obj: any): void {    if (obj !== undefined) {      this.counterValue = obj;    }  }  registerOnChange(fn: any): void {    this.onChange = fn;  }  registerOnTouched(fn: any): void { }  setDisabledState?(isDisabled: boolean): void { }}

注册 ControlValueAccessor

为了获得 ControlValueAccessor 用于表单控件,Angular 内部将注入在 NG_VALUE_ACCESSOR 令牌上注册的所有值,这是将控件本身注册到 DI 框架成为一个可以让表单访问其值的控件。因此,我们需要做的就是NG_VALUE_ACCESSOR 使用我们自己的值访问器实例(这是我们的组件)扩展 multi-provider 。所以设置 multi: true,是声明这个 token 对应的类很多,分散在各处。

这里我们必须使用 useExisting,因为TestControlValueAccessorComponent 可能在使用它的组件中被其创建为指令依赖项。这就得用到 forwardRef 了,这个函数允许我们引用一个尚未定义的对象。

@Component({  ...  providers: [    {       provide: NG_VALUE_ACCESSOR,      useExisting: forwardRef(() => TestControlValueAccessorComponent ),      multi: true    }  ]})export class TestControlValueAccessorComponent implements ControlValueAccessor {  ...}

控件界面

<div class="panel panel-primary">  <div class="panel-heading">自定义控件</div>  <div class="panel-body">    <button (click)="increment()">+</button>    {{counterValue}}    <button (click)="decrement()">-</button>  </div></div>

在表单中使用

<div class="constainer">  <form #form="ngForm">    <app-test-control-value-accessor name="message" [(ngModel)]="message"></app-test-control-value-accessor>    <button type="button" (click)="submit(form.value)">Submit</button>  </form>  <pre>{{ message }}</pre></div>
@Component({  selector: 'app-root',  templateUrl: './app.component.html',  styleUrls: ['./app.component.css']})export class AppComponent {  message = 5;  submit(value: any): void {    console.log(value);  }}

感谢你能够认真阅读完这篇文章,希望小编分享的“Angular如何使用ControlValueAccessor实现自定义表单控件”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网行业资讯频道,更多相关知识等着你来学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯