Maison >interface Web >js tutoriel >À propos de l'utilisation de contrôles de formulaire personnalisés dans Angular19

À propos de l'utilisation de contrôles de formulaire personnalisés dans Angular19

亚连
亚连original
2018-06-08 16:23:421287parcourir

Cet article présente principalement les informations pertinentes sur les contrôles de formulaire personnalisés Angular19. Il est très bon et a une valeur de référence. Les amis qui en ont besoin peuvent s'y référer

1 Exigences

Lorsque les développeurs ont besoin d'un contrôle de formulaire spécifique, ils doivent développer un contrôle similaire au contrôle de formulaire fourni par défaut en tant que contrôle de formulaire personnalisé ; interagir avec les données

2 Document officiel-> Cliquez pour accéder à

Angular L'interface ControlValueAccessor est fournie aux développeurs pour aider les développeurs à créer des contrôles de formulaire personnalisés. Les développeurs n'ont qu'à implémenter les méthodes de l'interface ControlValueAccessor dans la classe de contrôle de formulaire personnalisé pour obtenir une interaction de données entre le modèle et la vue

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

Cette méthode est utilisée pour écrire des valeurs dans des éléments dans des contrôles de formulaire personnalisés

Cette valeur de paramètre (obj ) est transmise ; la liaison de données du formulaire modèle ou du formulaire réactif à l'aide du composant de ce contrôle de formulaire personnalisé ;

Dans la classe du contrôle de formulaire personnalisé, il vous suffit d'attribuer cette valeur (obj) à une variable membre ; , et la vue du contrôle de formulaire personnalisé affichera cette valeur via la liaison d'attribut

2.2 registerOnChange

registerOnChange(fn: any): void

Données du contrôle de formulaire personnalisé La méthode registerOnChange est déclenchée lorsqu'un changement se produit, qui est utilisé pour gérer les modifications dans les données de contrôle du formulaire personnalisé ;

Le paramètre (fn) reçu par la méthode registerOnChange est en fait une méthode responsable du traitement des données modifiées

Lorsque les données du contrôle personnalisé changent, la méthode exécutée par fn sera automatiquement appelée. Cependant, l'approche habituelle consiste à personnaliser une méthode propagateChange et à laisser la méthode personnalisée pointer vers fn. il vous suffit d'appeler propagateChange. Traitement des données modifiées

2.3 registerOnTouched

registerOnTouched(fn: any): void

La méthode registerOnTouched sera déclenchée lorsque le contrôle du formulaire est touché. sera mis à jour... 2018- 1-31 11:18:33

2.4 setDisabledState

setDisabledState(isDisabled: boolean)?: void

À mettre à jour...2018-1-31 11:19:30

3 Étapes de programmation

3.1 Créer un composant de contrôle de formulaire personnalisé

<p>
 <h4>当前计数为:{{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 &#39;@angular/core&#39;;
import { ControlValueAccessor } from &#39;@angular/forms&#39;;
@Component({
 selector: &#39;app-counter&#39;,
 templateUrl: &#39;./counter.component.html&#39;,
 styleUrls: [&#39;./counter.component.scss&#39;]
})
export class CounterComponent implements OnInit {
 countNumber: number = 0;
 constructor() { }
 ngOnInit() {
 }
 onIncrease() {
 this.countNumber++;
 }
 onDecrease() {
 this.countNumber--;
 }
}

3.1.1 Description de la fonction

Lorsque vous cliquez sur le bouton d'augmentation, le nombre actuel augmentera de 1, et lorsque vous cliquez sur le bouton de diminution, le décompte actuel sera réduit de 1

3.1.2 Une erreur sera signalée en cas d'utilisation directe dans d'autres composants

Le message d'erreur est le suivant :

Le message d'erreur signifie que le composant que nous utilisons e25ec79a20da4c9966e96cb66e7b8c11 pas un contrôle de formulaire

3.2 Comment faire en sorte que le composant e25ec79a20da4c9966e96cb66e7b8c11 devienne un composant de contrôle de formulaire

3.2.1 Implémenter l'interface 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 Spécifier les fournisseurs d'informations de dépendance

import { Component, OnInit, forwardRef } from &#39;@angular/core&#39;;
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from &#39;@angular/forms&#39;;
@Component({
 selector: &#39;app-counter&#39;,
 templateUrl: &#39;./counter.component.html&#39;,
 styleUrls: [&#39;./counter.component.scss&#39;],
 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 Bugs à corriger

Bien qu'il puisse s'exécuter normalement, les éléments du contrôle de formulaire ne peuvent pas recevoir de données du modèle de formulaire dans le composant qui utilise le contrôle de formulaire, et le les données modifiées par le contrôle de formulaire ne peuvent pas être retransmises au modèle de formulaire dans le composant qui utilise le contrôle de formulaire ; en bref, c'est le modèle. Il n'y a pas d'interaction de données entre la vue et le modèle

3.3 Pratiquer l'interaction des données entre le modèle et la vue

3.3.1 Modèle à afficher

Refactoriser la méthode writeValue dans la classe de contrôle de formulaire personnalisé

Astuce 01 : Les paramètres de la méthode writeValue sont transmis via la liaison de données du formulaire par le composant à l'aide du contrôle de formulaire personnalisé

3.3. 2 Afficher le modèle

propagateChange = (_: any) => {};
》Personnaliser une méthode pour traiter les données changeantes dans les contrôles de formulaire personnalisés

 /**将数据从视图传播到模型 */
 registerOnChange(fn: any): void {
 this.propagateChange = fn;
 }
》Reconstruire la méthode registerOnChange dans la classe de contrôle de formulaire personnalisé

》Appelez la méthode personnalisée où les données changent

3.4 Résumé du code des composants de contrôle de formulaire personnalisé
<p>
 <h4>当前计数为:{{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>

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 {
 }
}
HTML

3.5 Résumé du code du composant qui utilise le contrôle de formulaire personnalisé

技巧01:如果自定义表单控件和使用自定义表单控件的组件都在不在同一个模块时需要对自定义表单控件对应组件进行导出和导入操作

 

<p class="panel panel-primary">
 <p class="panel-heading">面板模板</p>
 <p class="panel-body">
 <h3>面板测试内容</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>绿线上是自定义提取的表单控件显示的内容</h6>
 <hr style="border: solid green 2px" />
 <h6>绿线下是使用自定义表单控件时表单的实时数据</h6>
 <h3>表单控件的值为:{{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 style="background-color: red; color: white" >ngif变量的值为true</h4>
 </p>
 <ng-template #ngifTrue>
  <h4 style="background-color: black; color: white">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>测试内容</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>表单整体信息如下:</h2>
  <h4>表单数据有效性:{{testForm.valid}}</h4>
  <h4>表单数据为:{{testForm.value | json}}</h4>
  <h4>获取单个或多个FormControl:{{testForm.controls[&#39;email&#39;] }}</h4>
  <hr />
  <h2>email输入框的信息如下:</h2>
  <h4>有效性:{{testForm.get(&#39;email&#39;).valid}}</h4>
  <h4>email输入框的错误信息为:{{testForm.get(&#39;email&#39;).errors | json}}</h4>
  <h4>required验证结果:{{testForm.hasError(&#39;required&#39;, &#39;email&#39;) | json}}</h4>
  <h4>minLength验证结果:{{ testForm.hasError(&#39;minLength&#39;, &#39;email&#39;) | json }}</h4>
  <h4>hello:{{ testForm.controls[&#39;email&#39;].errors | json }}</h4>
  <hr />
  <h2>password输入框啊的信息如下:</h2>
  <h4>有效性:{{testForm.get(&#39;password&#39;).valid}}</h4>
  <h4>password输入框的错误信息为:{{testForm.get(&#39;password&#39;).errors | json }}</h4>
  <h4>required验证结果:{{testForm.hasError(&#39;required&#39;, &#39;password&#39;) | json}}</h4>
 </p>
 <p>
  <button nd-rasied-button (click)="onTestClick()">获取数据</button>
  <h4>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>名为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>测试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>描述</h3>
 <p>使用了ngNonBindable的标签,会将该标签里面的元素内容全部都看做时纯文本</p>
 <h3>例子</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 &#39;@angular/core&#39;;
import { FormControl, FormGroup, FormBuilder, Validators } from &#39;@angular/forms&#39;;
import { Http } from &#39;@angular/http&#39;;
import { QuoteService } from &#39;../../service/quote.service&#39;;
@Component({
 selector: &#39;app-test01&#39;,
 templateUrl: &#39;./test01.component.html&#39;,
 styleUrls: [&#39;./test01.component.scss&#39;]
})
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 = &#39;hello boy&#39;;
 taskLists = [
 {label: 1, name: &#39;进行中&#39;},
 {label: 2, name: &#39;已完成&#39;}
 ];
 constructor(
 private formBuilder: FormBuilder,
 private http: Http,
 @Inject(&#39;BASE_CONFIG&#39;) private baseConfig,
 private quoteService: QuoteService
 ) {}
 ngOnInit() {
 this.testForm = new FormGroup({
  email: new FormControl(&#39;&#39;, [Validators.required, Validators.minLength(4)], []),
  password: new FormControl(&#39;&#39;, [Validators.required], [])
 });
 this.name.valueChanges
 .debounceTime(500)
 .subscribe(value => alert(value));
 this.loginForm = this.formBuilder.group({
  username: [&#39;&#39;, [Validators.required, Validators.minLength(4), this.myValidator], []],
  userpwd: [&#39;&#39;, [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(&#39;keyup.enter&#39;)
 onTestNgModelClick() {
 alert(&#39;提交&#39;);
 }
 onTestClick() {
 // this.data = this.testForm.get(&#39;email&#39;).value;
 // console.log(this.testForm.getError);
 console.log(this.testForm.controls[&#39;email&#39;]);
 }
 onTestLogin() {
 console.log(this.loginForm.value);
 if (this.loginForm.valid) {
  console.log(&#39;登陆数据合法&#39;);
 } else {
  console.log(&#39;登陆数据不合法&#39;);
  console.log(this.loginForm.controls[&#39;username&#39;].errors);
  console.log(this.loginForm.get(&#39;userpwd&#39;).errors);
 }
 }
 myValidator(fc: FormControl): {[key: string]: any} {
 const valid = fc.value === &#39;admin&#39;;
 return valid ? null : {myValidator: {requiredUsername: &#39;admin&#39;, actualUsername: fc.value}};
 }
}

3.6 初始化效果展示

 

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

JavaScript中Object基础内部方法图(图文教程)

在webpack中如何使用ECharts?

vue如何制作自动建站项目(详细教程)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn