十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
这期内容当中小编将会给大家带来有关Angular19 中如何自定义表单控件,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
网站建设哪家好,找创新互联!专注于网页设计、网站建设、微信开发、重庆小程序开发、集团企业网站建设等服务项目。为回馈新老客户创新互联还提供了阜南免费建站欢迎大家使用!
1 需求
当开发者需要一个特定的表单控件时就需要自己开发一个和默认提供的表单控件用法相似的控件来作为表单控件;自定义的表单控件必须考虑模型和视图之间的数据怎么进行交互
2 官方文档 ->点击前往
Angular为开发者提供了ControlValueAccessor接口来辅助开发者构建自定义的表单控件,开发者只需要在自定义表单控件类中实现ControlValueAccessor接口中的方法就可以实现模型和视图之间的数据交互
interface ControlValueAccessor { writeValue(obj: any): void registerOnChange(fn: any): void registerOnTouched(fn: any): void setDisabledState(isDisabled: boolean)?: void }
2.1 writeValue
writeValue(obj: any): void
该方法用于将值写入到自定义表单控件中的元素;
这个参数值(obj)是使用这个自定义表单控件的组件通过模板表单或者响应式表单的数据绑定传过来的;
在自定义表单控件的类中只需要将这个值(obj)赋值给一个成员变量即可,自定义表单控件的视图就会通过属性绑定显示出来这个值
2.2 registerOnChange
registerOnChange(fn: any): void
自定义表单控件的数据发生变化时会触发registerOnChange方法,该方用于如何处理自定义表单控件数据的变化;
registerOnChange方法接收的参数(fn)其实是一个方法,该方法负责处理变化的数据
当自定义控件数据变化时就会自动调用fn执行的方法,但是通常的做法是自定义一个方法 propagateChange 让自定义的方法指向fn,这样当数据变化时只需要调用 propagateChange 就可以对变化的数据进行处理
2.3 registerOnTouched
registerOnTouched(fn: any): void
表单控件被触摸时会触发registerOnTouched方法,具体细节待更新......2018-1-31 11:18:33
2.4 setDisabledState
setDisabledState(isDisabled: boolean)?: void
待更新......2018-1-31 11:19:30
3 编程步骤
3.1 创建自定义表单控件组件
当前计数为:{{countNumber}}
HTML
import { Component, OnInit } from '@angular/core'; import { ControlValueAccessor } from '@angular/forms'; @Component({ selector: 'app-counter', templateUrl: './counter.component.html', styleUrls: ['./counter.component.scss'] }) export class CounterComponent implements OnInit { countNumber: number = 0; constructor() { } ngOnInit() { } onIncrease() { this.countNumber++; } onDecrease() { this.countNumber--; } }
3.1.1 功能描述
点击增加按钮时当前计数会增加1,点击减少按钮时当前计数会剪1
3.1.2 直接在其他组件中使用时会报错
报错信息如下:
错误信息是说我们我们使用的组件
3.2 如何让
3.2.1 实现 ControlValueAccessor 接口
export class CounterComponent implements OnInit, ControlValueAccessor { countNumber: number = 0; constructor() { } ngOnInit() { } onIncrease() { this.countNumber++; } onDecrease() { this.countNumber--; } /**将数据从模型传输到视图 */ writeValue(obj: any): void { } /**将数据从视图传播到模型 */ registerOnChange(fn: any): void { } registerOnTouched(fn: any): void { } setDisabledState?(isDisabled: boolean): void { } }
3.2.2 指定依赖信息providers
import { Component, OnInit, forwardRef } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; @Component({ selector: 'app-counter', templateUrl: './counter.component.html', styleUrls: ['./counter.component.scss'], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CounterComponent), multi: true } ] }) export class CounterComponent implements OnInit, ControlValueAccessor { countNumber: number = 0; constructor() { } ngOnInit() { } onIncrease() { this.countNumber++; } onDecrease() { this.countNumber--; } /**将数据从模型传输到视图 */ writeValue(obj: any): void { } /**将数据从视图传播到模型 */ registerOnChange(fn: any): void { } registerOnTouched(fn: any): void { } setDisabledState?(isDisabled: boolean): void { } }
3.2.3 待修复bug
虽然可以正常运行,但是表单控件中的元素接受不到使用表单控件那个组件中表单模型传过来的数据,表单控件变化的数据也无法回传到使用表单控件那个组件中的表单模型中去;简而言之,就是模型和视图之间无法进行数据交互
3.3 实习那模型和试图的数据交互
3.3.1 模型到视图
重构自定义表单控件类中的 writeValue 方法
技巧01:writeValue 方法中的参数是使用自定义表单控件的那个组件通过表单的数据绑定传进来的
3.3.2 视图到模型
》自定义一个方法来处理自定义表单控件中的变化数据
propagateChange = (_: any) => {};
》重构自定义表单控件类中的 registerOnChange 方法
/**将数据从视图传播到模型 */ registerOnChange(fn: any): void { this.propagateChange = fn; }
》在数据变化的地方调用那个自定义的方法
3.4 自定义表单控件组件代码汇总
当前计数为:{{countNumber}}
HTML
import { Component, OnInit, forwardRef } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; @Component({ selector: 'app-counter', templateUrl: './counter.component.html', styleUrls: ['./counter.component.scss'], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CounterComponent), multi: true } ] }) export class CounterComponent implements OnInit, ControlValueAccessor { countNumber: number = 0; propagateChange = (_: any) => {}; constructor() { } ngOnInit() { } onIncrease() { this.countNumber++; this.propagateChange(this.countNumber); } onDecrease() { this.countNumber--; this.propagateChange(this.countNumber); } /**将数据从模型传输到视图 */ writeValue(obj: any): void { this.countNumber = obj; } /**将数据从视图传播到模型 */ registerOnChange(fn: any): void { /**fn其实是一个函数,当视图中的数据改变时就会调用fn指向的这个函数,从而达到将数据传播到模型的目的 */ this.propagateChange = fn; // 将fn的指向赋值给this.propagateChange,在需要将改变的数据传到模型时只需要调用this.propagateChange方法即可 } registerOnTouched(fn: any): void { } setDisabledState?(isDisabled: boolean): void { } }
3.5 使用自定义表单控件的那个组件的代码汇总
技巧01:如果自定义表单控件和使用自定义表单控件的组件都在不在同一个模块时需要对自定义表单控件对应组件进行导出和导入操作
面板模板面板测试内容
2018-1-22 10:22:20自定义提取表单控件绿线上是自定义提取的表单控件显示的内容
绿线下是使用自定义表单控件时表单的实时数据 表单控件的值为:{{myForm.value | json}}
2018-1-31 10:09:17提取表单控件2018-1-27 21:51:45ngIf指令测试
ngif变量的值为true
ngif变量的值为false
2018-1-27 16:58:17RXJS使用测试内容
2018-1-23 21:14:49自定义验证器2018-1-23 11:06:01响应式表单
表单整体信息如下:
表单数据有效性:{{testForm.valid}}
表单数据为:{{testForm.value | json}}
获取单个或多个FormControl:{{testForm.controls['email'] }}
email输入框的信息如下:
有效性:{{testForm.get('email').valid}}
email输入框的错误信息为:{{testForm.get('email').errors | json}}
required验证结果:{{testForm.hasError('required', 'email') | json}}
minLength验证结果:{{ testForm.hasError('minLength', 'email') | json }}
hello:{{ testForm.controls['email'].errors | json }}
password输入框啊的信息如下:
有效性:{{testForm.get('password').valid}}
password输入框的错误信息为:{{testForm.get('password').errors | json }}
required验证结果:{{testForm.hasError('required', 'password') | json}}
data变量:{{data}}
2018-1-22 15:58:43-->利用响应式编程实现表单元素双向绑定 姓名为:{{name.value}}2018-1-22 11:12:35模板表单名为desc的表单控件的值为:{{ a.value }}
2018-1-22 10:19:31md-chekbox的使用测试 测试checkbox被选中啦
2018-1-18 14:02:20md-tooltip的使用鼠标放上去2018-1-18 14:26:58md-select的使用{{taskList.name}} 2018-1-18 14:26:58ngNonBindable指令的使用描述
使用了ngNonBindable的标签,会将该标签里面的元素内容全部都看做时纯文本
例子
{{taskLists | json }} ← 这是{{taskLists | json }}渲染的内容
2018-1-19 09:34:26
HTML
import { Component, OnInit, HostListener, Inject} from '@angular/core'; import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms'; import { Http } from '@angular/http'; import { QuoteService } from '../../service/quote.service'; @Component({ selector: 'app-test01', templateUrl: './test01.component.html', styleUrls: ['./test01.component.scss'] }) export class Test01Component implements OnInit { countNumber: number = 9; outerCounterValue: number = 5; ngif = true; loginForm: FormGroup; testForm: FormGroup; data: any; name: FormControl = new FormControl(); desc: string = 'hello boy'; taskLists = [ {label: 1, name: '进行中'}, {label: 2, name: '已完成'} ]; constructor( private formBuilder: FormBuilder, private http: Http, @Inject('BASE_CONFIG') private baseConfig, private quoteService: QuoteService ) {} ngOnInit() { this.testForm = new FormGroup({ email: new FormControl('', [Validators.required, Validators.minLength(4)], []), password: new FormControl('', [Validators.required], []) }); this.name.valueChanges .debounceTime(500) .subscribe(value => alert(value)); this.loginForm = this.formBuilder.group({ username: ['', [Validators.required, Validators.minLength(4), this.myValidator], []], userpwd: ['', [Validators.required, Validators.minLength(6)], []] }); this.quoteService.test() .subscribe(resp => console.log(resp)); } onChangeNgifValue() { if (this.ngif == false) { this.ngif = true; } else { this.ngif = false; } } @HostListener('keyup.enter') onTestNgModelClick() { alert('提交'); } onTestClick() { // this.data = this.testForm.get('email').value; // console.log(this.testForm.getError); console.log(this.testForm.controls['email']); } onTestLogin() { console.log(this.loginForm.value); if (this.loginForm.valid) { console.log('登陆数据合法'); } else { console.log('登陆数据不合法'); console.log(this.loginForm.controls['username'].errors); console.log(this.loginForm.get('userpwd').errors); } } myValidator(fc: FormControl): {[key: string]: any} { const valid = fc.value === 'admin'; return valid ? null : {myValidator: {requiredUsername: 'admin', actualUsername: fc.value}}; } }
3.6 初始化效果展示
上述就是小编为大家分享的Angular19 中如何自定义表单控件了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注创新互联行业资讯频道。