Thursday, November 2, 2023

Angular Forms Part 8 (Forms Array)

 Form Array class:


This is used to create an array of form controls (or) form groups (or) nested form array

The main importance of form array is dynamic controls creation.

This class comes with 2 unique methods of an array
 1.push(item)--it will add an item into form array
 2.removeItem(index)--it will remove an element from formarray

requirement:
     cart model
        |
   Cust name--Form Control
   address --Form Control
     prods --Form Array[collection of Form Groups, Each Form Group will maintain one prod info]

Design a form with the following fields

    Cust name: textbox
     address:
         text area[multiline textbox]
         add product button

  productid      prod name     price
  textbox         textbox          textbox       remove

    ...      ...       ...
 
         save button




Create a component

ng g c mdf3 --flat

 
.ts Changes

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

@Component({
  selector: 'app-mdf3',
  templateUrl: './mdf3.component.html',
  styleUrls: ['./mdf3.component.css'],
})
export class Mdf3Component {
  cartmodel: FormGroup;
  custinfo: string | undefined;
  prodsinfo: string | undefined;

  createFormGroup(): FormGroup {
    return new FormGroup({
      pid: new FormControl('', [Validators.required]),
      pname: new FormControl('', [Validators.required]),
      price: new FormControl('', [Validators.required]),
    });
  }
  constructor() {
    //build a model
    this.cartmodel = new FormGroup({
      custname: new FormControl('', [Validators.required]),
      address: new FormControl('', [Validators.required]),
      prods: new FormArray([this.createFormGroup()]),
    });
  }
  addproduct() {
    (<FormArray>this.cartmodel.get('prods')).push(this.createFormGroup());
    //get("prods") will return AbstractControl class,this should be typecasted to FormArray class to access push method
  }
  delete(i: number) {
    //para i will recieve index number
    (<FormArray>this.cartmodel.get('prods')).removeAt(i);
  }
  save() {
    this.custinfo =
      this.cartmodel.value.custname + ':' + this.cartmodel.value.address;
    this.prodsinfo = '';
    for (let p of this.cartmodel.value.prods) {
      this.prodsinfo =
        this.prodsinfo + p.pid + ':' + p.pname + ':' + p.price + '<br>';
    }
  }
}


.html Changes

<form [formGroup]="cartmodel">
    <div style="font-size:x-large;margin:15px">
   custname:<input formControlName="custname"> <br>
   address : <br>
   <textarea rows="5" cols="30" formControlName="address"></textarea>
   <br>
   <input type="button" value="addproduct" (click)="addproduct()">
   <br>
   <table border="1">
       <tr>
           <th>pid</th>
           <th>pname</th>
           <th>price</th>
           <th>option</th>
       </tr>
       <ng-container formArrayName="prods">
        <tr *ngFor="let p of cartmodel.get('prods')?.value;let i=index" [formGroupName]="i">
            <td>
                <input formControlName="pid">
            </td>
            <td>
               <input formControlName="pname">
           </td>
           <td>
               <input formControlName="price">
           </td>
           <td>
            <input type="button" value="remove" (click)="delete(i)">
        </td>
        </tr>
      </ng-container>
   </table>
   <br>
   <input type="button" value="save" (click)="save()">
   <br>
   {{custinfo}}
   <br>
   <span [innerHtml]="prodsinfo"></span>
   </div>
   </form>
   

note:
-----
Initially prods form array will have only one form group, so ngfor will create
 one table row with textboxes
addproduct button click will add one new formgroup into prods formarray,accordingly
 ngfor will create a new table row with textboxes

*remove button click will remove formgroup from prods formarray based on
 index,accordingly table row will be removed


Output





Angular Forms Part 7 DropDownList

.html Changes .

<form #studentForm="ngForm" (ngSubmit)="RegisterStudent(studentForm)">

        <div class="form-group">
          <label for="branch">Branch</label>
          <select id="branch" name="branch" ngModel class="form-control">
            <option value="1">CSE</option>
            <option value="2">ETC</option>
            <option value="3">Mechanical</option>
            <option value="4">Electrical</option>
          </select>
        </div>
        <div class="panel-footer">
          <button class="btn btn-primary" type="submit">Submit</button>
        </div>
    </form>


.ts Changes

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


OutPut














Dropdownlist item selected 
If we include the selected attribute on the dropdownlist, then we may expect that option or item to be selected by default. But in angular template driven forms, that will not work. Lets include the “selected” attribute on the ETC branch option to verify this



 <select id="branch" name="branch" class="form-control">
            <option value="1">CSE</option>
            <option value="2" selected>ETC</option>
            <option value="3">Mechanical</option>
            <option value="4">Electrical</option>
          </select>



ETC department is not selected by default when the page load.

However, if you remove the “ngModel” directive from the select list as shown below, then you will see that the ETC branch is selected when the form is load.













Output















we use the “ngModel” directive in angular for two-way data binding. So when we put the ngModel directive back into the control then the “selected” attribute will not work on the drop down list or select list. If we remove the ngModel directive from the control then selected attribute work but two way data binding will not work.

To Make it work


.html 

<form #studentForm="ngForm" (ngSubmit)="RegisterStudent(studentForm)">
        <div class="form-group">
          <label for="branch">Branch</label>
          <select id="branch" name="branch" [(ngModel)]="BranchId" class="form-control">
            <option value="1">CSE</option>
            <option value="2">ETC</option>
            <option value="3">Mechanical</option>
            <option value="4">Electrical</option>
          </select>
        </div>
        <div class="panel-footer">
          <button class="btn btn-primary" type="submit">Submit</button>
        </div>
    </form>


.ts

export class FormsvalidationComponent {
  BranchId = "2";
  RegisterStudent(studentForm: NgForm): void {  
    console.log(studentForm.value);
  }


Output



 











Dynamically Binding Drop Down

.html Changes


<form #studentForm="ngForm" (ngSubmit)="RegisterStudent(studentForm)">
        <div class="form-group">
          <label for="branch">Branch</label>
          <select id="branch" name="branch" class="form-control" ngModel>
            <option *ngFor="let branch of Branches" [value]="branch.id">
              {{branch.name}}
            </option>
          </select>
        </div>
        <div class="panel-footer">
          <button class="btn btn-primary" type="submit">Submit</button>
        </div>
    </form>


.ts Changes

@Component({
  selector: 'app-formsvalidation',
  templateUrl: './formsvalidation.component.html',
  styleUrls: ['./formsvalidation.component.css']
})
export class FormsvalidationComponent {
 
  Branches: any[] = [
    { id: 1, name: 'CSE' },
    { id: 2, name: 'ETC' },
    { id: 3, name: 'Mechanical' },
    { id: 4, name: 'Electrical' }
  ];

  RegisterStudent(studentForm: NgForm): void {  
    console.log(studentForm.value);
  }
}


Output




Angular Forms Part 6 CheckBox



 .html Changes

<form #studentForm="ngForm" (ngSubmit)="RegisterStudent(studentForm)">
        <div class="form-group">
          <div class="form-control">
            <label class="checkbox-inline">
              <input type="checkbox" name="isAccept" ngModel>Accept Terms & Conditions
            </label>
          </div>
        </div>
        <div class="panel-footer">
          <button class="btn btn-primary" type="submit">Submit</button>
        </div>
    </form>


In the above code, we set the name attribute of the input element checkbox to isAccept. We have not set the value property here. This is because its value can be true of false. If the checkbox is checked or selected then the value is true else the value is false.


.ts Changes

export class FormsvalidationComponent {
  RegisterStudent(studentForm: NgForm): void {  
    console.log(studentForm.value);
  }
}


Output











Default Check Box Checked

<input type=”checkbox” name=”isAccept” ngModel checked>Accept Terms & Conditions

With the above changes in place, now browse the application and you will see the the checkbox is not checked by default when the page load.

However, if we remove the “ngModel” directive from the checkbox as shown below, then you will see that the checkbox is checked when the form is load.


 <input type=”checkbox” name=”isAccept” checked>Accept Terms & Conditions


How to make it work

.ts Changes

export class FormsvalidationComponent {
  isAccept = true;
  RegisterStudent(studentForm: NgForm): void {  
    console.log(studentForm.value);
  }
}

.html

<div class="form-group">
          <div class="form-control">
            <label class="checkbox-inline">
              <input type="checkbox" name="isAccept" [(ngModel)]="isAccept">Accept Terms & Conditions
            </label>
          </div>
</div>


Output














Angular Forms Part 5- Radio Button

 .Html Changes


<div class="container">
    <div class="row">
        <div class="form-bg">
            <form #studentForm="ngForm" (ngSubmit)="RegisterStudent(studentForm)">
              <div class="form-group">
                <label>Gender</label>
                <div class="form-control">
                  <label class="radio-inline">
                    <input type="radio" name="gender" value="male" ngModel>
                    Male
                  </label>
                  <label class="radio-inline">
                    <input type="radio" name="gender" value="female" ngModel>
                    Female
                  </label>
                </div>
              </div>
                <div class="panel-footer">
                  <button class="btn btn-primary" type="submit">Submit</button>
                </div>
              </div>
            </form>
        </div>
    </div>
  </div>

Here, in the above html code, we can see the name attribute is having a common value
as gender. The most important point that you need to keep in mind is that both the radio buttons should have the same value for the “name” attribute. Otherwise the radio button selection won’t be mutually exclusive


Again if you notice we have set the value attribute of each radio button to male and female and this is the value which is going to be posted to the server when the form is submitted.

.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);
  }
}


Output






Radio Button Default Checked.










Note:
With the above changes now browse the application and you will see the Male radio button is not checked.

 if you remove the “ngModel” directive from the radio button , then it is checked by default.


<input type="radio" name="gender" value="male" checked>

we generally use the “ngModel” directive for two-way data binding. So when we put the ngModel directive back into the control then the “checked” attribute will not work as expected.

We can make it work as below

.ts changes

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

In html we need to include gender property.


<div class="form-control">
<label class="radio-inline">
<input type="radio" name="gender" value="male" [(ngModel)]="gender">
Male
</label>
<label class="radio-inline">
<input type="radio" name="gender" value="female" [(ngModel)]="gender">
Female
</label>
</div>
















Kubernetes

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