Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

Sorry, you do not have permission to ask a question, You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please type your username.

Please type your E-Mail.

Please choose an appropriate title for the post.

Please choose the appropriate section so your post can be easily searched.

Please choose suitable Keywords Ex: post, video.

Browse

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Navigation

  • Home
  • About Us
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • About Us
  • Contact Us
Home/ Questions/Q 7529

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Latest Questions

Author
  • 60k
Author
Asked: November 28, 20242024-11-28T04:40:07+00:00 2024-11-28T04:40:07+00:00

Build your own angular forms – ngModel

  • 60k

If you are an angular developer, you must have used angular form package many a times in your projects to manage your forms.

If you are curious to know, what goes behind the scenes to propel such an awesome form management package?

I am trying to explain and decode angular forms through some series of articles like how angular form package is organized, written and well architected to handle so many different type of form controls and related use cases.

Don't worry if you feel overwhelmed seeing above flow diagram, we will go through it one component at a time.

As you already know, ngModel is used to synchronize the values defined in component with any form elements value.

But how ngModel does so?

So, let's think over some of the use cases, ngModel should have implemented.

  1. It should accept input property ngModel which will be synchronized with underlying host element.

  2. It should support all different types of form elements like text input, number input, checkbox, select etc.

  3. It should also work with the custom form elements.


Complexity involved in implementing ngModel directive with above use cases

As different form elements are dealt differently which means when you write to them, you write to different properties and when you want to track changes in form elemets, you might have to register for different types of events relevant to host element where you apply ngModel directive

For example, for input having types as text | number | email we will write to the value property but for checkbox we write to the checked property


Picking the naive approach to design ngModel

@Directive({   selector: '[ngModel]',   exportAs: 'ngModel' }) export class NgModel implements OnChanges {   @Input('ngModel') model: any   @Output('ngModelChange') update = new EventEmitter()    constructor(private _elementRef: ElementRef) {}    ngOnChanges(changes: SimpleChanges): void {         this._elementRef.nativeElement.value = this.model   }    @HostListener("input", ["$event.target.value"]) onInput(value: any) {     this.update.emit(value)   }  } 
Enter fullscreen mode Exit fullscreen mode

So, as you can see, we inject the elemetRef to get hold of host element and write to it when ngModel input property is passed during change detection and also, we register on host element for the input event and emit updated input value back to the use case component.

Though simple approach but it has some drawbacks:

  1. If we adopt this approach, it won't scale easily for remaining form controls as different form controls involve some complexity when writing and reading their values.

  2. Putting everything in ngModel makes it less configurable and hard to work with custom form elements.


Instead, how angular does it?

Image description

Referring to the above diagram, ngModel delegate this responsibility of reading and writing to different types of form elements to different set of directives called control value accessors.

What are control value accessors?

These are just simple directives which gets applied to a particular or group of form elements based on their selectors.

Each control value accessor implements below interface

export interface ControlValueAccessor {     writeValue(obj: any): void;     registerOnChange(fn: any): void; } 
Enter fullscreen mode Exit fullscreen mode

How it helps ngModel?

Each CVA directive is aware of, how to write to particular host element and how to read it by registering to events emitted by host element and thus it frees ngModel from managing the complexity.

Also these CVA directives expose themselves as a service on a DI token NG_VALUE_ACCESSOR which ngModel can inject and get hold of correct control value accessor to write and read values from host element


When ngModel directive is applied on a form element then not only ngModel instance is created but alongwith it an instance of control value accessor directive is also created which is relevant to host element.

Angular provides different types of CVA directive

  1. DefaultControlValueAccessor, It is created when applying ngModel on inputs expect the input having type as checkbox.

  2. CheckBoxControlValueAccessor, When applying ngModel on checkbox input, instead of default CVA this is created.

  3. SelectControlValueAccessor, Its created for select box and a few more.

How ngModel integerate with CVA ?

Control value accessor directive expose itself as a service on a dependency injection token NG_VALUE_ACCESSOR

const DEFAULT_VALUE_ACCESSOR: Provider  = {     provide: NG_VALUE_ACCESSOR,     useExisting: forwardRef(() => DefaultControlValueAccessor) }  @Directive({     selector: "input:not([type=checkbox])[ngModel]",     providers: [DEFAULT_VALUE_ACCESSOR] }) export class DefaultControlValueAccessor extends BaseControlValueAccessor implements ControlValueAccessor {         writeValue(value: string): void {         this.setProperty("value", value)     }      @HostListener("input", ["$event.target.value"]) onInput(value: string) {         this.onChange(value)     } } 
Enter fullscreen mode Exit fullscreen mode

ngModel can inject this DI token and get hold of correct CVA directive created.

constructor(@Inject(NG_VALUE_ACCESSOR) valueAccessor: ControlValueAccessor) {     this.valueAccessor = valueAccessor;   } 
Enter fullscreen mode Exit fullscreen mode

ngModel register itself using registerOnChange method of the injected control value accessor directive instance so that it gets all updates made by user on the host element and thus emit the updated data back to component using ngModelChange event emitter.

How ngModel works with custom form elements?

@Component({   selector: 'choose-quantity',   templateUrl: "choose-quantity.component.html",   styleUrls: ["choose-quantity.component.scss"],   providers: [     {       provide: NG_VALUE_ACCESSOR,       multi:true,       useExisting: ChooseQuantityComponent     }   ] }) export class ChooseQuantityComponent implements ControlValueAccessor { 
Enter fullscreen mode Exit fullscreen mode

Actually, what ngModel cares about is control value accessor and a component representing a custom form element can simply implement control value accessor interface and configure itself as a service on the DI token NG_VALUE_ACCESSOR

Please share your thought and doubts in the comment section.

If you love exploring the angular form internals and recreate it from scratch with me, you can visit my YouTube channel

angularangularformsjavascriptwebdev
  • 0 0 Answers
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

Sidebar

Ask A Question

Stats

  • Questions 4k
  • Answers 0
  • Best Answers 0
  • Users 1k
  • Popular
  • Answers
  • Author

    How to ensure that all the routes on my Symfony ...

    • 0 Answers
  • Author

    Insights into Forms in Flask

    • 0 Answers
  • Author

    Kick Start Your Next Project With Holo Theme

    • 0 Answers

Top Members

Samantha Carter

Samantha Carter

  • 0 Questions
  • 20 Points
Begginer
Ella Lewis

Ella Lewis

  • 0 Questions
  • 20 Points
Begginer
Isaac Anderson

Isaac Anderson

  • 0 Questions
  • 20 Points
Begginer

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore, ask, and connect. Join our vibrant Q&A community today!

About Us

  • About Us
  • Contact Us
  • All Users

Legal Stuff

  • Terms of Use
  • Privacy Policy
  • Cookie Policy

Help

  • Knowledge Base
  • Support

Follow

© 2022 Querify Question. All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.