Tuesday, October 31, 2023

Angular Forms (Part 4) -Template Driven Forms

Angular Template Driven Forms

The Angular Template Driven Forms are simple forms which can be used to develop forms. These are called template driven as everything we are going to use in a application is defined into the template that we are defining along with the component.


--------------------------------------------------------------------------
Validations applied to controls with in a template is called TDF validations
TDF validations is based on HTML5 validations, this will use html5 attributes
 1.required
 2.minlength
 3.maxlength
 4.pattern

Syntax:
   <form #modelname="ngForm"  [ngFormOptions]="{updateOn:'change|blur|submit'}">
   
<input [(ngModel)]="fieldname"  name="controlname"  required|minlength|maxlength|pattern="">
       ...
   </form>

ngForm keyword will generate FormGroup object,this will be referenced
    by modelname
  ->controlname will be considered as model property name,it is recommended
    to provide controlname same as fieldname
  
->FormGroup and FormControl props[like invalid,touched,..] will be same as MDF validations

Steps 

1 Import the namespace

import{FormsModule} from "@angular/forms";

















Create a basic Registration Form








.Ts Changes

import { Component } from '@angular/core';
import { NgForm } from '@angular/forms';

@Component({
  selector: 'app-formsvalidation',
  templateUrl: './formsvalidation.component.html',
  styleUrls: ['./formsvalidation.component.css']
})
export class FormsvalidationComponent {
  RegisterStudent(studentForm: NgForm): void {  
    console.log(studentForm.value);
  }
}


.Html Changes

<div class="container">
    <div class="row">
        <div class="form-bg">
            <form #studentForm="ngForm" (ngSubmit)="RegisterStudent(studentForm)">
              <div class="panel panel-primary">
                <div class="panel-heading">
                  <h3 class="panel-title">Student Registration</h3>
                </div>
                <div class="panel-body">
                 
                  <div class="form-group">
                    <label for="firstName">First Name</label>
                    <input id="firstName" type="text" class="form-control"
                          name="firstName" ngModel>
                  </div>
                  <div class="form-group">
                    <label for="lastName">Last Name</label>
                    <input id="lastName" type="text" class="form-control"
                          name="lastName" ngModel>
                  </div>
                  <div class="form-group">
                    <label for="email">Email</label>
                    <input id="email" type="text" class="form-control"
                          name="email" ngModel>
                  </div>
                </div>
                <div class="panel-footer">
                  <button class="btn btn-primary" type="submit">Submit</button>
                </div>
              </div>
            </form>
        </div>
    </div>
  </div>



Understanding the code

NgForm:

It is the directive which helps to create the control groups inside form directive.

NgModel

When we add ngModel directive to the control, all the input elements are registered with the NgForm.

Next important thing is to consider is that when we use ngModel with form tag, then we should have to use the name property of the HTML control.

#studentForm is called the template reference variable and if you notice we have assigned “ngForm” as the value for the template reference variable studentForm. So the studentForm reference variable holds a reference to the form.

Output




If you get the below error then you might have forgotten to import the formmodule in the
appModule.ts














Validations in Angular Part 3 [MDF Validations]

 FormBuilder class

-----------------
This is used to build a model [ formgroup ] with collection of props without using
 FormControl class

Syntax:
  this.<formgroup>=this.<formbuilder>.group({
                   prop1:["",[validations]],
                       ...
                                 },{updateOn:'..'});



*requirement:

   JobModel
      |
 username   --required
                     pattern[username should allow lower, upper, dot and spaces].

 password   --min length 4 chars
                    max length 8 chars

 mobile      --pattern[10 digit number]----property level updateOn blur

 gender     --required[radiobuttons]

 skillset      --required[listbox-multiple selection--> select tag with multiple]

 country     --required[dropdownlist-single selection-->select tag without multiple]

  terms       --requiredTrue[checkbox]


Create a component











.ts Changes

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-mdf2',
  templateUrl: './mdf2.component.html',
  styleUrls: ['./mdf2.component.css']
})
export class Mdf2Component  implements OnInit{
  _formbuilder:FormBuilder;
  jobmodel:FormGroup;
  info:string | undefined;
 
  constructor() {
    this._formbuilder=new FormBuilder();
    //build a model
    this.jobmodel=this._formbuilder.group({
      username:["",[Validators.required,Validators.pattern("[A-Za-z.\\s]{1,}")]],
      password:["",[Validators.minLength(4),Validators.maxLength(8)]],
      mobile:["",  {validators:[Validators.pattern("[0-9]{10}")],updateOn:'blur'}],
      gender:["",  [Validators.required]],
      skillset:["",[Validators.required]],
      country:["", [Validators.required]],
      terms:  [""  ,[Validators.requiredTrue]]
             });
   }
  ngOnInit(): void {
    throw new Error('Method not implemented.');
  }

   register()
   {
     this.info=this.jobmodel.value.username+":"+this.jobmodel.value.password+":"+this.jobmodel.value.mobile+":"+this.jobmodel.value.gender+":"+this.jobmodel.value.skillset+":"+this.jobmodel.value.country+":"+this.jobmodel.value.terms;
   }
}


.html Changes


<form [formGroup]="jobmodel">
    <div style="font-size:x-large;margin:20px">
        <input formControlName="username" placeholder="username">
        <span *ngIf="jobmodel.controls['username'].hasError('required')">enter username</span>
        <span *ngIf="jobmodel.controls['username'].hasError('pattern')">enter proper username</span>
        <br>
        <input formControlName="password" placeholder="password">
        <span *ngIf="jobmodel.controls['password'].invalid">enter password between 4 to 8 chars</span>
        <br>
        <input formControlName="mobile" placeholder="mobile">
        <span *ngIf="jobmodel.controls['mobile'].invalid">enter 10 digit</span>
        <br>
        <input type="radio" formControlName="gender" value="male"> male
        <input type="radio" formControlName="gender" value="female"> female
        <span *ngIf="jobmodel.controls['gender'].invalid">select gender</span>
        <br>
        skillset:<br>
        <select formControlName="skillset" multiple size="3" style="width: 120px;">
            <option>angular</option>
            <option>reactjs</option>
            <option>core</option>
            <option>aws</option>
        </select>
        <span *ngIf="jobmodel.controls['skillset'].invalid">select skillset</span>
        <br>
        <select formControlName="country">
            <option value="">country</option>
            <option value="ind">india</option>
            <option value="usa">united states</option>
        </select>
        <span *ngIf="jobmodel.controls['country'].invalid">select country</span>
        <br>
        <input type="checkbox" formControlName="terms"> I agree terms and conds
        <br>
        <span *ngIf="jobmodel.controls['terms'].invalid">select terms and conds</span>
        <br>
        <input type="button" value="register" (click)="register()" [disabled]="jobmodel.invalid">
        <br>
        {{info}}
    </div>
</form>


styles.css

input.ng-invalid{
    border:2px solid red;
  }

Note:
-----
* input.ng-invalid css will be applied to textbox,if validation is failed.
*user selected skillset options will be assigned to model prop,the options
 will be seperated by ,

Output




















Monday, October 30, 2023

Validations in Angular Part 2 [MDF Validations]

 example to build a user model with collection of props by applying mdf validations

Create a component.

ng g c mdf1 --flat






Index.html











appModule.ts


Change the Bootstrap Name to the newly created component.











.ts Changes

First, we need to import the namespace

import { FormControl, FormGroup, Validators } from '@angular/forms';


import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-mdf1',
  templateUrl: './mdf1.component.html',
  styleUrls: ['./mdf1.component.css']
})
export class Mdf1Component  implements OnInit{
userModel:FormGroup;
info:string | undefined;

  constructor() {
   //build a model
   this.userModel=new FormGroup(
     {
       firstname:new FormControl("",[Validators.required]),
       lastname:new FormControl("",[Validators.required]),
       emailid:new FormControl("xyz@gmail.com",[Validators.email])
     },{updateOn:'change'}
   );
   }
   register()
   {
     if(this.userModel.valid)
     this.info=this.userModel.value.firstname+":"+this.userModel.value.lastname+":"+this.userModel.value.emailid;
   }
}

.html Changes


<form [formGroup]="userModel" (ngSubmit)="register()">
    <div style="font-size: x-large;margin: 20px;">
        firstname:<input formControlName="firstname">
        <span *ngIf="userModel.controls['firstname'].invalid">
            enter firstname
        </span>
        <br>
        lastname:<input formControlName="lastname">
        <span *ngIf="userModel.controls['lastname'].invalid && userModel.controls['lastname'].touched">
            enter lastname..
        </span>
        <br>
        emailid:<input formControlName="emailid">
        <span *ngIf="userModel.controls['emailid'].invalid">
            enter valid emailid
        </span>
        <br>
        <input type="submit" value="register">
        <br>
        {{info}}
        <br>
        {{userModel.value|json}}
    </div>
</form>


AppModule.ts




















Output


















Explanation

note:
-----
1.styles declared with in styles.css will be global through out the project

2.initially firstname property value is blank,this makes required validation failed
  initially,in this case invalid will return true,so span will show error message
  [enter firstname] initially,initial errormessage display for required validation
  can be avoided using touched property along with invalid
  [this is done for lastname prop]














Modify the above html as

        firstname:<input formControlName="firstname">
        <span *ngIf="userModel.controls['firstname'].invalid && userModel.controls['firstname'].touched">
            enter firstname
        </span>


3.submit button click will call ngsubmit event of form tag,this will
  execute register function

4.control data------>property-----validation-----invalid prop will be
                                                  set with true | false--no error message display
                                                            |
                                                     error message display

5.updateOn will specify, when the controls data to be updated to model props and
  validation should take place
  
 i.change[default]--control editing will be applied to model prop and
                      validation takes place

  ii.blur           --control loosing focus will be applied to model prop and
                      validation takes place

 iii.submit         --submit button click will update all the controls data to all the
                      props and validations will take place



Validations in Angular Part 1 [MDF Validations]

Why we need Forms?

Forms are the main building blocks of any type of application. When we use forms for login, registration, submission. Help request, etc., it is necessary that whatever forms we are developing, they should be user friendly. And it should have the indication of what went wrong by display user friendly message, etc.


Ensuring proper data[input] from user is called "validation"

  eg: username cannot be blank
      mobile requires 10 digit number

*Angular is providing built-in support[code] for validations, this makes developer
 job easy and faster
*Angular supports 2 types of validations
 1.MDF[Model Driven Form] validations
 2.TDF[Template Driven Form] validations

MDF validations:
----------------
*Validations applied to model properties with in a component class is called
 "MDF validations"

*MDF will separate validations from UI, this makes unit testing validations easy
 and provides programming flexibility

*programming flexibility means dynamic controls creation with validation[s] is possible and validations can be referenced | verified from router guards[comes later in the routing]

*MDF validations is also called "ReactiveForm Validations"

*Angular is providing ReactiveFormsModule with @angular/forms package with set of classes to work with MDF validations.


For this, first, we need to create the model using Agular's inbuilt classes like formGroup and formControl and then we need to bind that model to the HTML form.



1.Form Control class--this is used to declare a model property to set | get
                      form control data by applying validation

2 Form Group class --this is used to build a model with collection of props.


3.FormArray class --this is used to create an array of form controls (or) form groups
                      (or) nested form array

     ->formgroup will be serialized into an object
       formarray will be serialized into an array

     ->formgroup doesn't support dynamic controls creation
       formarray supports dynamic controls creation

In order to use Reactive Forms, you need to import ReactiveFormsModule into the applications root module i.e. app.module.ts

4.Validators class--this is providing collection of static methods to perform
                     different types of validations
                    
i. required-   this will validate whether input is provided or not
                               [applied for mandatory fields]
ii. minlength(n)-this will validate user input for minimum no of chars

iii.maxlength(n)-this will validate user input for maximum no of chars.
                   
iv.email--this will validate user input for an email id.
                    
v.pattern(expression)--this will validate user input against an
                                           expression
                      
eg:

                       [0-9]{10} --expression | pattern to accept 10 digit number
                [A-Za-z.\\s]{1,} --expression to accept a string with lower |upper |dot |spaces with 1 to any
                        


Form Group, Form Array and Form Control props | methods:
--------------------------------------------------
                    AbstractClass           --> base class
              [valid|invalid|..-->props]
                         |
   FormGroup      FormArray     FormControl --> derived classes
    class                  class               class 



1.valid-it will return true | false
        true-validation[s] is success
         
2.invalid-it will return true | false
         true-validation[s] is failed

3.touched-it will return true | false
         true-focus to control

4.untouched-it will return true  | false
         true-no focus to control

5.pristine-it will return true  | false
         true-control is not edited

6.dirty-it will return true | false
        true-control is edited

7.value-it will provide model props data
        <modelname | formgroupname>.value.<propname>

8.hasError('validationname')-it will return true|false
                             true-validation is failed 

  mobile--required validation
          pattern is 10 digit

  <span *ngIf="usermodel.controls['mobile'].invalid">
       error message-->common for required and pattern
  </span>

   (or)  

 <span  *ngIf="usermodel.controls['mobile'].hasError('required')">
       ...
 </span>

 <span  *ngIf="usermodel.controls['mobile'].hasError('pattern')">
       ...
 </span>


steps to work with mdf:
-----------------------
1.create|build a model with collection of props
  syntax:
  this.<modelname>=new FormGroup({
     <propname1>:new FormControl(initialvalue,[validation[s]]),
            ...
            },{updateOn:'change|blur|submit'});



this.userModel=new FormGroup(
     {
       firstname:new FormControl("",[Validators.required]),
       lastname:new FormControl("",[Validators.required]),
       emailid:new FormControl("xyz@gmail.com",[Validators.email])
     },{updateOn:'change'}
   );

2.bind model and props to template
   syntax:
       <form [formGroup]="modelname" ..>
          <input formControlName="propname">
              ..
       </form>


<form [formGroup]="userModel" (ngSubmit)="register()">
 firstname:<input formControlName="firstname">
        <span *ngIf="userModel.controls['firstname'].invalid">
            enter firstname
        </span>
3.place|import ReactiveFormsModule into AppModule
















Features of Reactive Forms:
  1. More flexible, but need a lot of practice
  2. Handles any complex scenarios.
  3. No data binding is done (Immutable data model preferred by most developers).
  4. More component code and less HTML Markup.
  5. Easier unit testing.
  6. Reactive transformations can be made possible such as
  7. Handling a event based on a denounce time.
  8. Handling events when the components are distinct until changed.
  9. Adding elements dynamically.


Kubernetes

Prerequisites We assume anyone who wants to understand Kubernetes should have an understating of how the Docker works, how the Docker images...