An Analysis of Angular19 custom form controls and angular19

Source: Internet
Author: User
Tags export class

An Analysis of Angular19 custom form controls and angular19

1 Requirement

When developers need a specific form control, they need to develop a control similar to the default form control usage as a form control; the custom form control must consider how the data between the model and the view interacts.

2. Official documentation->Click to go

Angular provides the ControlValueAccessor interface to help developers build custom form controls, developers only need to implement methods in the ControlValueAccessor interface in the custom form control class to realize data interaction between the model and view.

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

This method is used to write values to elements in the custom form control;

This parameter value (obj) is transmitted by using the custom form control component through the data binding of the template form or response form;

In the class of the custom form control, you only need to assign this value (obj) to a member variable. The view of the custom form control will display this value through property binding.

2.2 registerOnChange

registerOnChange(fn: any): void

The registerOnChange method is triggered when the data of the custom form control changes. This method is used to process the data changes of the custom form control;

The parameter (fn) received by the registerOnChange method is actually a method that processes the changed data.

The fn execution method is automatically called when the custom control data changes. However, a custom method propagateChange directs the custom method to fn, in this way, you only need to call propagateChange to process the changed data.

2.3 registerOnTouched

registerOnTouched(fn: any): void

The registerOnTouched method is triggered when the form control is touched. The details are to be updated... 11:18:33

2.4 setDisabledState

setDisabledState(isDisabled: boolean)?: void

To be updated... 11:19:30

3 programming steps

3.1 create a custom form Control Component

<Div> 

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 Function Description

When you click the Add button, the current count increases by 1. When you click the reduce button, the current count is cut by 1.

 

3.1.2 when used directly in other components, an error is reported.

 

The error message is as follows:

 

The error message indicates that the <app-counter> component we use is not a Form Control.

3.2 how to turn the <app-counter> component into a form Control Component

3.2.1 implement the ControlValueAccessor Interface

 

Export class CounterComponent implements OnInit, ControlValueAccessor {countNumber: number = 0; constructor () {} ngOnInit () {} onIncrease () {this. countNumber ++;} onDecrease () {this. countNumber --;}/** transfers data from the model to the view */writeValue (obj: any ): void {}/** transmits data from the view to the model */registerOnChange (fn: any): void {} registerOnTouched (fn: any): void {} setDisabledState? (IsDisabled: boolean): void {}}

3.2.2 specify the dependency information 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 impleme CNT OnInit, ControlValueAccessor {countNumber: number = 0; constructor () {} ngOnInit () {} onIncrease () {this. countNumber ++;} onDecrease () {this. countNumber --;}/** transfers data from the model to the view */writeValue (obj: any ): void {}/** transmits data from the view to the model */registerOnChange (fn: any): void {} registerOnTouched (fn: any): void {} setDisabledState? (IsDisabled: boolean): void {}}

3.2.3 bugs to be fixed

Although it can run normally, the elements in the Form Control cannot accept the data transmitted from the form model in the component using the form control, the changed data of the form control cannot be uploaded back to the form model of the component using the form control. In short, data interaction between the model and the view cannot be performed.

3.3 interworking with the model and attempted data

3.3.1 model to view

Refactor the writeValue method in the custom form control class

Tip 01: the parameters in the writeValue method are transmitted by using the component of the custom form control through the data binding of the form.

 

3.3.2 view to Model

To process the changed data in the custom form control.

propagateChange = (_: any) => {};

Reconstructs the registerOnChange method in the custom form control class.

/** Spread data from the view to the model */registerOnChange (fn: any): void {this. propagateChange = fn ;}

Call the custom method where data changes

 

3.4 custom form control component code Summary

<Div> 

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 impleme CNT OnInit, ControlValueAccessor {countNumber: number = 0; propagateChange = (_: any) =>{}; constructor () {} ngOnInit () {} onIncrease () {this. countNumber ++; this. propagateChange (this. countNumber);} onDecrease () {this. countNumber --; this. propagateChange (this. countNumber);}/** transmit data from the model to the view */writeValue (obj: any): void {this. countNumber = obj;}/** spread data from the view to the model */registerOnChange (fn: any): v Oid {/** fn is actually a function. When the data in the view changes, the fn point is called to spread data to the model. */this. propagateChange = fn; // assign the fn point to this. propagateChange: you only need to call this when transferring the changed data to the model. the propagateChange method can be} registerOnTouched (fn: any): void {} setDisabledState? (IsDisabled: boolean): void {}}

3.5 code Summary of the component using the custom form Control

Tip 01: If the custom form control and the components using the custom form control are not in the same module, you must export and import the corresponding components of the custom form control.

 

<Div class = "panel-primary"> <div class = "panel-heading"> panel template </div> <div class = "panel-body"> 

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 impleme CNT 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:' In Progress '}, {label: 2, name: 'finished'}]; 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. myValidat Or], [], 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 ('Submit');} onTestClick () {// this. data = this. testForm. get ('email '). value; // console. log (this. test Form. getError); console. log (this. testForm. controls ['email ']);} onTestLogin () {console. log (this. loginForm. value); if (this. loginForm. valid) {console. log ('valid login data');} else {console. log ('invalid login data'); 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 display of initialization results

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.