這篇文章主要介紹了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 建立自訂表單控制項元件
<p> <h4 id="当前计数为-countNumber">当前计数为:{{countNumber}}</h4> <br /> <p> <button md-icon-button (click)="onIncrease()"> <span>增加</span> <md-icon>add</md-icon> </button> <span style="margin-left: 30px;"></span> <button md-icon-button (click)="onDecrease()"> <span>减少</span> <md-icon>remove</md-icon> </button> </p> </p>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.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 自訂表單控制項元件程式碼總結
<p> <h4 id="当前计数为-countNumber">当前计数为:{{countNumber}}</h4> <br /> <p> <button md-icon-button (click)="onIncrease()"> <span>增加</span> <md-icon>add</md-icon> </button> <span style="margin-left: 30px;"></span> <button md-icon-button (click)="onDecrease()"> <span>减少</span> <md-icon>remove</md-icon> </button> </p> </p>
# 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:如果自定义表单控件和使用自定义表单控件的组件都在不在同一个模块时需要对自定义表单控件对应组件进行导出和导入操作
<p class="panel panel-primary"> <p class="panel-heading">面板模板</p> <p class="panel-body"> <h3 id="面板测试内容">面板测试内容</h3> </p> <p class="panel-footer">2018-1-22 10:22:20</p> </p> <p class="panel-primary"> <p class="panel-heading">自定义提取表单控件</p> <p class="panel-body"> <form #myForm=ngForm> <app-counter name="counter" [(ngModel)]="countNumber"> </app-counter> </form> <h6 id="绿线上是自定义提取的表单控件显示的内容">绿线上是自定义提取的表单控件显示的内容</h6> <hr style="border: solid green 2px" /> <h6 id="绿线下是使用自定义表单控件时表单的实时数据">绿线下是使用自定义表单控件时表单的实时数据</h6> <h3 id="表单控件的值为-myForm-value-nbsp-nbsp-json">表单控件的值为:{{myForm.value | json}}</h3> </p> <p class="panel-footer">2018-1-31 10:09:17</p> </p> <p class="panel-primary"> <p class="panel-heading">提取表单控件</p> <p class="panel-body"> <form #form="ngForm"> <p>outerCounterValue value: {{outerCounterValue}}</p> <app-exe-counter name="counter" [(ngModel)]="outerCounterValue"></app-exe-counter> <br /> <button md-raised-button type="submit">Submit</button> <br /> <p> {{form.value | json}} </p> </form> </p> <p class="panel-footer">2018-1-27 21:51:45</p> </p> <p class="panel panel-primary"> <p class="panel-heading">ngIf指令测试</p> <p class="panel-body"> <button md-rasied-button (click)="onChangeNgifValue()">改变ngif变量</button> <br /> <p *ngIf="ngif; else ngifTrue" > <h4 id="ngif变量的值为true">ngif变量的值为true</h4> </p> <ng-template #ngifTrue> <h4 id="ngif变量的值为false">ngif变量的值为false</h4> </ng-template> </p> <p class="panel-footer">2018-1-27 16:58:17</p> </p> <p class="panel panel-primary"> <p class="panel-heading">RXJS使用</p> <p class="panel-body"> <h4 id="测试内容">测试内容</h4> </p> <p class="panel-footer">2018-1-23 21:14:49</p> </p> <p class="panel panel-primary"> <p class="panel-heading">自定义验证器</p> <p class="panel-body"> <form (ngSubmit)="onTestLogin()" [formGroup]="loginForm"> <md-input-container> <input mdInput placeholder="请输入登录名" formControlName="username" /> </md-input-container> <br /> <md-input-container> <input mdInput placeholder="请输入密码" formControlName="userpwd" /> </md-input-container> <br /> <button type="submit" md-raised-button>登陆</button> </form> </p> <p class="panel-footer">2018-1-23 11:06:01</p> </p> <p class="panel panel-primary"> <p class="panel-heading">响应式表单</p> <p class="panel-body"> <form [formGroup]="testForm"> <md-input-container> <input mdInput type="text" placeholder="请输入邮箱" formControlName="email" /> <span mdSuffix>@163.com</span> </md-input-container> <br /> <md-input-container> <input mdInput type="password" placeholder="请输入密码" formControlName="password" /> </md-input-container> </form> <hr /> <p> <h2 id="表单整体信息如下">表单整体信息如下:</h2> <h4 id="表单数据有效性-testForm-valid">表单数据有效性:{{testForm.valid}}</h4> <h4 id="表单数据为-testForm-value-nbsp-nbsp-json">表单数据为:{{testForm.value | json}}</h4> <h4 id="获取单个或多个FormControl-testForm-controls-email-nbsp">获取单个或多个FormControl:{{testForm.controls['email'] }}</h4> <hr /> <h2 id="email输入框的信息如下">email输入框的信息如下:</h2> <h4 id="有效性-testForm-get-email-valid">有效性:{{testForm.get('email').valid}}</h4> <h4 id="email输入框的错误信息为-testForm-get-email-errors-nbsp-nbsp-json">email输入框的错误信息为:{{testForm.get('email').errors | json}}</h4> <h4 id="required验证结果-testForm-hasError-required-nbsp-email-nbsp-nbsp-json">required验证结果:{{testForm.hasError('required', 'email') | json}}</h4> <h4 id="minLength验证结果-nbsp-testForm-hasError-minLength-nbsp-email-nbsp-nbsp-json-nbsp">minLength验证结果:{{ testForm.hasError('minLength', 'email') | json }}</h4> <h4 id="hello-nbsp-testForm-controls-email-errors-nbsp-nbsp-json-nbsp">hello:{{ testForm.controls['email'].errors | json }}</h4> <hr /> <h2 id="password输入框啊的信息如下">password输入框啊的信息如下:</h2> <h4 id="有效性-testForm-get-password-valid">有效性:{{testForm.get('password').valid}}</h4> <h4 id="password输入框的错误信息为-testForm-get-password-errors-nbsp-nbsp-json-nbsp">password输入框的错误信息为:{{testForm.get('password').errors | json }}</h4> <h4 id="required验证结果-testForm-hasError-required-nbsp-password-nbsp-nbsp-json">required验证结果:{{testForm.hasError('required', 'password') | json}}</h4> </p> <p> <button nd-rasied-button (click)="onTestClick()">获取数据</button> <h4 id="data变量-data">data变量:{{data}}</h4> </p> </p> <p class="panel-footer">2018-1-22 15:58:43</p> </p> <p class="panel panel-primary"> <p class="panel-heading">利用响应式编程实现表单元素双向绑定</p> <p class="panel-body"> <md-input-container> <input mdInput placeholder="请输入姓名(响应式双向绑定):" [formControl]="name"/> </md-input-container> <p> 姓名为:{{name.value}} </p> </p> <p class="panel-footer">2018-1-22 11:12:35</p> </p> --> <p class="panel panel-primary"> <p class="panel-heading">模板表单</p> <p class="panel-body"> <md-input-container> <input mdInput placeholder="随便输入点内容" #a="ngModel" [(ngModel)]="desc" name="desc" /> <button type="button" md-icon-button mdSuffix (click)="onTestNgModelClick()"> <md-icon>done</md-icon> </button> </md-input-container> <p> <h3 id="名为desc的表单控件的值为-nbsp-a-value-nbsp">名为desc的表单控件的值为:{{ a.value }}</h3> </p> </p> <p class="panel-footer">2018-1-22 10:19:31</p> </p> <p class="panel panel-primary"> <p class="panel-heading">md-chekbox的使用</p> <p calss="panel-body"> <p> <md-checkbox #testCheckbox color="primary" checked="true">测试</md-checkbox> </p> <p *ngIf="testCheckbox.checked"> <h2 id="测试checkbox被选中啦">测试checkbox被选中啦</h2> </p> </p> <p class="panel-footer">2018-1-18 14:02:20</p> </p> <p class="panel panel-primary"> <p class="panel-heading">md-tooltip的使用</p> <p class="panel-body"> <span md-tooltip="重庆火锅">鼠标放上去</span> </p> <p class="panel-footer">2018-1-18 14:26:58</p> </p> <p class="panel panel-primary"> <p class="panel-heading">md-select的使用</p> <p class="panel-body"> <md-select placeholder="请选择目标列表" class="fill-width" style="height: 40px;"> <md-option *ngFor="let taskList of taskLists" [value]="taskList.name">{{taskList.name}}</md-option> </md-select> </p> <p class="panel-footer">2018-1-18 14:26:58</p> </p> <p class="panel panel-primary"> <p class="panel-heading">ngNonBindable指令的使用</p> <p class="panel-body"> <h3 id="描述">描述</h3> <p>使用了ngNonBindable的标签,会将该标签里面的元素内容全部都看做时纯文本</p> <h3 id="例子">例子</h3> <p> <span>{{taskLists | json }}</span> <span ngNonBindable>← 这是{{taskLists | json }}渲染的内容</span> </p> </p> <p class="panel-footer">2018-1-19 09:34:26</p> </p>
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 初始化效果展示
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
JavaScript中Object基础内部方法图(图文教程)
以上是在Angular19中有關自訂表單控制項使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JavaScript在瀏覽器和Node.js環境中運行,依賴JavaScript引擎解析和執行代碼。 1)解析階段生成抽象語法樹(AST);2)編譯階段將AST轉換為字節碼或機器碼;3)執行階段執行編譯後的代碼。

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

Dreamweaver Mac版
視覺化網頁開發工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)