详解Angular使用ControlValueAccessor实现自定义表单控件
跟大家讲解下有关详解Angular使用ControlValueAccessor实现自定义表单控件,相信小伙伴们对这个话题应该也很关注吧,现在就为小伙伴们说说详解Angular使用ControlValueAccessor实现自定义表单控件,小编也收集到了有关详解Angular使用ControlValueAccessor实现自定义表单控件的相关资料,希望大家看到了会喜欢。
本篇文章给大家介绍一下Angular使用ControlValueAccessor实现自定义表单控件的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。Angular: [ControlValueAccessor] 自定义表单控件我们在实际开发中,通常会遇到各种各样的定制化功能,会遇到有些组件会与 Angular 的表单进行交互,这时候我们一般会从外部传入一个 FormGroup 对象,然后在组件的内部写相应的逻辑对 Angular 表单进行操作。如果我们只是对表单中的一个项进行定制,将整个表单对象传入显然不合适,并且组件也会显得臃肿。
<form [formGroup]="simpleForm"> <other-component [form]="simpleForm"></other-component> </form>那么,我们能不能像原生表单一样去使用这些自定义组件呢?目前,开源组件 ng-zorro-antd 表单组件能和原生表单一样使用 formControlName 这个属性,这类组件就叫自定义表单组件。【相关推荐:《angular教程》】
如何实现自定义表单控件在 Angular 中,使用 ControlValueAccessor 可以实现组件与外层包裹的 form 关联起来。
ControlValueAccessor是用于处理以下内容的接口:
将表单模型中的值写入视图/ DOM在视图/ DOM更改时通知其他表单指令和控件ControlValueAccessor
ControlValueAccessor 接口定义了四个方法:
writeValue(obj: any): voidregisterOnChange(fn: any): voidregisterOnTouched(fn: any): voidsetDisabledState(isDisabled: boolean)?: voidwriteValue(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 { ...}控件界面
test-control-value-accessor.component.html<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>在表单中使用
app.component.html<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>app.component.ts@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css']})export class AppComponent { message = 5; submit(value: any): void { console.log(value); }}参考https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html
https://almerosteyn.com/2016/04/linkup-custom-control-to-ngcontrol-ngmodel
https://juejin.im/post/597176886fb9a06ba4746d15
https://github.com/shhdgit/blogs/issues/11
更多编程相关知识,请访问:编程视频!!
以上就是详解Angular使用ControlValueAccessor实现自定义表单控件的详细内容,更多请关注php中文网其它相关文章!
来源:php中文网
免责声明:本文由用户上传,与本网站立场无关。财经信息仅供读者参考,并不构成投资建议。投资者据此操作,风险自担。 如有侵权请联系删除!
-
作为A股市场中极具代表性的黄金珠宝行业龙头企业,作为中国历史最悠久的珠宝品牌之一,老凤祥(股票代码:600612)...浏览全文>>
-
宝子们,杭州 房子装修完成啦!这次要给大家分享几家设计超赞的装修公司哦。它们各具特色,从空间规划到风格...浏览全文>>
-
欲筑室者,先治其基。在上海,装修房子对于每个业主而言,都是极为关键的一步,然而,如何挑选一家值得信赖的...浏览全文>>
-
2025年以来,联通支付严格贯彻落实国家战略部署,以数字和科技为驱动,做好金融五篇大文章,履行支付为民社会...浏览全文>>
-
良工巧匠,方能筑就华居;精雕细琢,方可打造美家。当我们谈论装修公司时,选择一家靠谱可靠的公司是至关重要...浏览全文>>
-
在当今社会,随着城市化进程的高速推进,建筑垃圾的产生量与日俱增。据权威数据显示,我国每年建筑垃圾产生量超 ...浏览全文>>
-
家人们,在上海要装修,选对公司那可太重要了!古语有云:"安得广厦千万间,大庇天下寒士俱欢颜。"一个温馨的...浏览全文>>
-
近年来,新能源汽车市场发展迅猛,各大品牌纷纷推出各具特色的车型以满足消费者多样化的需求。作为国内新能源...浏览全文>>
-
近年来,随着汽车市场的不断变化和消费者需求的升级,安徽滁州地区的宝来2025新款车型在市场上引起了广泛关注...浏览全文>>
-
随着汽车市场的不断变化,滁州地区的消费者对高尔夫车型的关注度持续上升。作为大众品牌旗下的经典车型,高尔...浏览全文>>
- 安徽滁州途安L新车报价2022款,最低售价16.68万起,入手正当时
- 小鹏G7试驾,新手必知的详细步骤
- 别克GL8预约试驾,4S店的贴心服务与流程
- 安徽阜阳ID.4 CROZZ落地价全解,买车必看的省钱秘籍
- 淮北探岳多少钱 2025款落地价,最低售价17.69万起现在该入手吗?
- 安徽淮南大众CC新款价格2025款多少钱能落地?
- 淮北长安启源C798价格,最低售价12.98万起现在该入手吗?
- 安徽淮南途锐价格,各配置车型售价全解析
- 蒙迪欧试驾预约,4S店体验全攻略
- 沃尔沃XC40试驾需要注意什么
- 滁州ID.4 X新车报价2025款,各车型售价大公开,性价比爆棚
- 试驾思域,快速操作,轻松体验驾驶乐趣
- 试驾长安CS35PLUS,一键搞定,开启豪华驾驶之旅
- 天津滨海ID.6 X落地价限时特惠,最低售价25.9888万起,错过不再有
- 天津滨海凌渡多少钱?看完这篇购车攻略再做决定
- 安徽池州长安猎手K50落地价,买车前的全方位指南
- 山东济南ID.6 CROZZ 2024新款价格,最低售价19.59万起,现车充足
- 试驾海狮05EV,新手必知的详细步骤
- 生活家PHEV多少钱 2025款落地价走势,近一个月最低售价63.98万起,性价比凸显
- 奇瑞风云A9试驾,新手必知的详细步骤