Thursday, October 31, 2019

My Angular Material Quick Review Points Reference

1- Just for refrence :  https://material.angular.io/guide/getting-started
            https://material.angular.io/components/categories

ng add @angular/material  // install angular material into the project , don't forget to accept all questions you are faced with

Usually , we create a separate Module name it Material Module and put all the components in an array then put this array into the imports and exports  of the Material Module
Then importing the Material Module into the app.module.ts file makes all these components available for use into our application normally.

@Material Module
import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material';

const MaterialComponents =[
  MatButtonModule
];

@NgModule({
  declarations: [],
  imports: [
    MaterialComponents

  ] ,
  exports: [
    MaterialComponents

  ]
})
export class MaterialModule { }

 @App Module

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MaterialModule } from './material/material.module';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule ,
    MaterialModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

2- to add a button
in app.module.ts
import { MatButtonModule } from '@angular/material';

imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule ,
    MatButtonModule
  ],

in app.component.html
<button mat-raised-button>Hellow World</button>

3- It is better to generate separate module for angular material components

ng generate module material

at the material.module.ts

import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material';

const MaterialComponents =[
  MatButtonModule
];

@NgModule({
  declarations: [],
  imports: [
    MaterialComponents

  ] ,
  exports: [
    MaterialComponents

  ]
})
export class MaterialModule { }

at app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MaterialModule } from './material/material.module';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule ,
    MaterialModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

3- to display text with different sizes

<div class="mat-display-4"> This is the text <div>
<div class="mat-display-3"> This is the text <div>
<div class="mat-display-2"> This is the text <div>
<div class="mat-display-1"> This is the text <div>

and also

<div class="mat-headline"> This is the text of h1 <div>
<div class="mat-title"> This is the text of h2<div>
<div class="mat-subheading-2"> This is the text of h3<div>
<div class="mat-subheading-1"> This is the text of h4<div>

and also

<div class="mat-body-1"> This is the text body<div>
<div class="mat-body-2"> This is the bold text body<div>
<div class="mat-caption"> This is the caption text<div>

or you can use this way it will give the same result:-

<div class="mat-typography">
 <h1>This is h1</h1>
 <h2>This is h2</h2>
 <h3>This is h3</h3>
 <h4>This is h4</h4>
</div>


4- Material Design Buttons :-

to use the material buttons you need to import MatButtonModule from @angular/material/button

examples
<div>
 <button mat-button>click me </button> 
 <button mat-raised-button>click me </button>
 <button mat-flat-button>click me </button>
 <button mat-stroked-button>click me </button>
 <button mat-icon-button>click me </button>
 <button mat-fab>click me </button>
 <button mat-mini-fab>click me </button>
<button color="primary" mat-button>click me </button>
<button color="accent" mat-button>click me </button>
<button color="warn" mat-button>click me </button>

<button color="primary" mat-raised-button>click me </button>  ///// this is the best button color and effect
<button color="accent" mat-raised-button>click me </button>
<button color="warn" mat-raised-button>click me </button>


</div>

5- to use mat-button-toggle

import MatButtonToggleModule from '@angular/material'; and put it in the imports array
in the html
<mat-button-toggle #toggleBtn>Toggle</mat-button-toggle>
{{ toggleBtn.checked }}

or

The value property evaluates to the overall group value and in this case it acts like a radio button

<mat-button-toggle-group #toggleGroup="matButtonToggleGroup">
  <mat-button-toggle value="angular">Angular</mat-button-toggle>
  <mat-button-toggle value="react">React</mat-button-toggle>
</mat-button-toggle-group>
 {{toggleGroup.value}}

to act like a check box add the multiple attribute

<mat-button-toggle-group #toggleGroup="matButtonToggleGroup" multiple>
  <mat-button-toggle value="angular">Angular</mat-button-toggle>
  <mat-button-toggle value="react">React</mat-button-toggle>
</mat-button-toggle-group>
 {{toggleGroup.value}}


6- Icons

import MatIconModule from '@angular/material' and add it to the imports array

go to https://material.io/tools/icons

click the desired icon and get it's name and put it inside the tag

<mat-icon color="primary">grade</mat-icon>


7- Badges : are icon notifications that are displayed over certain text

import {MatBadgeModule} from '@angular/material/badge'; and add it to the imports array

<span matBadge="5">Notification</span>

or to change position of badge using

<span matBadge="5" matBadgePosition="below before">Notification</span>

to control size of badge small , medium , large

<span matBadge="5" matBadgeSize="small">Notification</span>

to control color of badge primary , accent , warn

<span matBadge="5" matBadgeColor="primary">Notification</span>

to control whether badge overlaps with text under it

<span matBadge="5" matBadgeOverlap="false">Notification</span>

or dynamically

<span [matBadge]="propertyName" [matBadgeHidden]="propertyName === 0">Notification</span>

8- Mat Progress Spinner

import {MatProgressSpinnerModule} from '@angular/material';

<mat-progress-spinner value="40" ></mat-progress-spinner>

or using this component to show a loading status ,  color is : primary / accent /warn
<mat-spinner *ngIf="showSpinner" color="primary"></mat-spinner>


9- Navbar Component

import {MatToolbarModule} from '@angular/material'; and add to the imports array

color : primary / Accent / warn

<mat-toolbar color="primary" class="navbar">
 <div>  Code Evolution </div>
 <div>
   <span> Home </span>
   <span> About </span>
   <span> Services</span>
 </div>
</mat-toolbar>

at Css
.navbar {
justify-content: space-between;
}
span {
padding-right: 1rem;
}

11- SideNav Component

import { MatSidenavModule } from '@angular/material';

mode = over/push/side

<mat-sidenav-container>
 <mat-sidenav #sidenav mode="side" [(opened)]="openedFlag"> Sidenav </<mat-sidenav>
 <mat-sidenav-content> Main
<button (click)="openedFlag=!openedFlag"> Toggle openned </button>
<button (click)="sidenav.open()"> Open</button>
<button (click)="sidenav.close()"> Close</button>
<button (click)="sidenav.toggle()"> Toggle </button>
</mat-sidenav-content
 
</mat-sidenav-container>

at Css file
mat-sidenav-container
{
height: 100%;
}

mat-sidenav , mat-sidenav-content
{
padding: 16px;
}

mat-sidenav
{
background-color: lightcoral;
width: 200px;
}


12- Menu

import {MatMenuModule} from '@angular/material';

<mat-menu #appMenu="matMenu" xPosition="after" yPosition="above">
  <button mat-menu-item [matMenuTriggerFor]="subMenu">Front End</button>
  <button mat-menu-item>Back End</button>
</mat-menu>
<button mat-flat-button [matMenuTriggerFor]="appMenu">Menu</button>

<mat-menu #subMenu="matMenu">
 <button mat-menu-item>Angular</button>
 <button mat-menu-item>React</button>
</mat-menu>

to lazy load menu items in menus untill the menu is opened use the below

<mat-menu #lazyMenu="matManu">
 <ng-template matMenuContent let-name="name" let-hobby="hobby">
  <button mat-menu-item>Settings</button>
  <button mat-menu-item>Logout {{name}} And your Hoppy is {{hobby}}</button>
 </ng-template>
</mat-menu>

<button mat-raised-button
[matMenuTriggerData]="{ name : 'Mahmoud' , hoppy: 'football'}"
[matMenuTriggerFor]="lazyMenu"> Mahmoud Button </button>


13- List

import {MatListModule} from '@angular/material';
import {MatDividerModule} from '@angular/material';

<mat-list dense>
    <mat-list-item>Item 1</mat-list-item>
    <mat-list-item>Item 2</mat-list-item>
</mat-list>

to create a navigational list

<mat-nav-list>
  <a mat-list-item href="#">Home</a>
  <a mat-list-item href="#">About</a>
</mat-nav-list>

we can use the navigational list with the side nav component to create the items of the side nav

or with icons like , This is very Suitable to display data List items

<mat-list>
    <mat-list-item>
      <mat-icon matListIcon>home</mat-icon>
      <h3 matLine> Heading </h3>
      <p matLine> Line </p>
    </mat-list-item>
<mat-divider></mat-divider>
    <mat-list-item>
      <mat-icon matListIcon>folder</mat-icon>
      <h3 matLine> Heading 2</h3>
      <p matLine> Line 2</p>
    </mat-list-item>
</mat-list>


14- Grid List

import {MatGridListModule} from '@angular/material';

<mat-grid-list cols="2" gutterSize="10px" rowHeight="100px">    // or rowHeight="2:1" which means that height is half the width
   <mat-grid-tile rowspan="2">Tile 1</mat-grid-tile>
   <mat-grid-tile>Tile 2</mat-grid-tile>
   <mat-grid-tile colspan="2">Tile 3</mat-grid-tile>
   <mat-grid-tile>Tile 4</mat-grid-tile>
</mat-grid-list>


15- Expansion Panel / Accordions

import {MatExpansionModule} from '@angular/material';

<mat-accordion multi="true">
<mat-expansion-panel>
 <mat-expansion-panel-header>
  <mat-panel-title>
   Angular Fundamental
  </mat-panel-title>
  <mat-panel-description>
  Total Duration : 3 hours
  </mat-panel-description>
 </mat-expansion-panel-header>
  <p>This is the panel content , Add course details</p>
<mat-action-row>
  <button mat-button> Enroll </button>
</mat-action-row>
</mat-expansion-panel>

<mat-expansion-panel>
 <mat-expansion-panel-header>
  <mat-panel-title>
   Angular material
  </mat-panel-title>
  <mat-panel-description>
  Total Duration : 2 hours
  </mat-panel-description>
 </mat-expansion-panel-header>
  <p>This is the panel content , Add course details</p>
<mat-action-row>
  <button mat-button> Enroll </button>
</mat-action-row>
</mat-expansion-panel>
</mat-accordion>


16- Cards

import {MatCardModule} from '@angular/material'

<mat-card>b
<mat-card-title>
 card Title
</mat-card-title>
<mat-card-content>
This is the card content
</mat-card-content>
<mat-card-actions align="end">
 <button mat-flat-button>Login<button>
</mat-card-actions>
</mat-card>



17- Tabs

import { MatTabsModule } from '@angular/material';

<mat-tab-group #tabRef (selectedTabChange)="logChanges(tabRef.selectedIndex)"> // logChanges() is a function
  <mat-tab label="Angular">Angular Content</mat-tab>
  <mat-tab label="React">React Content</mat-tab>
  <mat-tab label="Vue">Vue Content</mat-tab>
</mat-tab-group>

{{ tabRef.selectedIndex }}


18- Stepper (Train)

import { MatStepperModule } from '@angular/material';


<mat-horizontal-stepper linear>
    <mat-step label="Shipping Address" completed="true">
     <p>Shipping Address Details</p>
    </mat-step>
    <mat-step label="Billing Address" completed="false" optional>  // now we can navigate between one and two because one is completed
     <p>Billing Address Details</p>
     <button mat-button matStepperPrevious>Back</button>
     <button mat-button matStepperNext>Next</button>
    </mat-step>
    <mat-step label="Place Order" completed="false">
     <p>Place Order</p>
    </mat-step>
</mat-horizontal-stepper>

You can also use <mat-vertical-stepper>


19- Input (Forms)

import {MatFormFieldModule , MatInputModule} from '@angular/material';

<mat-form-field floatLabel="never" appearance="legacy" color="primary"> // floatLabel : never or always or auto // appearance=legacy or standard or fill or outline  // color="primary" or accent or warn
  <mat-label>Name</mat-label>
  <input matInput required>
  <mat-hint align="end">Min 5 characters</mat-hint>
</mat-form-field>


20- Select
import {MatSelectModule} from '@angular/material';

<mat-form-field>
 <mat-label>Topic</mat-label>
 <mat-select [(value)]="selectedValue" multiple>
   <mat-option >None</mat-option>
   <mat-option value="angular">Angular</mat-option>
   <mat-option value="react">React</mat-option>
   <mat-option value="vue">Vue</mat-option>
 </mat-select>
</mat-form-field>




21- Auto Complete


import {MatAutocompleteModule} from '@angular/material';
import {ReactiveFormsModule} from '@angular/forms';

<form>
 <mat-form-field>
  <input type="text" matInput [matAutocomplete]="auto" [formControl]="myControl"/>
   <mat-autocomplete #auto="matAutocomplete">
    <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
     {{ option }}
    </mat-option>
   </mat-autocomplete>
 </mat-form-field>
</form>


import {Observable} from 'rxjs';
import {map , startWith} from 'rxjs/operators';


options: string[] = ['Angular' , 'React' , 'Vue'];
myControl = new FormControl();
filteredOptions : Observable<string[]>;

ngOnInit()
{
 this.filteredOptions = this.myControl.valueChanges.pipe(
 startWith(''),
 map(value => this.filter(value))
 );

}

private filter(value : string) : string[]
{
const filterValue = value.toLowerCase();
return this.options.filter( option=> option.toLowerCase().includes(filterValue));

}




22- Check Box and Radio Button


import {MatCheckboxModule} from '@angular/material';

<mat-checkbox labelPosition="before" color="primary">
Subscribe
</mat-checkbox>


import {MatRadioModule} from '@angular/material';
import {FormsModule} from '@angulat/forms'

<mat-radio-group [(ngModel)] = "propertyName">  // This to access the value of the radio group
 <mat-radio-button value="angular" color="primary">Angular</mat-radio-button>
 <mat-radio-button value="react" color="primary">React</mat-radio-button>
 <mat-radio-button value="vue" color="primary">Vue</mat-radio-button>
</mat-radio-group>



23- Date Picker


import {MatDatepickerModule , MatNativeDateModule} from '@angular/material';


<mat-form-field>
 <input matInput [matDatepicker]="myDatePicker" [matDatepickerFilter]="dateFilter" [min]="minDate" [max]="maxDate">
 <mat-datepicker-toggle [for]="myDatePicker" matSuffix></mat-datepicker-toggle>
 <mat-datepicker #myDatePicker > </mat-datepicker>
</mat-form-field>


minDate = new Date();
maxDate = new Date(2019,3,10);  // 10-APR-2019

// prevent saturday and sunday from being selected

dateFilter = date => {
const day = date.getDay();
return day =/= 0 && day =/= 6;
}



24- Tooltips



import { MatTooltipModule } from '@angular/material';


<button mat-raised-button matTooltip="welcome" matTooltipPosition="after" matTooltipShowDelay="2000" matToolTipHideDelay="2000">hello</button>



25- Snake bar  (Confirmation Messages)

import { MatSnackBarModule } from '@angular/material';

<button mat-button (click)="openSnackBar('Item deleted','Undo')"> Delete </button>


@ class
-------
import {MatSnackBar} from '@angular/material';

constructor(private snackBar : MatSnackBar)
{
}

openSnackBar(message , action)
{
let snakeBarRef = this.snackBar.open(message , action , {duration: 2000});
snakeBarRef.afterDismissed().subscribe(
()=> {
console.log('Snack bar dismissed');
}

);

snakeBarRef.onAction().subscribe(
()=> {
console.log('the snack bar action was triggered');
}
);



}




26- Dialog

import {MatDialogModule} from '@angular/material';


<button mat-raised-button (click)="openDialog()">Open Dialog</button>

AT app.module.ts

import the dialog component class and put it in the entryComponents Array

@NgModule({
declarations: [AppComponent , DialogExampleComponent ]
entryComponents: [DialogExampleComponent],
imports : [...

AT component Class :-

import {MatDialog} from '@angular/material';

constructor(public dialog:MatDialog){}

openDialog()
{
let dialogRef = this.dialog.open(DialogExampleComponent , { data:{name:'MG'} } );
dialogRef.afterClosed().subscribe(
result => {
console.log(`Dialog result: $result`);
}
);

}


AT DialogExampleComponent html

<h2 mat-dialog-title> Session Timeout</h2>
<mat-dialog-content> hi {{ data.name }} you will be logged out due to inactivity</mat-dialog-content>
<mat-dialog-actions>
 <button mat-button mat-dialog-close mat-dialog-close="true">Keep me logged in </button>
 <button mat-button mat-dialog-close mat-dialog-close="false"> Logout </button>
</mat-dialog-actions>


AT DialogExampleComponent class

import {Inject} from '@angular/core';
import {MAT_DIALOG_DATA} from '@angular/material';

constructor(@Inject(MAT_DIALOG_DATA) public data : any){}





27- Data Table (Check The online docs https://material.angular.io/components/table/examples )

import {MatTableModule} from '@angular/material';

AT HTML

<mat-table [dataSource]="dataSource" class="mat-elevation-z8">
  <!-- Position Column -->
  <ng-container matColumnDef="position">
    <mat-header-cell *matHeaderCellDef> No. </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
  </ng-container>

  <!-- Name Column -->
  <ng-container matColumnDef="name">
    <mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
  </ng-container>

  <!-- Weight Column -->
  <ng-container matColumnDef="weight">
    <mat-header-cell *matHeaderCellDef> Weight </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell>
  </ng-container>

  <!-- Symbol Column -->
  <ng-container matColumnDef="symbol">
    <mat-header-cell *matHeaderCellDef> Symbol </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell>
  </ng-container>

  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
  <mat-row (click)=editRow(row) *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>


AT Component Class


export interface PeriodicElement {
  name: string;
  position: number;
  weight: number;
  symbol: string;
}

const ELEMENT_DATA: PeriodicElement[] = [
  {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
  {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
  {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
  {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
  {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
  {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
  {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
  {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
  {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
  {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
];

export class AppComponents {
  displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
  dataSource = ELEMENT_DATA;


editRow(row)
{
console.log(row); // display the current selected record

}
}







28- Exploring Data Tables


check https://www.youtube.com/watch?v=mogliLm_mII&list=PLC3y8-rFHvwilEuCqFGTL5Gt5U6deIrsU&index=28


29- Data Table Filtering

check https://www.youtube.com/watch?v=ZhcYPXLGr_E&list=PLC3y8-rFHvwilEuCqFGTL5Gt5U6deIrsU&index=29





AT Component Class


import {MatTableDataSource} from '@angular/material';

export interface PeriodicElement {
  name: string;
  position: number;
  weight: number;
  symbol: string;
}

const ELEMENT_DATA: PeriodicElement[] = [
  {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
  {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
  {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
  {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
  {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
  {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
  {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
  {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
  {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
  {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
];

export class AppComponents {
  displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
  dataSource = new MatTableDataSource(ELEMENT_DATA);


editRow(row)
{
console.log(row); // display the current selected record

}
}

applyFilter(filterValue : string)
{

this.dataSource.filter = filterValue.trim().toLowerCase();
}



AT HTML

<mat-form-field>
  <input matInput placeholder="filter" (keyup)="applyFilter($event.target.value)" >

</mat-form-field>

<mat-table [dataSource]="dataSource" class="mat-elevation-z8">
  <!-- Position Column -->
  <ng-container matColumnDef="position">
    <mat-header-cell *matHeaderCellDef> No. </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
  </ng-container>

  <!-- Name Column -->
  <ng-container matColumnDef="name">
    <mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
  </ng-container>

  <!-- Weight Column -->
  <ng-container matColumnDef="weight">
    <mat-header-cell *matHeaderCellDef> Weight </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell>
  </ng-container>

  <!-- Symbol Column -->
  <ng-container matColumnDef="symbol">
    <mat-header-cell *matHeaderCellDef> Symbol </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell>
  </ng-container>

  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
  <mat-row (click)=editRow(row) *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>




30-   Data Table Sorting

import {MatSortModule} from '@angular/material';


AT HTML

<mat-form-field>
  <input matInput placeholder="filter" (keyup)="applyFilter($event.target.value)" >

</mat-form-field>

<mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">
  <!-- Position Column -->
  <ng-container matColumnDef="position">
    <mat-header-cell mat-sort-header *matHeaderCellDef> No. </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
  </ng-container>

  <!-- Name Column -->
  <ng-container matColumnDef="name">
    <mat-header-cell mat-sort-header *matHeaderCellDef> Name </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
  </ng-container>

  <!-- Weight Column -->
  <ng-container matColumnDef="weight">
    <mat-header-cell mat-sort-header *matHeaderCellDef> Weight </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell>
  </ng-container>

  <!-- Symbol Column -->
  <ng-container matColumnDef="symbol">
    <mat-header-cell mat-sort-header *matHeaderCellDef> Symbol </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell>
  </ng-container>

  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
  <mat-row (click)=editRow(row) *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>



AT Component Class


import {MatTableDataSource , MatSort} from '@angular/material';
import { Component , ViewChild , OnInit } from '@angular/core';

export interface PeriodicElement {
  name: string;
  position: number;
  weight: number;
  symbol: string;
}

const ELEMENT_DATA: PeriodicElement[] = [
  {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
  {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
  {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
  {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
  {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
  {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
  {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
  {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
  {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
  {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
];

export class AppComponents implements OnInit {
  displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
  dataSource = new MatTableDataSource(ELEMENT_DATA);


@ViewChild(MatSort) sort : MatSort;

ngOnInit()
{
this.dataSource.sort = this.sort;

}

editRow(row)
{
console.log(row); // display the current selected record

}
}

applyFilter(filterValue : string)
{

this.dataSource.filter = filterValue.trim().toLowerCase();
}




31- Data Table Pagination


import {MatPaginatorModule} from '@angular/material';


AT HTML

<mat-form-field>
  <input matInput placeholder="filter" (keyup)="applyFilter($event.target.value)" >

</mat-form-field>

<div class="mat-elevation-z8">
<mat-table [dataSource]="dataSource" matSort >
  <!-- Position Column -->
  <ng-container matColumnDef="position">
    <mat-header-cell mat-sort-header *matHeaderCellDef> No. </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
  </ng-container>

  <!-- Name Column -->
  <ng-container matColumnDef="name">
    <mat-header-cell mat-sort-header *matHeaderCellDef> Name </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
  </ng-container>

  <!-- Weight Column -->
  <ng-container matColumnDef="weight">
    <mat-header-cell mat-sort-header *matHeaderCellDef> Weight </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell>
  </ng-container>

  <!-- Symbol Column -->
  <ng-container matColumnDef="symbol">
    <mat-header-cell mat-sort-header *matHeaderCellDef> Symbol </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell>
  </ng-container>

  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
  <mat-row (click)=editRow(row) *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>

<mat-paginator [pageSizeOptions]="[5,10,20]" showFirstLastButtons></mat-paginator >

</div>





AT Component Class


import {MatTableDataSource , MatSort , MatPaginator} from '@angular/material';
import { Component , ViewChild , OnInit } from '@angular/core';

export interface PeriodicElement {
  name: string;
  position: number;
  weight: number;
  symbol: string;
}

const ELEMENT_DATA: PeriodicElement[] = [
  {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
  {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
  {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
  {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
  {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
  {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
  {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
  {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
  {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
  {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
];

export class AppComponents implements OnInit {
  displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
  dataSource = new MatTableDataSource(ELEMENT_DATA);


@ViewChild(MatSort) sort : MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;

ngOnInit()
{
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
}

editRow(row)
{
console.log(row); // display the current selected record

}
}

applyFilter(filterValue : string)
{

this.dataSource.filter = filterValue.trim().toLowerCase();
}


32- Virtual Scrolling

import {ScrollingModule} from '@angular/cdk/scrolling';

AT HTML

<cdk-virtual-scroll-viewport itemSize="100">
 <div *cdkVirtualFor="let number of numbers">
  {{ number }}
 </div>
</cdk-virtual-scroll-viewport>




33- To Create a responsive navigation toolbar and menu in angular +6

ng generate @angular/material:material-nav --name=main-nav













Sunday, October 20, 2019

My Angular JS Short Summary Notes




0- Basic Commands of angular is as follows
npm install -g npm@latest // to update npm version
node -v
npm -v
npm install -g @angular/cli@latest   // install latest angular
ng new my-app-name // create new app
ng serve --open // run the app in the browser
ng generate component component_name
ng generate module module-name
        ng generate component module-name/component-name // to generate the component on a specific module rather than app.module.ts
ng generate service service-name // this cmd will not add the service to the providers array in App module.ts you need to register it manually
ng build // builds and generates the dist directory that contains the deployments files
ng g class class-name // generate only a class that can be used as a model object


1- To evaluate a one way data binding expression use the following  {{ value * 3 }} where value is a member variable inside the class ts file

2- To pass a value from parent component to child component , put in the child component the directive @Input("PropertyName")
and the calling component will be like <CHILD-TAG PropertyName="Mahmoud"></CHILD-TAG>

3- To Pass a member variable from parent to child and this member variable is not just a string value passing , use the following syntax
<CHILD-TAG [PropertyName]="Mahmoud"></CHILD-TAG> where Mahmoud in this case is not just a string passed , it's the name of the property
or object defined in the parent component class ts , the child component will remain able to accept the new passed object with the same
@Input("PropertyName") myObject : User;  way

4- to loop and display multiple items :
<p *ngFor="let item of user.phones">item</p> where user.phones is an object that contains array of string phones

5- to check the condition to display a div or not use ngIF
<div *ngIf="user.phones.length > 0">
</div>

6- To create an initialization for member variables in a class just use the ngOnInit() lifecycle hook to do your code as it is called
After the constructor of the class invoked.

7- style classes applied to the component css file applies only for this component and not globally because angular adds an extra property
for HTML tags by default for every component and style the classes using this property in the back scene ... this property value changes from
one component to another in the same project.

8- to execute a method in the ts class file from a button on the html use the following syntax , we surrounded the click with () to differntiate it from html default click event
<button (click)="doMyCode()"> Press Me </button>

9- To create a two way data binding between the page html and the class ts file use the ngModel as below to evaluate the property name text inside the "" which is defined inside the ts file class
<input type="text" [(ngModel)]="propertyName"> </input> , and to use the ngModel we need to import the FormsModule in the app.module.ts file Imports.

10- We can create multiple modules in angular , we can use them inside each others provided that we will add them to the imports part of the parent module and components that to be used in other
modules should be exported first in their containing module.

11- Service classes has the annotation @Injectable() which means that this is a service can be injected into the constructor of other services or component classes.

12- Dependency Injection is a way that services could be injected into other services or components , angular will instantiate the service
and provide it to the consuming class as below, the private will create an instance variable for the class and inject it with the injected class

constructor(private svc: TestService)
{
this.svc.doSomething();
}

13- To use HttpClient service we need to put HttpClientModule in the imports section of the app.module.ts
import { HttpClientModule } from '@angular/common/http';
@NgModule({
  declarations: [
    AppComponent,
    HelloWorldComponent
  ],
  imports: [
    BrowserModule ,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
and in the component class :-
import { HttpClient } from '@angular/common/http';

constructor(private http : HttpClient)
  {
  }
 ngOnInit()
  {
    let obs = this.http.get('http://172.16.3.35:8001/myweb/mms/routeschedule' ,
    {
       headers: new HttpHeaders({
      'Authorization': 'Basic bWdhYnIg=',
      'Content-Type': 'application/json'})
     }
    );
    obs.subscribe( res=> {
      console.log(res);
      this.response = res.toString();
    } );
  }

14- We can use the following syntax when we are not sure of the existence of the name property on the response object
{{response?.name}}

15- to create a server that hosts a certain build directory on your machine rather than the developement server
ng build --prod
npm install http-server -g
http-server dist/build-proj/  // this opens the server and hosts the files in this directory which is the build files


16- Routing is done based on certain URL patterns , the views will be switched between components but all will be in the same page view (SPA).


17- creating application with routing enabled

ng new app-name --routing

18- Simple routing code

import {Route , RouterModule } from '@angular/router';
const routes : Route[] =
[
{path: '' , redirectTo: '/view1' , pathMatch: 'full'}, // redirect to default path
{path: 'view1' ,  component : View1},
{
 path: 'view2' , // For this parent component html we need to add another
<router-outlet></router-outlet>
 tag to display the second level child components
 component : View2 ,
 children :[
           {path: '' , redirectTo: 'view3' , pathMatch: 'full'},  // default child route is specified and note that there is no '/' needed
           {path: 'view3' ,  component : View3} ,   // child route that will be accessed with this URL /view2/view3
           {path: 'view4' ,  component : View4} ,    // child route that will be accessed with this URL /view2/view4
           {path: '**' , component: ErrorNotFoundComponent } // wild card for child level routes
  ]
},
{path: '**' , component: ErrorNotFoundComponent }    // anything else not mentioned above just display the Not Found Component
];

@NgModule(
{
imports: [RouterModule.forRoot(routes)],
exports : [RouterModule]
})
export class AppRoutingModule {}


19- On the main page html there will be a tag called
<router-outlet></router-outlet>
  that switches between routed components

20- You can specify the routing links with this way , but it will make a full page refresh
<a href="/view1">view 1</a>
<a href="/view2">view 2</a>

intsead you need to specify the links with this way so as not to make a full page refresh
<a routerLink="view1">view 1</a>
<a routerLink="view2">view 2</a>

or dynamically as
<a *ngFor="let route of routes" [routerLink]="route.url">{{route.name}}</a>


21-  to truncate a certain displayable value to certain lenght you can use angular pipes as below {{ user.desc | truncate : [30]}}
ng g pipe truncate //  this will create a pipe class and register it in app.module.ts
Inside the class u will find a transform method that takes the value as 1st param and arguments as a 2nd param
 or if you want to call the pipe programmatically from the component class you can do the following :
- add the pipe class to the providers array of app.module.ts
- Dependency inject the pipe class single instance into the component class by specifying it in the constructor of the component
- in ngOnInit() use the pipe class reference to call the transform method on the values you want.


22-
this.pages = new Array(this.numberOfPages); // creating array of certain length
*ngFor="let page of pages ; index as i"  // Syntax to create a loop and get the index

23- Emitting events happens from child components to parent ones..
on the child component use :
 @Output() pageNumberClicked = new EventEmitter<number>();  //where number is the type of data to be emitted.
then on the method that invokes the event  on the child side
this.pageNumberClicked.emit(pageNumber);

on the parent side we will listen to the child pageNumberClicked event
<app-paginator (pageNumberClicked)="handleEventOnParent($event)" [numberOfPages]="blogPosts.length"> </app-paginator>

24- ViewEncapsulation is a feature either set to Emulated which is the default value or NONE.
If Emulated , the css classes will be isolated from one compnent to another but NONE keeps the components shares the CSS classes

25- To bind a child component in the html to the parent component class , use local refrence and @ViewChild()

@ViewChild('compLocalRef') blogPostTileComponent : BlogPostTileComponent;
and the html as <app-blog-post-tile #compLocalRef ></app-blog-post-tile>

26- If you want to apply a style sheet class for a certain component based on an expression just do the following

<div [ngClass]="'fav' : post.isFavourite"> </div>

Where 'fav' is the name of the syle sheet class and post.isFavourite is an expression that returns true / false


27- generate a directive class to be put on certain elements , directives are used to change the dom element they are applied to
That's why they accept an elementRef object in their constructor to manipulate the dom of the element they are applied to.

ng g directive directive-name


28- <ng-content></ng-content> tells angular that you are interested in the HTML dom elements that you place inside the component openning and closing tags on the parent page.
ex: at the parent page
<component-tag>
<h1>Heading</h1>
</component-tag>

and at the child component just put the <ng-content></ng-content> to display the h1 tag and all dom elements inside the component's tag


29- How to Pass parameters to Angular Route

We can define parameter by adding forward slash followed colon and a placeholder (id , id1 , id2) as shown below in the routes array of the app.routing.module.ts

{ path: 'product/:id/:id1/:id2', component: ProductDetailComponent }

We, now need to provide both path and the route parameter routerLink directive.

This is done by adding the productID as the second element to the routerLink parameters array as shown below

<a [routerLink]="['/Product', ‘2’]">{{product.name}} </a>

OR

<a [routerLink]="['/Product', product.productID]">{{product.name}} </a>

Which, dynamically takes the value of id from the product object.

Finally, our component needs to extract the route parameter from the URL

This is done via the ActivatedRoute service from angular/router module to get the parameter value
The ActivatedRoute is a service, which keeps track of the currently activated route associated with the loaded Component.

import { ActivatedRoute } from '@angular/router';

Then inject it into the component using dependency injection

constructor(private _Activatedroute:ActivatedRoute)

The Angular adds the map all the route parameters in the ParamMap object, which can be accessed from the ActivatedRoute service

There are two ways in which you can use the ActivatedRoute to get the parameter value from the ParamMap object.

- Using Snapshot

this.id=this._Activatedroute.snapshot.paramMap.get("id");

- Using observable

this._Activatedroute.paramMap.subscribe(params => {
    this.id = params.get('id');
});

Use this option if you expect the value of the parameter to change over time.

Why use observable

We usually retrieve the value of the parameter in the ngOninit life cycle hook, when the component initialised.

When the user navigates to the component again, the Angular does not create the new component but reuses the existing instance. In such circumstances, the ngOnInit method of the component is not called again. Hence you need a way to get the value of the parameter.

By subscribing to the observable paramMap property, you will retrieve the latest value of the parameter and update the component accordingly.

check example at the following URL : https://www.tektutorialshub.com/angular/angular-passing-parameters-to-route/

Use the Router to navigate programatically and don't forget to unSubscribe the observable in the ngDestroy() hook

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router,ActivatedRoute } from '@angular/router';

import { ProductService } from './product.service';
import { Product } from './product';


@Component({
  templateUrl: './product-detail.component.html',
})

export class ProductDetailComponent
{

   product:Product;
   id;
 
   constructor(private _Activatedroute:ActivatedRoute,
               private _router:Router,
               private _productService:ProductService){
   }

 
   /* Using snapshot */
   // ngOnInit() {

   //    //This still works but is deprecated
   //    //this.id=this._Activatedroute.snapshot.params['id'];

   //    this.id=this._Activatedroute.snapshot.paramMap.get("id");

     
   //    let products=this._productService.getProducts();
   //    this.product=products.find(p => p.productID==this.id);
   // }
 

   /* Using Subscribe */
 
   sub;

   ngOnInit() {

      this.sub=this._Activatedroute.paramMap.subscribe(params => {
         console.log(params);
          this.id = params.get('id');
          let products=this._productService.getProducts();
          this.product=products.find(p => p.productID==this.id);  
      });

      // This params is deprecated

      //this.sub=this._Activatedroute.params.subscribe(params => {
      //    this.id = params['id'];
      //    let products=this._productService.getProducts();
      //    this.product=products.find(p => p.productID==this.id);  
      //
      //});
   }

   ngOnDestroy() {
     this.sub.unsubscribe();
   }
 
   onBack(): void {
      this._router.navigate(['product']);
   }
}


30- Angular JWT Token Authentication complete example


https://jasonwatmore.com/post/2019/06/22/angular-8-jwt-authentication-example-tutorial




31- Angular Forms

https://appdividend.com/2019/06/07/angular-8-forms-tutorial-angular-reactive-and-template-forms-example/

Reactive forms in Angular 8
Reactive forms or Model-driven forms are more robust, scalable, reusable, and testable. If forms are the key part of your application, or you’re already using reactive patterns for building your web application, use reactive forms.

In Reactive Forms, most of the work is done in the component class.

Template-driven forms in Angular 8
Template-driven forms are useful for adding the simple form to an app, such as the email list signup form. They’re easy to add to a web app, but they don’t scale as well as the reactive forms.

If you have the fundamental form requirements and logic that can be managed solely in the template, use template-driven forms.

In template-driven forms, most of the work is done in the template.

Example of Template-driven form in Angular 8
Okay, now let’s install the fresh Angular 8 application.

Then go to an app.module.ts file and add the following code.

// app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

In the above file, we have imported the FormsModule from the @angular/forms library.

Now, we can use the FormsModule inside our app.component.ts file.

// app.component.ts

import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
   constructor() { }
   ngOnInit() {
   }
   onClickSubmit(formData) {
      alert('Your Email is : ' + formData.email);
   }
}
In this file, we have defined on onClickSubmit function, which will trigger when the user clicks the submit button on the form. The function also accepts one argument called formData, which is the object of the entire form values.

Through that formData object, we can access all the form field values. In our case, I only need the user’s email id. In the general scenario, we want to pass that object to the POST request to the backend server to store the user’s data.

Now, only remaining thing is to write the HTML of the app component. So, write the following code inside the app.component.html file.

<form #login = "ngForm" (ngSubmit) = "onClickSubmit(login.value)" >
  <input type = "text" name = "email" placeholder = "email" ngModel>
  <br/>
  <input type = "password" name = "pwd" placeholder = "password" ngModel>
  <br/>
  <input type = "submit" value = "submit">
</form>

We have created the web form with input tags having email, password and the submit button. We have assigned a type, name, and placeholder attributes to it.

In the template driven forms, we need to create a model form controls by adding the ngModel directive and the name attribute. Thus, whenever we want Angular to access our data from forms, add ngModel to that tag as shown above. Now, if we have to read an email and password, we need to add a ngModel across it.

If you close look at the form, we have also added the ngForm to the #login. The ngForm directive needs to be added to a form template that we have created.

Atlast, We have also added the function onClickSubmit and assigned login.value to it.


Model-driven or Reactive Forms in Angular 8
In the model-driven form, we need to import a ReactiveFormsModule from @angular/forms and use the same in the imports array.

There is a change which goes in app.module.ts. See the app.module.ts file.

// app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
In the app.component.ts file, we need to import the few modules for the model-driven form. For example, import { FormGroup, FormBuilder } from ‘@angular/forms’.


See the following app.component.ts file.

// app.component.ts

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  angForm: FormGroup;
  constructor(private fb: FormBuilder) {
    this.createForm();
  }
  createForm() {
    this.angForm = this.fb.group({
      email: [''],
      password: ['']
    });
  }
  onClickSubmit(email, password) {
    alert('Your Email is : ' + email);
  }
   ngOnInit() {
   }
}


In the above code, we have used a FormBuilder to create a form and initialize the value of two fields which is empty.

We have also defined one function called onClickSubmit() which accepts the two parameter email and password.

So,  when the user pressed the submit button, we got the values here and then we send these values with the POST request to the backend server.

Finally, write the app.component.html file.

<form [formGroup]="angForm">
  <input type = "text"
        name = "email"
        placeholder = "email"
        formControlName="email"
        #email>
  <br/>
  <input type = "password"
        name = "pwd"
        placeholder = "password"
        formControlName="password"
        #password>
  <br/>
  <input type = "submit"
          value = "submit"
          (click) = "onClickSubmit(email.value, password.value)" >
</form>

One of the advantages of the Model-driven approach is that the Validations become very easy.