{"id":21696329,"url":"https://github.com/dinanathsj29/angular-forms-templatedriven-tutorial","last_synced_at":"2026-05-10T10:10:58.166Z","repository":{"id":38734053,"uuid":"193945609","full_name":"dinanathsj29/angular-forms-templatedriven-tutorial","owner":"dinanathsj29","description":"Learn Angular Forms API specially Template Driven Forms approach from basics to advanced level.","archived":false,"fork":false,"pushed_at":"2023-01-05T20:19:14.000Z","size":8997,"stargazers_count":1,"open_issues_count":12,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-25T14:11:25.062Z","etag":null,"topics":["angular-forms","angular-template-driven-forms","formsmodule","ng-invalid","ng-touched","ng-valid","ngform","ngmodel","ngmodelgroup","template-driven-forms","template-reference-variable"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dinanathsj29.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-06-26T16:59:53.000Z","updated_at":"2020-04-20T10:26:08.000Z","dependencies_parsed_at":"2022-08-29T04:51:17.558Z","dependency_job_id":null,"html_url":"https://github.com/dinanathsj29/angular-forms-templatedriven-tutorial","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dinanathsj29%2Fangular-forms-templatedriven-tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dinanathsj29%2Fangular-forms-templatedriven-tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dinanathsj29%2Fangular-forms-templatedriven-tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dinanathsj29%2Fangular-forms-templatedriven-tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dinanathsj29","download_url":"https://codeload.github.com/dinanathsj29/angular-forms-templatedriven-tutorial/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244635919,"owners_count":20485440,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular-forms","angular-template-driven-forms","formsmodule","ng-invalid","ng-touched","ng-valid","ngform","ngmodel","ngmodelgroup","template-driven-forms","template-reference-variable"],"created_at":"2024-11-25T19:19:29.712Z","updated_at":"2026-05-10T10:10:53.135Z","avatar_url":"https://github.com/dinanathsj29.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./_images-angular-forms-templatedriven/angular_logo_1.png\" alt=\"Angular logo\" title=\"Angular logo\" width=\"200\" /\u003e\n\u003c/p\u003e\n\nAngular Template Driven Forms\n=====================\n\nWorking with existing/cloned/copied Angular App\n---------------------\n- Clone or Download the project/app from Github or any other sources\n- If using Visual Studio Code / Insiders, open Command panel/terminal from menu: View -\u003e Terminal (shortcut key is `CTRL + BackTick` OR `COMMAND + J`)\n- Go inside the project/app directory, command: `cd _examples-angular-templateDrivenForm OR cd templateDrivenForm`\n- Run command: `npm install` to install project/app dependencies `(node_modules)`\n- To Build and run Angular App, command: `ng serve / npm start` OR `ng serve -o` OR `ng serve --open`\n- To change the port from 4200 to other port - type command:  `ng serve --port 5000`\n- To check the application in browser type path/URL: `localhost:4200 / 5000`\n\n1 - Angular Forms - Introduction\n=====================\n1.1. Introduction to forms in Angular\n---------------------\n- Forms are the main, critical building block of any modern front-end Web/Mobile application\n- `The real objective of forms is gathering data`\n- While dealing with Forms one should create an efficient and effective workflow, User Experience (UX) and User Interface (UI) which guide users properly\n- In the context of Form, the Angular framework provides support for `two-way data binding, change tracking, validation, and error handling`\n\n#### Forms are an important and vital part of any business applications, Forms are used to:\n- Authentication\n- Register / Login / Profile creation\n- Submit request / Place an Order\n- Pay Bills\n- Schedule appointments\n- Also to perform many other countless data entry operations/tasks\n\n#### As Developers while dealing with Forms, we have to perform the following tasks:\n- Data binding\n- Change tracking\n- Validation\n- Visual feedback\n- Error messages\n- Form submission\n\n1.2. Prerequisites to working with Angular Forms (Basic to Intermediate knowledge):\n---------------------\nBasic familiarity with HTML, CSS, and JavaScript, Angular 2/4/5/6 is a must. \n\n- HTML          - Markup\n- CSS           - Style, Formates\n- JavaScript    - Behaviour, Click, Validations\n- Angular       - Templates, Components, Data Binding, Modules, Services, etc.\n- TypeScript basics - Advanced JS features (Class, Arrow Function, Spread Operator)\n- Text Editor / Visual Text Editors\n\n1.3. Setup the Angular development environment:    \n---------------------\nIn this section, we will learn how to set up a local development environment to start developing Angular apps. \n\n- `Node`, (website: https://nodejs.org/en) \n- `NPM`, (Node Package Manager - comes inbuilt with Node)\n- `Angular CLI = Command Line Interface`, Angular CLI (Command Line Interface) for angular (website:  https://cli.angular.io/), \n    - The quickest and easiest way of starting an Angular app is through the `Angular CLI (Command Line Interface)`. It allows/helps the developer to build/generate building blocks of angular application like component, services, routings, modules, etc. with best practices quicker and easier)\n- `Text Editor`\n    - Visual Studio Code / Visual Studio Code Insiders (website: https://code.visualstudio.com)\n    - Sublime Text, \n    - Atom, \n    - Brackets etc.\n\n1.4. Anatomy / Mechanism / Concept behind Angular Forms:\n---------------------\nComponent Template Markup `(.HTML view - Collects data)` -\u003e Class `(.TS - Binds Data)` -\u003e Services `(.TS Send Data)` -\u003e Server\n\n1.5. Angular Forms Types/techniques/strategies/approaches:\n---------------------\n1. **Template Driven Forms**: \n    - Primarily depends on the component template (manual HTML)\n    - Most of the code written in the component (.HTML) template file\n    - Template-driven forms are useful for adding a simple form to an app, such as an email list, signup form, etc.\n2. **Reactive Model Driven Forms**: \n    - Primarily depends on the component class (dynamic)\n    - Majority of code written in component .ts class file\n    - Reactive forms are more robust, scalable, reusable, and testable\n\n2 - Angular Template Driven Forms (TDFs)\n=====================\nIn Template Driven forms, most of the logic/code resides in the .HTML/view/template file. The template is responsible for setting up the form, the validation, control, group etc. \n\n2.1 Template Driven Forms (TDFs) - what is it all about?\n---------------------\n- Template Driven Forms (TDFs) are easy to use and similar to AngularJs (Angular 1.x) forms\n- TDFs are mainly/heavily relay and depends on `Two Way Data Binding`\n- The `ngModel` directives take care of actual input field values and data changes\n- TDFs most of the code is a manual template, so it consists of bulky (.HTML) code/markups and minimal component code\n- `ngForm` directive along with `ngModel` directive automatically tracks the form and form elements state \u0026 validity\n\n2.2 Drawback of TDF\n---------------------\n- `Unit testing` is the biggest challenge (we need to run `End2End test (e2e)` with browser)\n- Due to heavy markup in the template, `readability decreases and markup code looks complex`\n- TDFs are `suitable for simple scenarios` only, Reactive forms are used for complex validations, unit test validations       \n\n2.3 Steps to create and use Template Driven Forms (TDFs):\n---------------------\n1. Create/generate new Angular CLI project\n2. Add a form HTML/markup\n3. Binding the Data (`ngForm` and `ngModel` directives)\n4. Tracking state and validity (Add validation using `built-in validators`)\n5. Providing visual Feedback (Display meaningful messages-feedbacks)\n6. Displaying error messages (Display validation errors)\n7. Posting data to server/`express server` (Handle form submission using `ngSubmit`)\n\n3 - Setting up new Angular project\n=====================\n1. First check `angular cli` installed version details on machine by using command at command prompt: `ng -v` or `ng --version`\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/03-01-01-angular-cli.png\" alt=\"Angular CLI version\" title=\"command: `ng -v` or `ng --version` to check angular cli version\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Angular CLI version\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n2. If `angular CLI` not installed/available on machine (no version or error message displayed) then install it by using the command: `npm install -g @angular/cli@latest`\n3. To `update/upgrade angular CLI` to the latest version, use following commands in sequence:\n    - command: `npm uninstall -g @angular/cli`\n    - command: `npm cache verify or npm cache clean`\n    - command: `npm install -g @angular/cli@latest`\n4. Generate/create a new Angular app/project with Angular CLI - for dealing with angular forms with the syntax: `ng new appName` or `ng new project-name`, command: `ng new angular-forms-templatedriven` (after creation check the newly generated folder structure)\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/03-01-02-angular-project-structure.png\" alt=\"Angular project/app folder structure\" title=\"Angular project/app folder structure\" width=\"500\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Angular project/app folder structure\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n5. To run/serve the application, at command prompt type command: `ng serve` or `ng serve --port 5000` (change the port number)\n6. Go to the browser and load the application by typing address: `http://localhost:4200/` or `http://localhost:5000/`\n7. Add the `Bootstrap` framework to an application (CSS framework used to make cool/intuitive User Interface and look/feel)\n    - Download bootstrap css to local machine from bootstrap website: https://getbootstrap.com/docs/4.1/getting-started/download/ into folder `assets/library/bootstrap.min.css`\n    - Include bootstrap in application - index.html under `head` tag - `\u003clink rel=\"stylesheet\" href=\"./assets/library/bootstrap.min.css\" integrity=\"sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO\" crossorigin=\"anonymous\" /\u003e`\n    - or you can include a `CDN` path in index.html under head tag\n    - or else you can install bootstrap with npm command: `npm install bootstrap` and use it\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/03-01-03-bootstrap-cdn.png\" alt=\"Bootstrap website - installation options\" title=\"Bootstrap website - installation options\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Bootstrap website - installation options\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n8. To verify bootstrap included/working properly in an application, check in Browser fonts, etc changed or not?\n    - Also in `app.component.html` just create any simple component like buttons or divs with bootstrap class: \n        - `\u003cbutton class=\"btn btn-success\"\u003eSuccess Button\u003c/button\u003e`  or \n        - `\u003cdiv class=\"lead\"\u003eLead Heading\u003c/div\u003e`\n        - Right click on element and check in `inspect element` the bootstrap class and properties applied to respective elements\n\n\u003e **Syntax \u0026 Example**: index.html\n```html\n\u003c!doctype html\u003e\n\u003chtml lang=\"en\"\u003e\n\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\"\u003e\n    \u003ctitle\u003eTemplateDrivenForms\u003c/title\u003e\n    \u003cbase href=\"/\"\u003e\n\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\"\u003e\n    \u003clink rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\"\u003e\n    \u003clink rel=\"stylesheet\" href=\"./assets/library/bootstrap.min.css\" integrity=\"sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO\" crossorigin=\"anonymous\" /\u003e\n  \u003c/head\u003e\n\n  \u003cbody\u003e\n\n    \u003capp-root\u003e \u003c/app-root\u003e\n\n  \u003c/body\u003e\n\n\u003c/html\u003e\n```\n\n4 - Adding Form Markup-Template HTML\n=====================\n4.1. Create an enrollment form with bootstrap classes: \n--------------------- \n- In file `app.component.html` create a enrollment form\n    1. Use bootstrap classes like `form-group`, `form-control`, `form-check` and `form-check-input`, etc. with div and input field respectively to create a form fields with standard look and feel\n    2. Create a name and email `input` fields\n    3. Create a `Drop-Down` menu with `\u003cselect\u003e` tag and add/show drop down menu options with `*ngFor` structural directive\n    4. Create a `radio` button group with `\u003cinput type=\"radio\"\u003e` to show/select Time preference \n    5. Create a `checkbox` with `\u003cinput type=\"checkbox\"\u003e` to check/opt for promotional offer\n- In `app.component.ts` class file \n    1. Create a new property `topics` to store an array of topics and to display as a select drop-down menu options\n\n\u003e **Syntax \u0026 Example**: app.component.html\n```html\n\u003cdiv class=\"container-fluid\"\u003e\n    \u003ch1\u003eEnrollment Form\u003c/h1\u003e\n    \u003chr /\u003e\n\n    \u003cform\u003e\n\n        \u003c!-- name --\u003e\n        \u003cdiv class=\"form-group\"\u003e\n            \u003clabel for=\"\"\u003eName\u003c/label\u003e\n            \u003cinput type=\"text\" class=\"form-control\"\u003e\n        \u003c/div\u003e\n\n        \u003c!-- email --\u003e\n        \u003cdiv class=\"form-group\"\u003e\n            \u003clabel for=\"\"\u003eEmail\u003c/label\u003e\n            \u003cinput type=\"email\" class=\"form-control\"\u003e\n        \u003c/div\u003e\n\n        \u003c!-- phone --\u003e\n        \u003cdiv class=\"form-group\"\u003e\n            \u003clabel for=\"\"\u003ePhone\u003c/label\u003e\n            \u003cinput type=\"tel\" class=\"form-control\"\u003e\n        \u003c/div\u003e\n\n        \u003c!-- user can select the topics bind with array --\u003e\n        \u003cdiv class=\"form-group\"\u003e\n            \u003cselect class=\"custom-select\"\u003e\n            \u003coption selected\u003eChoose Your Interested Topic\u003c/option\u003e\n            \u003coption *ngFor=\"let topic of topics\"\u003e{{ topic }}\u003c/option\u003e\n            \u003c/select\u003e\n        \u003c/div\u003e\n\n        \u003c!-- radio button group --\u003e\n        \u003cdiv class=\"mb-3\"\u003e\n            \u003clabel for=\"\"\u003eTime Preference\u003c/label\u003e\n            \n            \u003cdiv class=\"form-check\"\u003e\n                \u003cinput type=\"radio\" class=\"form-check-input\" name=\"timePreference\" value=\"morning\"\u003e\n                \u003clabel for=\"\" class=\"form-check-label\"\u003eMorning\u003c/label\u003e\n            \u003c/div\u003e\n\n            \u003cdiv class=\"form-check\"\u003e\n                \u003cinput type=\"radio\" class=\"form-check-input\" name=\"timePreference\" value=\"evening\"\u003e \n                \u003clabel for=\"\" class=\"form-check-label\"\u003eEvening\u003c/label\u003e\n            \u003c/div\u003e\n\n        \u003c/div\u003e\n\n        \u003c!-- checkbox --\u003e\n        \u003cdiv class=\"form-check mb-3\"\u003e\n            \u003cinput type=\"checkbox\" class=\"form-check-input\"\u003e\n            \u003clabel for=\"\" class=\"form-check-label\"\u003eSend me promotional offers\u003c/label\u003e\n        \u003c/div\u003e\n\n        \u003c!-- submit button --\u003e\n        \u003cdiv\u003e\n            \u003cbutton type=\"submit\" class=\"btn btn-primary\"\u003eSubmit\u003c/button\u003e\n        \u003c/div\u003e\n\n    \u003c/form\u003e\n\n\u003c/div\u003e\n```\n\n\u003e **Syntax \u0026 Example**: app.component.ts\n```typescript\n\n/* topics array */\ntopics = ['JavaScript', 'Angular', 'React', 'Vue'];\n\n```\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/04-01-01-form.png\" alt=\"Bootstrap Registration Form\" title=\"Bootstrap Registration Form\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Bootstrap Registration Form\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n\u003chr/\u003e\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/04-01-02-form-drop-down.png\" alt=\"Bootstrap Registration Form with Drop Down Menu *ngFor\" title=\"Bootstrap Registration Form with Drop Down Menu *ngFor\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Bootstrap Registration Form with Drop Down Menu *ngFor\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n5 - Binding Data with ngForm\n=====================\n5.1. Angular Form - Key concepts:\n---------------------\n- **FormsModule**: Angluar template-driven forms are in their own module named `FormsModule`, to use the template driven form, we need to `explicitly import {FormsModule}` in our application module from `@angular/forms`\n\n- **ngForm**: The `ngForm is an instance of the FormGroup`. The FormGroup represents the group of `FormControl` from HTML form tag, each form is a FormGroup because it will have at least one FormControl that gives us access to `(ngSubmit)` which can be bind to a method in our component and triggered when we submit the form. `The NgForm directive supplements the form element with additional features`. \n\n- **ngModel**: We need the `ngModel in the form input, and the input must be named too`. `[(ngModel)]` follows `[(banana in the box)]` syntax and performs `two-way binding` for reading and writing input control values. If a `[(ngModel)]` directive is used, the input field takes an initial value from the bound component class and updates it back whenever any change to the input control value is detected `(on keystroke and button press)`. \n\n- **ngModelGroup**: `ngModelGroup` is useful and helps to create group and sub-groups within forms like `ngModelGroup=\"address\" -\u003e and its sub child's like street, state, postal code, etc., ngModelGroup=\"person\" -\u003e and its sub child's name, age, gender, nationality etc.,` and so on\n\n5.2. To start working with Angular Forms we need to follow some other steps:\n---------------------\n- In `app.module.ts` module class file \n    - import angular `FormsModule` and also include in `imports array`\n- In file `app.component.html` the main markup file\n    - As and When we use `form tag, angular attaches its inbuilt ngForm` directive to give/pass and manage valuable information of forms\n    - `ngForm` directive denotes values of different fields/form-control and also values are valid or invalid\n\n5.3. Template Reference Variable (TRF)\n---------------------\n- Template Reference Variable (TRF) is used to get the complete reference of the ngForm directive, we can use: `\u003cform #userForm=\"ngForm\"\u003e` \n    - Use interpolation to see/get form-control values entered: `{{ userForm.value | json }}` \n    - By default angular does not track each and every form-controls,  to track repsective field use `ngModel` directive with respective form field\n    - Error will generate: \u003cstrong\u003e*`ERROR Error: If ngModel is used within a form tag, either the name attribute must be set or the form control must be defined as 'standalone' in ngModelOptions`*\u003c/strong\u003e\n    - To resolve error we must need to use `name` attribute with every input form-control with `ngModel` : `\u003cinput type=\"text\" class=\"form-control\" name=\"userName\" ngModel\u003e`\n        - Check the difference in `user form.value` object\n        - Enter data in every form field and again verify `userForm.value`\n- We can collect and `send data to the server by using userForm.value` but the better approach is to bind data to `user defined model` and send model data to the server\n\n\u003e **Syntax \u0026 Example**: app.module.ts\n```typescript\nimport { BrowserModule } from '@angular/platform-browser';\nimport { NgModule } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\n\nimports: [\n    BrowserModule, \n    FormsModule\n]\n```\n\n\u003e **Syntax \u0026 Example**: app.component.html\n```html\n\u003cdiv class=\"container-fluid\"\u003e\n    \u003ch1\u003eEnrollment Form\u003c/h1\u003e\n    \u003chr /\u003e\n\n     \u003cform #userForm=\"ngForm\"\u003e\n\n        \u003cspan class=\"lead\"\u003e\u003cstrong\u003eForms Values : userForm.value :\u003c/strong\u003e\u003c/span\u003e {{ userForm.value | json }} \n        \u003chr /\u003e\n\n        \u003c!-- name --\u003e\n        \u003cdiv class=\"form-group\"\u003e\n            \u003clabel for=\"\"\u003eName\u003c/label\u003e\n            \u003cinput type=\"text\" class=\"form-control\" name=\"userName\" ngModel\u003e\n        \u003c/div\u003e\n\n        \u003c!-- email --\u003e\n        \u003cdiv class=\"form-group\"\u003e\n            \u003clabel for=\"\"\u003eEmail\u003c/label\u003e\n            \u003cinput type=\"email\" class=\"form-control\" name=\"email\" ngModel\u003e\n        \u003c/div\u003e\n\n        \u003c!-- phone --\u003e\n        \u003cdiv class=\"form-group\"\u003e\n            \u003clabel for=\"\"\u003ePhone\u003c/label\u003e\n            \u003cinput type=\"tel\" class=\"form-control\" name=\"phone\" ngModel\u003e\n        \u003c/div\u003e\n\n        \u003c!-- user can select the topics bind with array --\u003e\n        \u003cdiv class=\"form-group\"\u003e\n            \u003cselect class=\"custom-select\" name=\"topic\" ngModel\u003e\n            \u003coption selected\u003eChoose Your Interested Topic\u003c/option\u003e\n            \u003coption *ngFor=\"let topic of topics\"\u003e{{ topic }}\u003c/option\u003e\n            \u003c/select\u003e\n        \u003c/div\u003e\n\n        \u003c!-- radio button group --\u003e\n        \u003cdiv class=\"mb-3\"\u003e\n            \u003clabel for=\"\"\u003eTime Preference\u003c/label\u003e\n            \n            \u003cdiv class=\"form-check\"\u003e\n            \u003cinput type=\"radio\" class=\"form-check-input\" name=\"timePreference\" value=\"morning\" ngModel\u003e\n            \u003clabel for=\"\" class=\"form-check-label\"\u003eMorning\u003c/label\u003e\n            \u003c/div\u003e\n\n            \u003cdiv class=\"form-check\"\u003e\n            \u003cinput type=\"radio\" class=\"form-check-input\" name=\"timePreference\" value=\"evening\" ngModel\u003e \n            \u003clabel for=\"\" class=\"form-check-label\"\u003eEvening\u003c/label\u003e\n            \u003c/div\u003e\n\n        \u003c/div\u003e\n\n        \u003c!-- checkbox --\u003e\n        \u003cdiv class=\"form-check mb-3\"\u003e\n            \u003cinput type=\"checkbox\" class=\"form-check-input\" name=\"subscribe\" ngModel\u003e\n            \u003clabel for=\"\" class=\"form-check-label\"\u003eSend me promotional offers\u003c/label\u003e\n        \u003c/div\u003e\n\n        \u003c!-- submit button --\u003e\n        \u003cdiv\u003e\n            \u003cbutton type=\"submit\" class=\"btn btn-primary\"\u003eSubmit\u003c/button\u003e\n        \u003c/div\u003e\n\n    \u003c/form\u003e\n\n\u003c/div\u003e\n```\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/05-01-01-ngmodel-error.png\" alt=\"Template Driven Form - ngModel error\" title=\"Template Driven Form - ngModel error\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Template Driven Form - ngModel error\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n\u003chr/\u003e\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/05-01-02-form-value-object.png\" alt=\"Form Model, FormControl/FormGroup - defualt values\" title=\"Form Model, FormControl/FormGroup - defualt values\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Form Model, FormControl/FormGroup - defualt values\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n\u003chr/\u003e\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/05-01-03-form-value-object.png\" alt=\"Form Model, FormControl/FormGroup - updated values\" title=\"Form Model, FormControl/FormGroup - updated values\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Form Model, FormControl/FormGroup - updated values\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n6 - Binding Data to a Model\n=====================\n- Here will try to create `user defined model`, as soon as user will enter data will update an instance of user model and send model data to the server\n- Inside the app/project folder/directory generate a new class which acts as a model with the command: `ng generate class User` or `ng g class User` \n- It will generate a new file named: `user.ts`, type in the different `properties` of user class like `name, email, phone - as per fields used in the form`\n- User model is ready with us now create an instance of model in `app.component.ts` with new property named `userModel` which consists of user default details/information: `userModel = new User('Dinanath', 'dinanathj@gmail.com', 9892221165, 'default', 'morning', true);`\n- Custom userModel instance with data is ready in the class file now its time to `bind userModel with enrollment form using interpolation {{ userModel | JSON }}`\n- To bind the userModel properties with form field use property binding denotes by a square bracket to the ngModel directive and userModel properties `[(ngModel)]=\"userModel.name\"` and so on...\n- `Property data binding by square bracket only is one-way data binding [(ngModel]` -\u003e data flow from class to the view but not flows from view to the class\n- So to implement/achieve two-way `data binding use banana in the box ie [(ngModel)]`, two-way data binding sync model and view\n\n\u003e **Syntax \u0026 Example**: user.ts\n```typescript\nexport class User {\n  constructor(\n    public name: string,\n    public email: string,\n    public phone: number,\n    public topic: string,\n    public timePreference: string,\n    public subscribe: boolean\n  ){}\n}\n```\n\n\u003e **Syntax \u0026 Example**: app.component.ts\n```typescript\nimport { User } from './user';\n\nuserModel = new User('Dinanath', 'dinanathj@gmail.com', 9892221165, 'default', 'morning', true);\n```\n\n\u003e **Syntax \u0026 Example**: app.component.html\n```html\n\u003cdiv class=\"container-fluid\"\u003e\n  \u003ch1\u003eEnrollment Form\u003c/h1\u003e\n  \u003chr /\u003e\n\n  \u003cform\u003e\n\n    \u003cspan class=\"lead\"\u003e\u003cstrong\u003eForms Values : userForm.value :\u003c/strong\u003e\u003c/span\u003e {{ userForm.value | json }} \n    \u003chr /\u003e\n\n    \u003cspan class=\"lead\"\u003e\u003cstrong\u003eForms Values : userModel data :\u003c/strong\u003e\u003c/span\u003e {{ userModel | json }}\n    \u003chr /\u003e\n\n    \u003c!-- name --\u003e\n    \u003cdiv class=\"form-group\"\u003e\n      \u003clabel for=\"\"\u003eName\u003c/label\u003e\n      \u003c!-- two way data binding used to update view and class both --\u003e\n      \u003cinput type=\"text\" class=\"form-control\" name=\"userName\" [(ngModel)]=\"userModel.name\"\u003e\n    \u003c/div\u003e\n\n    \u003c!-- email --\u003e\n    \u003cdiv class=\"form-group\"\u003e\n      \u003clabel for=\"\"\u003eEmail\u003c/label\u003e\n      \u003cinput type=\"email\" class=\"form-control\" name=\"email\" [(ngModel)]=\"userModel.email\"\u003e\n    \u003c/div\u003e\n\n    \u003c!-- phone --\u003e\n    \u003cdiv class=\"form-group\"\u003e\n      \u003clabel for=\"\"\u003ePhone\u003c/label\u003e\n      \u003cinput type=\"tel\" class=\"form-control\" name=\"phone\" [(ngModel)]=\"userModel.phone\"\u003e\n    \u003c/div\u003e\n\n    \u003c!-- user can select the topics bind with array --\u003e\n    \u003cdiv class=\"form-group\"\u003e\n      \u003cselect class=\"custom-select\" name=\"topic\" [(ngModel)]=\"userModel.topic\"\u003e\n      \u003coption value=\"default\"\u003eChoose Your Interested Topic\u003c/option\u003e\n      \u003coption *ngFor=\"let topic of topics\"\u003e{{ topic }}\u003c/option\u003e\n      \u003c/select\u003e\n    \u003c/div\u003e\n\n    \u003c!-- radio button group --\u003e\n    \u003cdiv class=\"mb-3\"\u003e\n      \u003clabel for=\"\"\u003eTime Preference\u003c/label\u003e\n      \n      \u003cdiv class=\"form-check\"\u003e\n      \u003cinput type=\"radio\" class=\"form-check-input\" name=\"timePreference\" value=\"morning\" [(ngModel)]=\"userModel.timePreference\"\u003e\n      \u003clabel for=\"\" class=\"form-check-label\"\u003eMorning\u003c/label\u003e\n      \u003c/div\u003e\n\n      \u003cdiv class=\"form-check\"\u003e\n      \u003cinput type=\"radio\" class=\"form-check-input\" name=\"timePreference\" value=\"evening\" [(ngModel)]=\"userModel.timePreference\"\u003e\n      \u003clabel for=\"\" class=\"form-check-label\"\u003eEvening\u003c/label\u003e\n      \u003c/div\u003e\n\n    \u003c/div\u003e\n\n    \u003c!-- checkbox --\u003e\n    \u003cdiv class=\"form-check mb-3\"\u003e\n        \u003cinput type=\"checkbox\" class=\"form-check-input\" name=\"subscribe\" [(ngModel)]=userModel.subscribe\u003e\n        \u003clabel for=\"\" class=\"form-check-label\"\u003eSend me promotional offers\u003c/label\u003e\n    \u003c/div\u003e\n\n    \u003c!-- submit button --\u003e\n    \u003cdiv\u003e\n        \u003cbutton type=\"submit\" class=\"btn btn-primary\"\u003eSubmit\u003c/button\u003e\n    \u003c/div\u003e\n\n  \u003c/form\u003e\n\n\u003c/div\u003e\n```\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/06-01-01-class-user.png\" alt=\"User Class - works as Data Model\" title=\"User Class - works as Data Model\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - User Class - works as Data Model\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n\u003chr/\u003e\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/06-01-02-formvalue-modelvalue.png\" alt=\"User Class - formvalue, modelvalue\" title=\"User Class - formvalue, modelvalue\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - User Class - formvalue, modelvalue\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n\u003chr/\u003e\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/06-01-03-two-way-data-binding.png\" alt=\"User Class, form model, Two Way Data Binding\" title=\"User Class, form model, Two Way Data Binding\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - User Class, form model, Two Way Data Binding\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n7 - Tracking state and validity\n=====================\n- As Validations are an important aspect of programming, before sending data to the server it's pretty important to `validate the form data and show user respective visual feedback or error message`\n- Using `ngModel` in a form gives you more than just two-way data binding:\n    - It also tells you if the user touched the control (state \u0026 activity), \n    - If the value changed, or \n    - If the value became valid/invalid (validity)\n- The `NgModel` directive doesn't just track state:\n    - It updates the control with special `Angular CSS classes that reflect the state`,\n    - We can leverage/utilize those class names to change the appearance of the control\n\n7.1. Angular classes used to track control state and validity:\n---------------------\nAngular automatically attach classes like `ng-invalid, ng-dirty, ng-touched` to input fields\n\n| STATE                                         | CLASS applied \u003cbr/\u003e (if TRUE)   |  CLASS applied \u003cbr/\u003e (if FALSE)     |\n| ----------------------------------------------|-------------------|-----------------------|\n| The control has been visited/clicked/touched  \u003cbr/\u003e (`class will apply/change only on blur event`, user need to navigate away from form control)        | ng-touched        | ng-untouched          |\n| The controls value has been changed  \u003cbr/\u003e (class will apply when user type something)                                                                    | ng-dirty          | ng-pristine           |\n| The controls value is valid                   | ng-valid          | ng-invalid            |\n\n- Add a `#Template Reference Variable (#TRV)` named `#name` to the `Name \u003cinput\u003e field` and use it to display the input's CSS classes\n    - Use interpolation to see/get form-control classes: `{{ name.className }}` \n    - Right click on element and check in browser `inspect element` panel the respective angular state classes applied\n\n\u003e **Syntax \u0026 Example**: app.component.html (to apply state and class)\n```html\n\u003c!-- name --\u003e\n\u003cdiv class=\"form-group\"\u003e\n    \u003clabel for=\"\"\u003eName\u003c/label\u003e\n    \u003c!-- two way data binding used to update view and class both --\u003e\n    \u003cinput type=\"text\" #name required class=\"form-control\" name=\"userName\" [(ngModel)]=\"userModel.name\"\u003e\n\u003c/div\u003e\n\n\u003cspan class=\"text-primary\"\u003e\u003cstrong\u003eAngular Classes : name.className :\u003c/strong\u003e\u003c/span\u003e {{ name.className }}\n```\n\n7.2. Angular classes and properties used to track control state and validity:\n---------------------\n- With each of the `state classes` angular also provide an alternative associated `state properties` on the ngModel directive\n    - properties names are the same as the class name, only `ng-` removed from it\n\n| CLASS                                     | PROPERTY                                  |\n| ------------------------------------------|-------------------------------------------|\n| .ng-untouched                              | untouched                                 |\n| .ng-touched                                | touched                                   |\n| .ng-pristine                               | pristine                                  |\n| .ng-dirty                                  | dirty                                     |\n| .ng-valid                                  | valid                                     |\n| .ng-invalid                                | invalid                                   |\n\n- `#name` reference variable by default point to input element/field of DOM, by assigning `#name=\"ngModel\"` will `point to ngModel` so all ngModel properties will be available to us\n    - Use interpolation to see/get form-control properties: `{{ name.touched }} {{ name.pristine }} {{ name.valid }}` \n    - Right click on element and check in browser `inspect element` panel the respective angular state classes applied with respective properties\n\n\u003e **Syntax \u0026 Example**: app.component.html (to apply state and properties)\n```html\n\u003c!-- name --\u003e\n\u003cdiv class=\"form-group\"\u003e\n    \u003clabel for=\"\"\u003eName\u003c/label\u003e\n    \u003c!-- two way data binding used to update view and class both --\u003e\n    \u003cinput type=\"text\" #name=\"ngModel\" required class=\"form-control\" name=\"userName\" [(ngModel)]=\"userModel.name\"\u003e\n\u003c/div\u003e\n\n\u003cspan class=\"text-success\"\u003e\u003cstrong\u003eAngular ngModel properties used for input fields:\u003c/strong\u003e touched - {{ name.touched }} \u003cspan class=\"text-warning\"\u003e|\u003c/span\u003e pristine - {{ name.pristine }} \u003cspan class=\"text-warning\"\u003e|\u003c/span\u003e valid - {{ name.valid }}\u003c/span\u003e\n```\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/07-01-01-form-state-class-default.png\" alt=\"Form - State class - default\" title=\"Form - State class - default\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Form - State class - default\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n\u003chr/\u003e\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/07-01-02-form-state-class-changed.png\" alt=\"Form - State class - changed/upated/modified\" title=\"Form - State class - changed/upated/modified\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Form - State class - changed/upated/modified\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n\u003chr/\u003e\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/07-01-03-form-state-properties-default.png\" alt=\"Form - State Properties - default\" title=\"Form - State Properties - default\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Form - State Properties - default\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n\u003chr/\u003e\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/07-01-04-form-state-properties-changed.png\" alt=\"Form - State Properties - changed/upated/modified\" title=\"Form - State Properties - changed/upated/modified\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Form - State Properties - changed/upated/modified\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n8- Validation with Visual Feedback\n=====================\n- A good user experience is to visually indicate to the user `form field is valid/invalid` while feeling up the form/entering the details\n- Usually one can use attributes/properties like `Required, Maxlength, Minlength and Pattern` for form validation on form input fields \n- We can use Angular inbuilt validation classes or can create a custom css class and use for indication\n\n\u003e **Note**: bootstrap uses a class `'is-invalid'` to show a red border around input fields\n\n\u003e **Syntax \u0026 Example**: styles.css\n```css\n/* create custom css class for indicating invalid visual border */\n.form-control.ng-invalid.ng-touched {\n  border: 1px solid coral;\n  box-shadow: 1px 1px 5px 1px coral;\n}\n```\n\n- Check if the name is `invalid` and also `touched` (something entered and removed) then only apply a bootstrap/custom class named `'is-invalid'` but don't apply initially without touch:\n- Apply pattern matching validation input only `10 digits mobile number - pattern=\"^\\d{10}$\" `\n\n\u003e **Syntax \u0026 Example**: app.component.html (apply validation class to show red border)\n```html\n \u003c!-- name --\u003e\n\u003cdiv class=\"form-group\"\u003e\n    \u003clabel for=\"\"\u003eName\u003c/label\u003e\n    \u003c!-- two way data binding used to update view and class both --\u003e\n    \u003cinput type=\"text\" #name=\"ngModel\" required [class.is-invalid]=\"name.invalid \u0026\u0026 name.touched\" class=\"form-control\" name=\"userName\" [(ngModel)]=\"userModel.name\" placeholder=\"Name required*\"\u003e\n\u003c/div\u003e\n\n\u003c!-- phone --\u003e\n\u003cdiv class=\"form-group\"\u003e\n    \u003clabel for=\"\"\u003ePhone\u003c/label\u003e\n    \u003cinput type=\"tel\" #phone=\"ngModel\" required pattern=\"^\\d{10}$\" [class.is-invalid]=\"phone.invalid \u0026\u0026 phone.touched\"class=\"form-control\" name=\"phone\" [(ngModel)]=\"userModel.phone\" placeholder=\"10 digits mobile number\"\u003e\n\u003c/div\u003e\n```\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/08-01-01-form-properties-class-default.png\" alt=\"Form Default properties/class\" title=\"Form Default properties/class\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Form Default properties/class\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n\u003chr/\u003e\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/08-01-02-form-properties-class-red-border.png\" alt=\"Form field - show Red border\" title=\"Form field - show Red border\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Form field - show Red border\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n9 - Displaying Error Messages\n=====================\n- Its essential/advisable to show user visual red border with appropriate Error Messages/feedback\n\n\u003e **Note**: Bootstrap class `'d-none'` is used to `hide/display:none` for any element. We can use either `'*ngIf'` or `'class binding'` or both to display error messages.\n\n9.1. Showing single error with a class binding:\n---------------------\n\u003e **Syntax \u0026 Example**: app.component.html\n```html\n\u003c!-- name --\u003e\n\u003cdiv class=\"form-group\"\u003e\n    \u003clabel for=\"\"\u003eName\u003c/label\u003e\n    \u003c!-- two way data binding used to update view and class both --\u003e\n    \u003cinput type=\"text\" #name=\"ngModel\" required [class.is-invalid]=\"name.invalid \u0026\u0026 name.touched\" class=\"form-control\" name=\"userName\" [(ngModel)]=\"userModel.name\" placeholder=\"Name required*\"\u003e\n\n    \u003c!-- single error with a class binding --\u003e\n    \u003csmall class=\"text-danger\" [class.d-none]=\"name.valid || name.untouched\"\u003e* Name is required\u003c/small\u003e\n\u003c/div\u003e\n\n\u003c!-- phone --\u003e\n\u003cdiv class=\"form-group\"\u003e\n    \u003clabel for=\"\"\u003ePhone\u003c/label\u003e\n    \u003cinput type=\"tel\" #phone=\"ngModel\" required pattern=\"^\\d{10}$\" [class.is-invalid]=\"phone.invalid \u0026\u0026 phone.touched\"class=\"form-control\" name=\"phone\" [(ngModel)]=\"userModel.phone\" placeholder=\"10 digits mobile number\"\u003e\n\n    \u003c!-- single error with a class binding --\u003e\n    \u003csmall class=\"text-danger\" [class.d-none]=\"phone.valid || phone.untouched\"\u003eEnter 10 digits mobile number\u003c/small\u003e\n\u003c/div\u003e\n```\n\n9.2. Showing group or multiple error messages: error property:\n---------------------\n- Some times we come across a scenario where we need to apply multiple validations and also we need to show a different error message \n\n\u003e **Syntax \u0026 Example**: app.component.html\n```html\n\u003c!-- phone --\u003e\n\u003cdiv class=\"form-group\"\u003e\n    \u003clabel for=\"\"\u003ePhone\u003c/label\u003e\n    \u003cinput type=\"tel\" #phone=\"ngModel\" required pattern=\"^\\d{10}$\" [class.is-invalid]=\"phone.invalid \u0026\u0026 phone.touched\"class=\"form-control\" name=\"phone\" [(ngModel)]=\"userModel.phone\" placeholder=\"10 digits mobile number\"\u003e\n\n    \u003c!-- single error with a class binding --\u003e\n    \u003c!-- \u003csmall class=\"text-danger\" [class.d-none]=\"phone.valid || phone.untouched\"\u003eEnter 10 digits mobile number\u003c/small\u003e --\u003e\n\n    \u003c!-- group or multiple error messages : error property --\u003e\n    \u003cdiv *ngIf=\"phone.errors \u0026\u0026 (phone.invalid || phone.touched)\"\u003e\n        \u003csmall class=\"text-danger\" *ngIf=\"phone.errors.required\"\u003e* Phone is required\u003c/small\u003e\n        \u003csmall class=\"text-danger\" *ngIf=\"phone.errors.pattern\"\u003e* Phone number must be 10 digits\u003c/small\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n```\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/09-01-01-form-properties-class-error-message.png\" alt=\"Class binding error messages\" title=\"Class binding error messages\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Class binding error messages\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n\u003chr/\u003e\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/09-01-02-form-error-property-multiple.png\" alt=\"Error property showing multiple/different errors\" title=\"Error property showing multiple/different errors\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Error property showing multiple/different errors\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n\u003chr/\u003e\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/09-01-03-form-error-property-multiple.png\" alt=\"Error property showing multiple/different errors\" title=\"Error property showing multiple/different errors\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Error property showing multiple/different errors\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n10 - Select control validation\n=====================\n#### `Select option drop down menu` validation with required and showing error message: we need to listen/check `'Blur'/'Change'` event and verify option selected and accordingly set validation/show error messages:\n\n\u003e **Syntax \u0026 Example**: app.component.html\n```html\n\u003c!-- user can select the topics bind with array --\u003e\n\u003cdiv class=\"form-group\"\u003e\n    \u003cselect (blur)=\"validateChoosenTopic(topic.value)\" (change)=\"validateChoosenTopic(topic.value)\" #topic=\"ngModel\" [class.is-invalid]=\"topicHasError \u0026\u0026 topic.touched\" class=\"custom-select\" name=\"topic\" [(ngModel)]=\"userModel.topic\"\u003e\n        \u003coption value=\"default\"\u003eChoose Your Interested Topic\u003c/option\u003e\n        \u003coption *ngFor=\"let topic of topics\"\u003e{{ topic }}\u003c/option\u003e\n    \u003c/select\u003e\n\n    \u003csmall class=\"text-danger\" [class.d-none]=\"!topicHasError ||topic.untouched\"\u003ePlease choose right topic\u003c/small\u003e\n\u003c/div\u003e\n```\n\n\u003e **Syntax \u0026 Example**: app.component.ts\n```typescript\n// class member to hold select option error state\ntopicHasError = true;\n\n// select option validation\nvalidateChoosenTopic(curValue) {\nif (curValue === 'default') {\n        this.topicHasError = true;\n    } else {\n        this.topicHasError = false;\n    }\n}\n```\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/10-01-01-form-select-option-validation.png\" alt=\"Topic Select Dropdown validation\" title=\"Topic Select Dropdown validation\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Topic Select Dropdown validation\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n11 - Form level validation\n=====================\n- Whenever we add the `\u003cform\u003e` tag/element in to the html page, angular automatically attaches the `'ngForm'` directive to the form tag\n- We can get the reference of the `'ngForm'` directive by using `#Template Reference Variable (#TRV)`, example: `\u003cform #userForm=\"ngForm\"\u003e`\n- Form validation properties can be used for global level operations like `enable/disable of 'SUBMIT'` button etc.\n- Use interpolation to see/get form-validation status: `{{ userForm.form.valid }} ` \n\n\u003e **Syntax \u0026 Example**: app.component.html\n```html\n\u003cform #userForm=\"ngForm\"\u003e\n\n  \u003cspan class=\"lead\"\u003e\u003cstrong\u003eForm Validation status : userForm.form.valid :\u003c/strong\u003e\u003c/span\u003e {{ userForm.form.valid }} \n\n  \u003c!-- submit button --\u003e\n  \u003cdiv\u003e\n    \u003c!-- form level validation to enable/disable button --\u003e\n    \u003cbutton [disabled]=\"userForm.form.invalid || topicHasError\" type=\"submit\" class=\"btn btn-primary\"\u003eSubmit\u003c/button\u003e\n  \u003c/div\u003e\n```\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/11-01-01-form-userform-valid.png\" alt=\"userForm.form.valid status - Success\" title=\"userForm.form.valid status - Success\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - userForm.form.valid status - Success\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n\u003chr/\u003e\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/11-01-02-form-userform-invalid.png\" alt=\"userForm.form.valid status - false/invalid\" title=\"userForm.form.valid status - false/invalid\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - userForm.form.valid status - false/invalid\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n12 - Submitting form data\n=====================\n1. Use `'novalidate'` attribute to form tag to avoid/prevent browser `default validations` when will click on 'SUBMIT' button\n    - ```\u003cform #userForm=\"ngForm\" novalidate\u003e```\n2. Bind `'ngSubmit'` event to the form tag which will trigger on 'SUBMIT' button\n    - ```\u003cform #userForm=\"ngForm\" novalidate (ngSubmit)=\"onSubmit()\"\u003e```\n3. Define `onSubmit()` event handler in `app.component.ts` class file\n\n\u003e **Syntax \u0026 Example**: app.component.html\n```html\n\u003cform #userForm=\"ngForm\" novalidate (ngSubmit)=\"onSubmit()\"\u003e\n```\n\n\u003e **Syntax \u0026 Example**: app.component.ts\n```typescript\n// handler for submit button\nonSubmit() {\n    console.log('submit button clicked');\n    console.log(this.userModel);\n}\n```\n\n4. To send data to the server we need to create/use `'enrolment service'` with angular CLI by using the command: `ng generate service enrollment` or `ng g s enrollment`  \n    - `enrollment.service.ts:`\n        - Import HttpClient module: import { HttpClient } from '@angular/common/http';\n        - Invoke HttpClient in constructor as a local variable / Dependency injection:  \u003cbr/\u003e\n        constructor(public _httpClient:HttpClient) { }\n5. `app.module.ts: `\n    - import HttpClientModule: import { HttpClientModule } from '@angular/common/http'; \n    - add to the imports array: \u003cbr/\u003e\n    imports: [\n        BrowserModule, \n        FormsModule,\n        HttpClientModule\n    ], \n6. `enrollment.service.ts:` \n    - // create a variable which hold path to which will post the date \u003cbr/\u003e\n     _url = 'http://localhost:3000/enroll';\n    - // create a method called enroll which will post the data to server \u003cbr/\u003e\n    enroll(user:User){\n        return this._httpClient.post`\u003cany\u003e`(this._url,user);\n    }\n7. `app.component.ts: `\n    - The Post request will return response as an `observable`, so we need to subscribe to observables in app.component.ts\n    - Import enrollment service: import { EnrollmentService } from './enrollment.service';\n    - Invoke in constructor as a local variable / Dependency injection: \u003cbr/\u003e \n    constructor(public enrollmentService:EnrollmentService) { }\n    - On submit button clicked i.e. in onSubmit() method subscribe to the observables: \u003cbr/\u003e \n\n\u003e **Syntax \u0026 Example**: app.module.ts\n```typescript\nimport { BrowserModule } from '@angular/platform-browser';\nimport { NgModule } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { HttpClientModule } from '@angular/common/http';\nimport { AppComponent } from './app.component';\n\n@NgModule({\n  declarations: [\n    AppComponent,\n  ],\n  imports: [\n    BrowserModule, \n    FormsModule,\n    HttpClientModule\n  ],\n  providers: [],\n  bootstrap: [AppComponent]\n})\nexport class AppModule { }\n```\n\n\u003e **Syntax \u0026 Example**: enrollment.service.ts\n```typescript\nimport { Injectable } from '@angular/core';\nimport { HttpClient, HttpErrorResponse } from '@angular/common/http';\nimport { User } from './user';\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class EnrollmentService {\n  // create a variable which holds the path to which will post the date\n  _url = 'http://localhost:3000/enroll';\n\n  constructor(public _httpClient: HttpClient) { }\n\n  // create a method called enroll which will post the data to the server\n  enroll(user: User) {\n    return this._httpClient.post\u003cany\u003e(this._url, user)\n  }\n}\n```\n\n\u003e **Syntax \u0026 Example**: app.component.ts\n```typescript\n// handler for submit button\nonSubmit() {\n    console.log('submit button clicked');\n    console.log(this.userModel);\n    this.enrollmentService.enroll(this.userModel)\n      .subscribe(\n        data =\u003e console.log('Success!', data),\n        error =\u003e console.error('Error!', error)\n      )\n  }\n```\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/12-01-01-form-submit-usermodel.png\" alt=\"Submit - Check userModel value\" title=\"Submit - Check userModel value\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Submit - Check userModel value\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n13 - Create Express Server to Receive Form Data\n=====================\n1. At the root, besides the angular application folder create a new siblings folder named `'server'` which consists of server-side code\n2. Run the command: `npm init --yes` to create a `package.json` also bypass-surpass the questions with default answers (without giving answers to questions)\n3. Install express and other dependencies with the command: \u003cbr/\u003e\n    `npm install --save express body-parser cors` \u003cbr/\u003e\n    - **express**: node web server\n    - **body-parse**r: middleware to read/send/pass form data (to handle form data)\n    - **cors**: cross origin port/domain request (helps to make request through multiple ports/servers - cross origin resource sharing)\n\n\u003e **Syntax \u0026 Example**: package.json\n```json\n\"dependencies\": {\n    \"body-parser\": \"^1.18.3\",\n    \"cors\": \"^2.8.4\",\n    \"express\": \"^4.16.3\"\n}\n```\n4. Inside a `server` folder create a new file named `'server.js'` and required logic\n5. At command prompt/terminal run command: `node server` - will get output in terminal as 'Server running on localhost port:  3000'\n6. in browser type path: `'http://localhost:3000/'` - output - 'Hello from server!'\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/13-01-01-form-node-server.png\" alt=\"Node Server Running\" title=\"Node Server Running\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Node Server Running\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n7. add endpoint in server.js to which angular application will post data\n// add endpoint\napp.post('/enroll', function(req,res){\n    // req.body - contains user data send by the angular\n    console.log(req.body);\n    // send response\n    res.status(200).send({'message': 'Data received'});\n})\n8. insert/add endpoint path to angular url variable in 'enrollment.service.ts'\n    _url = 'http://localhost:3000/enroll';\n9. restart the node server by command: `node server`\n10. In angular application click on the submit button and check `inspect element` console as well as node console will get the message and user data as an output. for better usability its advisable to hide actual form/hide submit button / disable submit button etc. to avoid the extra click on submit button.\n\n\u003e **Syntax \u0026 Example**: server.ts\n```typescript\n// 1. imports/requires the packages\nconst express = require('express');\nconst bodyParser = require('body-parser');\nconst cors = require('cors');\n\n// port\nconst PORT = 3000;\n\nconst app = express();\n\n// handle the json data\napp.use(bodyParser.json());\n\napp.use(cors());\n\n// test/check get request\napp.get('/',function(req, res){\n    res.send('Hello from server!');\n})\n\n// add endpoint\napp.post('/enroll', function(req,res){\n    // req.body - contains user data send by the angular\n    console.log(req.body);\n    // send response\n    res.status(200).send({'message': 'Data received'});\n\n    // to see errors \n    // res.status(401).send({'message': 'Data received'});\n})\n\n// listen to request\napp.listen(PORT, function(){\n    console.log('Server running on localhost port: ', PORT);\n})\n```\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/13-01-02-form-console-server-response.png\" alt=\"Template Driven Form - Submit Form data\" title=\"Template Driven Form - Submit Form data\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Template Driven Form - Submit Form data\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n\u003chr/\u003e\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/13-01-03-form-node-response.png\" alt=\"Template Driven Form - Submit Form data with Node Server Response\" title=\"Template Driven Form - Submit Form data with Node Server Response\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Template Driven Form - Submit Form data with Node Server Response\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n\n14 - Error Handling\n=====================\n1. To catch error we need support of `'rxjs'` operators\n\n\u003e **Syntax \u0026 Example**: enrollment.service.ts\n```typescript\n// to catch error\nimport { catchError } from 'rxjs/operators';\nimport { throwError } from 'rxjs';\n\n// create a method called enroll which will post the data to the server\nenroll(user:User){\n    return this.httpClient.post`\u003cany\u003e`(this._url,user)\n      .pipe(catchError(this.errorHandler)) //catch errors\n}\n\nerrorHandler(error: HttpErrorResponse) {\n  return throwError(error);\n}\n```\n2. By defualt we log error to console its advisable to create a new data member/property named 'errorMessage' and bind to the view.\n\u003e **Syntax \u0026 Example**: app.component.ts:\n```typescript\n// store error in data member / property to bind to the view\nerror =\u003e this.errorMessage = error.statusText\n```\n3. \u003e **Syntax \u0026 Example**: app.component.html\n```html\n\u003c!--  errorMessage bind to the view --\u003e\n\u003cdiv class=\"alert alert-danger\" *ngIf=\"errorMessage\"\u003e\n    {{ errorMessage }}\n\u003c/div\u003e\n```\n4. in server.js change:\nres.status(200) to res.status(401).send({'message': 'Data received'});\n5. restart node server, load angular application application, click on submit and check\n\n15 - TDF and Reactive (Model Driven) Approach\n=====================\n- `'ngForm'` directive gives us entire information (different properties/methods/objects/values used with form/form fields)\n- To examine/understand just pass current form ie. `#userForm` parameter in submit button event handler function and check in `inspect element/developer tools` -\u003e console panel:\n- `NgForm` object -\u003e form: `FormGroup` -\u003e `controls` -\u003e each and every form field is of type FormControl\n- `FormGroup` and `FormControl` are building blocks of reactive forms\n- Template Driven Form approach is behind the scene works as Model Driven approach where models are automatically created by angular\n\n\u003e **Syntax \u0026 Example**: app.component.html:\n```html\n\u003cform #userForm=\"ngForm\" novalidate (ngSubmit)=\"onSubmit(userForm)\"\u003e\n```\n\n\u003e **Syntax \u0026 Example**: app.component.ts:\n```ts\nonSubmit(curForm) {\n    console.log('current User Form reactive details: ', curForm);\n}\n```\n\n\u003cp\u003e\n  \u003cfigure\u003e\n    \u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cimg src=\"./_images-angular-forms-templatedriven/15-01-01-tdf-vs-mdf-rf.png\" alt=\"Template Driven Form vs Module Driven/Reactive Form\" title=\"Template Driven Form vs Module Driven/Reactive Form\" width=\"1000\" border=\"2\" /\u003e\n    \u003cfigcaption\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp; Image - Template Driven Form vs Module Driven/Reactive Form\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdinanathsj29%2Fangular-forms-templatedriven-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdinanathsj29%2Fangular-forms-templatedriven-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdinanathsj29%2Fangular-forms-templatedriven-tutorial/lists"}