Author: saqibkhan

  • Server Side Rendering

    Server side Rendering (SSR) is a modern technique to convert a Single Page Application (SPA) running in the browser into a server based application. Usually, in SPA, the server returns a simple index.html file with the reference to the JavaScript based SPA app. The SPA app take over from there, configure the entire application, process the request and then send the final response.

    But in SSR supported application, the server as well do all the necessary configuration and then send the final response to the browser. The browser renders the response and start the SPA app. SPA app takeover from there and further request are diverted to SPA app. The flow of SPA and SSR is as shown in below diagram.

    SSR

    Converting a SPA application to SSR provides certain advantages and they are as follows −

    • Speed: First request is relatively fast. One of the main drawback of SPA is slow initial rendering. Once the application is rendered, SPA app is quite fast. SSR fixes the initial rendering issue.
    • SEO Friendly: Enables the site to be SEO friendly. Another main disadvantage of SPA is not able to crawled by web crawler for the purpose of SEO. SSR fixes the issue.

    Angular Universal

    To enable SSR in Angular, Angular should be able to rendered in the server. To make it happen, Angular provides a special technology called Angular Universal. It is quite new technology and it is continuously evolving. Angular Universal knows how to render Angular application in the server. We can upgrade our application to Angular Universal to support SSR.

  • Web Workers

    Web workers enables JavaScript application to run the CPU-intensive in the background so that the application main thread concentrate on the smooth operation of UI. Angular provides support for including Web workers in the application. Let us write a simple Angular application and try to use web workers.

    Create a new Angular application using below command −

    cd /go/to/workspace
    ng newweb-worker-sample
    

    Run the application using below command −

    cd web-worker-sample
    npm run start
    

    Add new web worker using below command −

    ng generate web-worker app
    

    The output of the above command is as follows −

    CREATE tsconfig.worker.json(212 bytes)CREATE src/app/app.worker.ts(157 bytes)UPDATE tsconfig.app.json(296 bytes)UPDATE angular.json(3776 bytes)UPDATE src/app/app.component.ts(605 bytes)

    Here,

    • app refers the location of the web worker to be created.
    • Angular CLI will generate two new files, tsconfig.worker.json and src/app/app.worker.ts and update three files, tsconfig.app.json, angular.json and src/app/app.component.ts file.

    Let us check the changes −

    // tsconfig.worker.json{"extends":"./tsconfig.json","compilerOptions":{"outDir":"./out-tsc/worker","lib":["es2018","webworker"],"types":[]},"include":["src/**/*.worker.ts"]}

    Here,

    tsconfig.worker.json extends tsconfig.json and includes options to compile web workers.

    // tsconfig.app.json [only a snippet]"exclude":["src/test.ts","src/**/*.spec.ts","src/**/*.worker.ts"]

    Here,

    Basically, it excludes all the worker from compiling as it has separate configuration.

    // angular.json (only a snippet) "webWorkerTsConfig": "tsconfig.worker.json"

    Here,

    angular.json includes the web worker configuration file, tsconfig.worker.json.

    // src/app/app.worker.tsaddEventListener('message',({ data })=>{const response =worker response to ${data};postMessage(response);});

    Here,

    A web worker is created. Web worker is basically a function, which will be called when a message event is fired. The web worker will receive the data send by the caller, process it and then send the response back to the caller.

    // src/app/app.component.ts [only a snippet]if(typeof Worker !=='undefined'){// Create a newconst worker =newWorker('./app.worker',{ type:'module'});
       worker.onmessage=({ data })=>{console.log(page got message: ${data});};
       worker.postMessage('hello');}else{// Web Workers are not supported in this environment.// You should add a fallback so that your program still executes correctly.}

    Here,

    • AppComponent create a new worker instance, create a callback function to receive the response and then post the message to the worker.

    Restart the application. Since the angular.json file is changed, which is not watched by Angular runner, it is necessary to restart the application. Otherwise, Angular does not identify the new web worker and does not compile it.

    Let us create Typescript class, src/app/app.prime.ts to find nth prime numbers.

    exportclassPrimeCalculator{staticisPrimeNumber(num :number):boolean{if(num ==1)returntrue;let idx :number=2;for(idx =2; idx < num /2; idx++){if(num % idx ==0)returnfalse;}returntrue;}staticfindNthPrimeNumber(num :number):number{let idx :number=1;let count =0;while(count < num){if(this.isPrimeNumber(idx))
    
            count++;
         idx++;console.log(idx);}return idx -1;}}</pre>

    Here,

    • isPrimeNumber check whether the given number is prime or not.
    • findNthPrimeNumber finds the nth prime number.

    Import the new created prime number class into src/app/app.worker.ts and change the logic of the web worker to find nth prime number.

    /// <reference lib="webworker" />import{ PrimeCalculator }from'./app.prime';addEventListener('message',({ data })=>{// const response = worker response to ${data};const response = PrimeCalculator.findNthPrimeNumber(parseInt(data));postMessage(response);});

    Change AppComponent and include two function, find10thPrimeNumber and find10000thPrimeNumber.

    import{ Component }from'@angular/core';import{ PrimeCalculator }from'./app.prime';@Component({
       selector:'app-root',
       templateUrl:'./app.component.html',
       styleUrls:['./app.component.css']})exportclassAppComponent{
       title ='Web worker sample';
       prime10 :number=0;
       prime10000 :number=0;find10thPrimeNumber(){this.prime10 = PrimeCalculator.findNthPrimeNumber(10);}find10000thPrimeNumber(){if(typeof Worker !=='undefined'){// Create a newconst worker =newWorker('./app.worker',{ type:'module'});
    
         worker.onmessage=({ data })=&gt;{this.prime10000 = data;};
         worker.postMessage(10000);}else{// Web Workers are not supported in this environment.// You should add a fallback so that your program still executes correctly.}}}</pre>

    Here,

    find10thPrimeNumber is directly using the PrimeCalculator. But, find10000thPrimeNumber is delegating the calculation to web worker, which in turn uses PrimeCalculator.

    Change the AppComponent template, src/app/app.commands.html and include two option, one to find 10th prime number and another to find the 10000th prime number.

    <h1>{{ title }}</h1><div><a href="#"(click)="find10thPrimeNumber()">Click here</a> to find 10th prime number<div>The 10<sup>th</sup> prime numberis{{ prime10 }}</div><br/><a href="#"(click)="find10000thPrimeNumber()">Click here</a> to find 10000th prime number<div>The 10000<sup>th</sup> prime numberis{{ prime10000 }}</div></div>

    Here,

    Finding 10000th prime number will take few seconds, but it will not affect other process as it is uses web workers. Just try to find the 10000th prime number first and then, the 10th prime number.

    Since, the web worker is calculating 10000th prime number, the UI does not freeze. We can check 10th prime number in the meantime. If we have not used web worker, we could not do anything in the browser as it is actively processing the 10000th prime number.

    The result of the application is as follows −

    Initial state of the application.

    Workers

    Click and try to find the 10000th prime number and then try to find the 10th prime number. The application finds the 10th prime number quite fast and shows it. The application is still processing in the background to find the 10000th prime number.

    Web worker

    Both processes are completed.

    Web workers

    Web worker enhances the user experience of web application by doing the complex operation in the background and it is quite easy to do it in Angular Application as well.

  • Accessibility

    Accessibility support is one of the important feature of every UI based application. Accessibility is a way of designing the application so that, it is accessible for those having certain disabilities as well. Let us learn the support provided by Angular to develop application with good accessibility.

    • While using attribute binding, use attr. prefix for ARIA attributes.
    • Use Angular material component for Accessibility. Some of the useful components are LiveAnnouncer and cdkTrapFocu.
    • Use native HTML elements wherever possible because native HTML element provides maximum accessibility features. When creating a component, select native html element matching your use case instead of redeveloping the native functionality.
    • Use NavigationEnd to track and control the focus of the application as it greatly helps in accessibility.
  • Standalone Component

    Standalone Components in Angular

    In Angular, Standalone components provide a simplified way to build Angular applications. As the name suggests, standalone components are independent and do not rely on other modules or components.

    Note! Yes, standalone components are independent; they no longer depend on the @NgModule. If you try to import a standalone component into an @NgModule, you might encounter errors

    Important! The Standalone components were introduced in Angular version 14. Learn more about Angular’s various versions: See more

    Standalone components are suitable for small applications that do not require module dependencies. However, when developing a large or complex application with mandatory dependencies for components, this becomes a drawback for standalone components.

    Important! Any existing angular applications can optionally and incrementally adopt the new standalone style without any breaking changes.

    Standalone vs Non-Standalone Components

    Below is a list which differentiate between standalone and non-standalone component:

    StandaloneNon-Standalone
    Independent: Standalone components do not depend on @NgModule.Module Dependency: These components must be declared in an @NgModule to be used.
    Simplified Structure: Ideal for creating reusable components, directives, or pipes without the need to involve Angular modules.Complex Structure: Suitable for larger, more complex applications where components are part of a bigger module structure.
    The standalone @Component directive contains standalone: true and imports: [].The non-standalone component does not include these configurations.

    How to Create a Standalone Component?

    To create an standalone component in your angular application, you need to run the following command:

    ng generate component component_name
    

    In the latest version of Angular, this command will automatically create a standalone component, as the application itself supports standalone components by default.

    However, in older versions of Angular, running the above command may not create a standalone component. In that case, we need to use the following command or manually set the standalone property and specify the imports.

    ng generate component component_name --standalone
    

    The standalone component initial data will look like:

    import{ Component}from'@angular/core';@Component({
      selector:'app-root',
      standalone:true,
      imports:[],
      templateUrl:'./app.component.html',
      styleUrl:'./app.component.css'})exportclassAppComponent{
      title ='my-crud-app';}

    Here,

    • The standalone: true property identifies this component as a standalone component.
    • The imports array is where you can add all the required dependencies for this component.

    Verify the Standalone Components

    You might be wondering how to determine if a component is standalone. To verify if a component is standalone in Angular, you can check using the following guide lines:

    • Standalone Property: Check the standalone property in the component’s TypeScript file (.ts file). If the standalone property is set to true, then it’s a standalone component.
    @Component({
      selector:'app-root',
      standalone:true,
      imports:[],
      templateUrl:'./app.component.html',
      styleUrl:'./app.component.css'})

    Importing Standalone Component: If you try to import the standalone component into a non-standalone module, it should throw an error:

    Component imports must be standalone component
    

    Advantages of Standalone Components

    Below is a list of some advantages of the Standalone components:

    • Reusability: These components are self-contained, making them easy to reuse in different parts of the application without any module dependency.
    • Faster Development: As there is no need to import within the modules, developers can quickly create and integrate new components, speeding up the development process.
    • Modularity: The Standalone components enable a modular approach, allowing for better organization and maintainability of the codebase.
  • Internationalization (i18n)

    Internationalization (i18n) is a must required feature for any modern web application. Internationalization enables the application to target any language in the world. Localization is a part of the Internationalization and it enables the application to render in a targeted local language. Angular provides complete support for internationalization and localization feature.

    Let us learn how to use Internationalization in Angular by creating a simple hello world application in different languages.

    Internationalization in Angular

    Follow the steps given below to enable internationalization in Angular:

    Step 1: Create a new Angular application using below command −

    ng newi18n-sample
    

    Step 2: Navigate to the app folder using the given command −

    cd i18n-sample
    

    Step 3: Change the AppComponent’s template as specified below −

    <h2>{{ title }}</h2><div>Hello</div><div>The Current time is {{ currentDate | date :'medium'}}</div>

    Step 4: Add localize module using below command −

    ng add @angular/localize
    

    Step 5: The LOCALE_ID is the Angular variable to refer the current locale. By default, it is set as en_US. Let us change the locale by using useValue: ‘hi’ (for Hindi) in the providers array of app.component.ts. Import the locale data from @angular/common/locales/hi and then, register it using registerLocaleData method. Also, define a local variable named CurrentDate and set current time using Date.now() as specified below:

    import{ Component }from'@angular/core';import{ RouterOutlet }from'@angular/router';import{LOCALE_ID}from'@angular/core';import{ DatePipe, registerLocaleData }from'@angular/common';import localeHi from'@angular/common/locales/hi';registerLocaleData(localeHi);
    
    @Component({
      selector:'app-root',
      standalone:true,
      imports:[RouterOutlet, DatePipe],
      providers:[{ provide:LOCALE_ID, useValue:'hi'}],
      templateUrl:'./app.component.html',
      styleUrl:'./app.component.css'})exportclassAppComponent{
      title ='Internationalization Sample';
      currentDate: number = Date.now();}

    Step 6: Now run the application using ng serve command and check the result. You will see the date is specified using hi locale.

    Internationalization Sample App

    Finally, we have created a localized application in Angular.

  • Authentication and Authorization

    Authentication is the process matching the visitor of a web application with the pre-defined set of user identity in the system. In other word, it is the process of recognizing the users identity. Authentication is very important process in the system with respect to security.

    Authorization is the process of giving permission to the user to access certain resource in the system. Only the authenticated user can be authorized to access a resource.

    Let us learn how to do Authentication and Authorization in Angular application in this tutorial.

    Guards in Routing

    In a web application, a resource is referred by url. Every user in the system will be allowed access a set of urls. For example, an administrator may be assigned all the url coming under administration section.

    As we know already, URLs are handled by Routing. Angular routing enables the urls to be guarded and restricted based on programming logic. So, a url may be denied for a normal user and allowed for an administrator.

    Angular provides a concept called Router Guards which can be used to prevent unauthorized access to certain part of the application through routing. Angular provides multiple guards and they are as follows:

    • CanActivate: Used to stop the access to a route.
    • CanActivateChild: Used to stop the access to a child route.
    • CanDeactivate: Used to stop ongoing process getting feedback from user. For example, delete process can be stop if the user replies in negative.
    • Resolve: Used to pre-fetch the data before navigating to the route.
    • CanLoad: Used to load assets.

    Working Example

    In this example, we are going to add login and logout functionality to an angular application and secure it using CanActivate guard. Follow the given steps:

    Step 1: Create an angular application using the following command −

    ng newnew-app
    

    Step 2: Now, navigate to project root folder.

    cd new-app
    

    Step 3: Next, we include the Bootstrap into our new-app application using styles option and change the default template to use Bootstrap components. Use the below command to install Bootstrap and JQuery in the project −

    npm install --save bootstrap jquery
    

    Now, open angular.json file and set bootstrap and jquery library path −

    {"projects":{"expense-manager":{"architect":{"build":{"builder":"@angular-devkit/build-angular:browser","options":{"outputPath":"dist/expense-manager","index":"src/index.html","main":"src/main.ts","polyfills":"src/polyfills.ts","tsConfig":"tsconfig.app.json","aot":false,"assets":["src/favicon.ico","src/assets"],"styles":["./node_modules/bootstrap/dist/css/bootstrap.css","src/styles.css"],"scripts":["./node_modules/jquery/dist/jquery.js","./node_modules/bootstrap/dist/js/bootstrap.js"]},},}}},"defaultProject":"expense-manager"}

    Here,

    scripts option is used to include JavaScript library.

    Step 4: Create a new service named AuthService to authenticate the user. The command given below will create a service with the name auth inside Services folder.

    ng generate service Services/auth
    

    On successful creation of service, you may see the below output on Angular CLI −

    CREATE src/app/Services/auth.service.spec.ts (363 bytes)
    CREATE src/app/Services/auth.service.ts (142 bytes)
    

    Step 5: Open AuthService and include below code:

    import{ Injectable }from'@angular/core';import{ Observable,of, BehaviorSubject }from'rxjs';import{ tap, delay }from'rxjs/operators';
    
    @Injectable({
      providedIn:'root'})exportclassAuthService{// Track login state with BehaviorSubjectprivate isUserLoggedInSubject =newBehaviorSubject<boolean>(false);constructor(){// Only initialize sessionStorage on the client-side (browser)if(typeof window !=='undefined'&& window.sessionStorage){const storedLoginState = sessionStorage.getItem('isUserLoggedIn')==='true';this.isUserLoggedInSubject.next(storedLoginState);}}login(userName: string, password: string): Observable<boolean>{const isLoggedIn = userName ==='admin'&& password ==='admin';if(typeof window !=='undefined'&& window.sessionStorage){
    
        sessionStorage.setItem('isUserLoggedIn', isLoggedIn ?'true':'false');}// Update the BehaviorSubject with new login statethis.isUserLoggedInSubject.next(isLoggedIn);returnof(isLoggedIn).pipe(delay(1000),tap(val=&gt; console.log("Is User Authentication successful: "+ val)));}logout():void{if(typeof window !=='undefined'&amp;&amp; window.sessionStorage){
        sessionStorage.removeItem('isUserLoggedIn');}// Update the BehaviorSubject to false when logged outthis.isUserLoggedInSubject.next(false);}// Expose the login status as an observablegetisUserLoggedIn$(): Observable&lt;boolean&gt;{returnthis.isUserLoggedInSubject.asObservable();}}</pre>

    Here,

    • We have written two methods, login and logout.
    • The purpose of the login method is to validate the user and if the user successfully validated, it stores the information in localStorage and then returns true.
    • Authentication validation is that the user name and password should be admin.
    • We have not used any backend. Instead, we have simulated a delay of 1s using Observables.
    • The purpose of the logout method is to invalidate the user and removes the information stored in localStorage.

    Step 6: Create a login component using below command −

    ng generate component login
    

    Following output will be produced on running the above code −

    CREATE src/app/login/login.component.html (21 bytes)
    CREATE src/app/login/login.component.spec.ts (608 bytes)
    CREATE src/app/login/login.component.ts (242 bytes)
    CREATE src/app/login/login.component.css (0 bytes)
    

    Step 7: Open LoginComponent and update the existing code with the below code −

    import{ Component, OnInit }from'@angular/core';import{ FormGroup, FormControl, ReactiveFormsModule }from'@angular/forms';import{ AuthService }from'../Services/auth.service';import{ Router }from'@angular/router';
    
    @Component({
       selector:'app-login',
       standalone:true,
       imports:[ReactiveFormsModule],
       templateUrl:'./login.component.html',
       styleUrl:'./login.component.css'})exportclassLoginComponentimplementsOnInit{
    
    userName: string ="";
    password: string ="";
    formData!: FormGroup;constructor(private authService : AuthService, private router : Router){}ngOnInit(){this.formData =newFormGroup({
         userName:newFormControl("admin"),
         password:newFormControl("admin"),});}onClickSubmit(data: any){this.userName = data.userName;this.password = data.password;
      console.log("Login page: "+this.userName);
      console.log("Login page: "+this.password);this.authService.login(this.userName,this.password).subscribe(data=&gt;{ 
            console.log("Is Login Success: "+ data);if(data)this.router.navigate(['/expenses']);});}}</pre>

    Here,

    • Used reactive forms.
    • Imported AuthService and Router and configured it in constructor.
    • Created an instance of FormGroup and included two instance of FormControl, one for user name and another for password.
    • Created a onClickSubmit to validate the user using authService and if successful, navigate to expense list.

    Step 8: Open LoginComponent template and include below template code.

    <div class="container"><div class="row"><div class="col-lg-12 text-center" style="padding-top: 20px;"><div class="container box" style="margin-top: 10px; padding-left: 0px; padding-right: 0px;"><div class="row"><div class="col-12" style="text-align: center;"><form [formGroup]="formData"(ngSubmit)="onClickSubmit(formData.value)"class="form-signin"><h2 class="form-signin-heading">Please sign in</h2><label for="inputEmail"class="sr-only">Email address</label><input type="text" id="username"class="form-control" formControlName="userName" placeholder="Username" required autofocus><label for="inputPassword"class="sr-only">Password</label><input type="password" id="inputPassword"class="form-control" formControlName="password" placeholder="Password" required><button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button></form></div></div></div></div></div></div>

    Here, we created a reactive form and designed a login form. And, attached the onClickSubmit method to the form submit action.

    Step 9: Open LoginComponent CSS file and include below CSS Code.

    .form-signin {
       max-width:330px;
    
       padding:15px;
       margin:0 auto;}
    
    input {
       margin-bottom:20px;}

    Here, some styles are added to design the login form.

    Step 10: Create a logout component using below command −

    ng generate component logout
    

    You may see the below output −

    CREATE src/app/logout/logout.component.html (22 bytes)
    CREATE src/app/logout/logout.component.spec.ts (615 bytes)
    CREATE src/app/logout/logout.component.ts (246 bytes)
    CREATE src/app/logout/logout.component.css (0 bytes)
    

    Step 11: Open LogoutComponent and include below code.

    import{ Component, OnInit }from'@angular/core';import{ AuthService }from'../Services/auth.service';import{ Router }from'@angular/router';
    
    @Component({
      selector:'app-logout',
      standalone:true,
      imports:[],
      templateUrl:'./logout.component.html',
      styleUrl:'./logout.component.css'})exportclassLogoutComponentimplementsOnInit{constructor(private authService : AuthService, private router: Router){}ngOnInit(){this.authService.logout();this.router.navigate(['/']);}}

    Here,

    • Used logout method of AuthService.
    • Once the user is logged out, the page will redirect to home page (/).

    Step 12: Create a guard using below command −

    ng generate guard authenticate
    

    On running the above command, Angular CLI will ask "Which type of guard would you like to create?" Choose canActivate.

    CREATE src/app/authenticate.guard.spec.ts (510 bytes)
    CREATE src/app/authenticate.guard.ts (141 bytes)
    

    Step 13: Open authenticateGuard and include below code −

    import{ Injectable }from'@angular/core';import{ CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree }from'@angular/router';import{ AuthService }from'./Services/auth.service';
    
    @Injectable({
       providedIn:'root'})exportclassauthenticateGuardimplementsCanActivate{constructor(private authService: AuthService, private router: Router){}canActivate(
    
      next: ActivatedRouteSnapshot,
      state: RouterStateSnapshot): boolean | UrlTree {let url: string = state.url;returnthis.checkLogin(url);}checkLogin(url: string):true| UrlTree {
      console.log("Url: "+ url);// Check if sessionStorage is available (only in the browser)if(typeof window !=='undefined'&amp;&amp; window.sessionStorage){let val = sessionStorage.getItem('isUserLoggedIn');// Check if the value is 'true'if(val ==="true"&amp;&amp; val !=null){// If the user is already logged in and trying to access the login page, redirect to /expensesif(url ==="/login"){returnthis.router.parseUrl('/expenses');}else{returntrue;// User is allowed to proceed}}else{// If the user is not logged in, redirect to /loginreturnthis.router.parseUrl('/login');}}// In case sessionStorage isn't available (for SSR)returnthis.router.parseUrl('/login');}}</pre>

    Here,

    • checkLogin will check whether the localStorage has the user information and if it is available, then it returns true.
    • If the user is logged in and goes to login page, it will redirect the user to expenses page
    • If the user is not logged in, then the user will be redirected to login page.

    Step 14: Let's add a new component in our application. User will be redirected to this page on successful login.

    ng generate component ExpenseEntryList
    

    The output is as follows −

    CREATE src/app/expense-entry-list/expense-entry-list.component.html (34 bytes)
    CREATE src/app/expense-entry-list/expense-entry-list.component.spec.ts (687 bytes)
    CREATE src/app/expense-entry-list/expense-entry-list.component.ts (292 bytes)
    CREATE src/app/expense-entry-list/expense-entry-list.component.css (0 bytes)
    

    Here, the command creates the ExpenseEntryList Component and add the necessary code by default.

    Step 15: Create a ExpenseEntry interface within src/app/expense-entry-list.component.ts file. Then, add a method named getExpenseEntries() to return list of expense entry (mock items) in ExpenseEntryListComponent. Also, declare a local variable, expenseEntries and load the mock list of expense entries.

    import{ CommonModule }from'@angular/common';import{ Component }from'@angular/core';exportinterfaceExpenseEntry{
       id: number;
       item: string;
       amount: number;
       category: string;
       location: string;
       spendOn: Date;
       createdOn: Date;}
    
    @Component({
       selector:'app-expense-entry-list',
       standalone:true,
       imports:[CommonModule],
       templateUrl:'./expense-entry-list.component.html',
       styleUrl:'./expense-entry-list.component.css'})exportclassExpenseEntryListComponent{getExpenseEntries(): ExpenseEntry[]{let mockExpenseEntries : ExpenseEntry[]=[{ id:1, 
    
           item:"Pizza", 
           amount: Math.floor((Math.random()*10)+1), 
           category:"Food", 
           location:"Mcdonald", 
           spendOn:newDate(2020,4, Math.floor((Math.random()*30)+1),10,10,10), 
           createdOn:newDate(2020,4, Math.floor((Math.random()*30)+1),10,10,10)},{ id:1, 
           item:"Pizza", 
           amount: Math.floor((Math.random()*10)+1), 
           category:"Food", 
           location:"KFC", 
           spendOn:newDate(2020,4, Math.floor((Math.random()*30)+1),10,10,10), 
           createdOn:newDate(2020,4, Math.floor((Math.random()*30)+1),10,10,10)},{ id:1,
           item:"Pizza",
           amount: Math.floor((Math.random()*10)+1), 
           category:"Food", 
           location:"Mcdonald", 
           spendOn:newDate(2020,4, Math.floor((Math.random()*30)+1),10,10,10), 
           createdOn:newDate(2020,4, Math.floor((Math.random()*30)+1),10,10,10)},{ id:1, 
           item:"Pizza", 
           amount: Math.floor((Math.random()*10)+1), 
           category:"Food", 
           location:"KFC", 
           spendOn:newDate(2020,4, Math.floor((Math.random()*30)+1),10,10,10), 
           createdOn:newDate(2020,4, Math.floor((Math.random()*30)+1),10,10,10)},{ id:1, 
           item:"Pizza", 
           amount: Math.floor((Math.random()*10)+1), 
           category:"Food", 
           location:"KFC", 
           spendOn:newDate(2020,4, Math.floor((Math.random()*30)+1),10,10,10), 
           createdOn:newDate(2020,4, Math.floor((Math.random()*30)+1),10,10,10)},];return mockExpenseEntries;}
    title: string =""; expenseEntries!: ExpenseEntry[];constructor(){}ngOnInit(){this.title ="Expense Entry List";this.expenseEntries =this.getExpenseEntries();}}

    Step 16: Open the template file, src/app/expense-entry-list/expense-entry-list.component.html and show the mock entries in a table.

    <!-- Page Content --><div class="container"><div class="row"><div class="col-lg-12 text-center" style="padding-top: 20px;"><div class="container" style="padding-left: 0px; padding-right: 0px;"><div class="row"><div class="col-sm" style="text-align: left;">{{ title }}</div><div class="col-sm" style="text-align: right;"><button type="button"class="btn btn-primary">Edit</button></div></div></div><div class="container box" style="margin-top: 10px;"><table class="table table-striped"><thead><tr><th>Item</th><th>Amount</th><th>Category</th><th>Location</th><th>Spent On</th></tr></thead><tbody><tr *ngFor="let entry of expenseEntries"><th scope="row">{{ entry.item }}</th><th>{{ entry.amount }}</th><td>{{ entry.category }}</td><td>{{ entry.location }}</td><td>{{ entry.spendOn | date:'short'}}</td></tr></tbody></table></div></div></div></div>

    Here,

    • Used bootstrap table. table and table-striped will style the table according to Boostrap style standard.
    • Used ngFor to loop over the expenseEntries and generate table rows.

    Step 17: Open src/app/app.routes.ts and update below code −

    import{ Routes }from'@angular/router';import{ LoginComponent }from'./login/login.component';import{ LogoutComponent }from'./logout/logout.component';import{ authenticateGuard }from'./authenticate.guard';import{ ExpenseEntryListComponent }from'./expense-entry-list/expense-entry-list.component';exportconst routes: Routes =[{ path:'login', component: LoginComponent },{ path:'logout', component: LogoutComponent },{ path:'expenses', component: ExpenseEntryListComponent, canActivate:[authenticateGuard]},{path:' ', redirectTo:'/login', pathMatch:'full'}];

    Here,

    • Imported LoginComponent and LogoutComponent.
    • Imported authenticateGuard.
    • Created routes, login and logout to access LoginComponent and LogoutComponent.
    • Add new option canActivate for ExpenseEntryListComponent.

    Step 18: Open AppComponent template and add two login and logout link.

    <nav class="navbar navbar-expand-lg navbar-dark bg-dark static-top"><div class="container"><a class="navbar-brand" href="#">{{ title }}</a><button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbarResponsive"><ul class="navbar-nav ml-auto"><li class="nav-item active"><a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a></li><li class="nav-item"><a class="nav-link" href="#">Report</a></li><li class="nav-item"><a class="nav-link" href="#">Add Expense</a></li><li class="nav-item"><a class="nav-link" href="#">About</a></li><li class="nav-item"><div *ngIf="isUserLoggedIn; else isLogOut"><a class="nav-link" routerLink="/logout">Logout</a></div><ng-template #isLogOut><a class="nav-link" routerLink="/login">Login</a></ng-template></li></ul></div></div></nav><router-outlet></router-outlet>

    Step 19: Open AppComponent and update below code −

    import{ Component }from'@angular/core';import{ RouterOutlet }from'@angular/router';import{ ExpenseEntryListComponent }from'./expense-entry-list/expense-entry-list.component';import{ LoginComponent }from'./login/login.component';import{ LogoutComponent }from'./logout/logout.component';import{ AuthService }from'./Services/auth.service';import{ CommonModule }from'@angular/common';
    
    @Component({
      selector:'app-root',
      standalone:true,
      imports:[RouterOutlet, ExpenseEntryListComponent, LoginComponent, LogoutComponent, CommonModule],
      templateUrl:'./app.component.html',
      styleUrl:'./app.component.css'})exportclassAppComponent{
    
    title ='Angular Authentication';
    isUserLoggedIn: any =false;
    router: any;constructor(private authService: AuthService){}ngOnInit(){// Subscribe to the isUserLoggedIn observable from AuthServicethis.authService.isUserLoggedIn$.subscribe(status=&gt;{this.isUserLoggedIn = status;
        console.log("Is User Logged In: ",this.isUserLoggedIn);});}logout():void{// Trigger logout in AuthServicethis.authService.logout();// Redirect to the homepage after logoutthis.router.navigate(['/']);}}</pre>

    Here, we have added the logic to identify the user status so that we can show login/logout functionality.

    Step 20: Start the application using following command −

    ng serve
    

    Enter admin as username and password and then, click submit. The application process the login and redirects the user to expense list page as shown below −

    authentication in angular
  • Signals

    What are Signals in Angular?

    Signal is a wrapper around a value that notifies interested consumers when that value changes. A signal can contain any value, from primitives to complex data structures.

    In Angular, Signals are a system (or reactive primitives) that granularly (closely) tracks and updates how and where your state is used throughout the application, allowing the framework to optimize rendering updates.

    When a signal value changes, it automatically triggers updates to any dependent components or services that are observing it. For example:

    // Declaring a regular variable
    count1:number=0;// Declaring a variable using signals
    count2 =signal(0);

    In this case, count1 will not automatically reflect the latest value when it changes. However, count2, which is a signal, will automatically update and reflect the latest value whenever it changes.

    Important! In Angular, the signals were introduced in version 16.0 and became stable in version 17.0.

    Note: Â To read a signal, you need to call its getter function, which allows angular to track where the signal is used. The signals in angular may be either writable or read-only.

    Reactive Primitives in Angular Signals

    Here is a list of the commonly used Signals or reactive primitives (constructs) in Angular:

    Writable Signals

    In Angular, the writable signals are specific types of signals that allow you to “modify the value directly”. In addition, they are used to represent the value that can be changed.

    These signals provide an API for “updating their values directly”. You can create writable signals by calling the signal function with the signal’s initial value.

    Syntax

    Following is the syntax of the Angular Writable Signal −

    count =signal(initial_value =0);

    Here,

    • The count is a variable whose “initial signal value” is 0 (can be any value).
    • Signal() is a constructor that “defines the writable signal”.

    Here are “two” commonly used methods to set or update the writable signal value:

    • set()
    • update()

    The set() method

    To “change” the value of the writable signal, you can use the set() method to set it directly.

    Syntax

    Below is the syntax of the set() method −

    //Initializing a signal with an initial value
    count.set(initial_value);

    Here, count is a variable for which we ‘set’ the initial_value.

    The update() method

    You can use the update() method or operation to compute a “new value” from the “previous one”.

    Syntax

    Below is the syntax of the update() method −

    count.update(value => value + new_value);

    Here, the value is the previous “value”, which will be updated by adding a new_value in it.

    Note! The writable signals have the type WritableSignal.

    Example of Writable Signal in Angular

    We create a Signal with an initial value of 0 using the signal(0) constructor. We will use the set() and update() methods in different functions to “increase” and “decrease” the count value on each click of the given button −

    TypeScript code (component.ts)

    import{ Component, OnInit, Signal, signal }from'@angular/core';import{ CommonModule }from'@angular/common';import{ RouterOutlet }from'@angular/router';@Component({
      selector:'app-root',
      standalone:true,
      imports:[CommonModule, RouterOutlet],
      templateUrl:'./app.component.html',
      styleUrl:'./app.component.css'})exportclassAppComponent{//declaring a singnal
      count =signal(0);increase(){//using .set() method to increase count valuethis.count.set(this.count()+1);}decrease(){//using .update() method to decrease count valuethis.count.update(value =>this.count()-1);}}

    HTML Code (component.html)

    <div><div class="count"><h3>{{count()}}</h3></div><div class="btn"><button (click)="increase()">Increase count</button><button (click)="decrease()">Decrease count</button></div></div>

    CSS Code (component.css)

    .main{width: 300px;}.count{font-size: 40px;font-weight: bold;font-family: sans-serif;text-align: center;}button{padding: 10px 4px;margin: 0px 5px auto;background-color: green;color: white;border-radius: 5px;cursor: pointer;}

    Output

    Following is the output of the above code:

    Writable Signals

    Computed Signals

    In Angular, the Computed Signals are read-only signals, which means they “can’t be edited” by the user. The computed signals drive their values from other signals (e.g., writable signals).

    You can define the Computed signal using the computed() function by specifying the derivation.

    Syntax

    Following is the syntax of the Angular Computed Signal −

    // Initializing a signal with an initial value
    count =signal(initial_value);// Creating a computed signal
    new_count: Signal<number>=computed(()=>count()+ new_value);

    Here,

    In the above snippet of code, the new_count signal depends on the count signal, so whenever the count signal updates, angular knows that the new_count also needs to be updated.

    Important Points of the Computed Signals

    1. Computed signals are both lazily evaluated and memorized

    In angular, the Computed (read-only) signals are both lazily evaluated and memorized, so the new_count derivation function does not run to calculate its value until the first time you read the “new_count”.

    2. Computed signals are not writable signals

    The Computed signals are “not writable signals”, because you can not directly assign values to them as:

    new_count.set(10);

    The above snippet of code in the application will produce a compilation error because new_count is “not” a Writable Signal.

    Example of Computed Signal in Angular

    We will create two writable signals named length and breadth with initial values of 20 and 40. Then we will create a Computed signal named area, which will be the “product” of both writable signal −

    TypeScript code (component.ts)

    import{ Component, computed, signal, WritableSignal }from'@angular/core';import{ CommonModule }from'@angular/common';import{ RouterOutlet }from'@angular/router';@Component({
      selector:'app-root',
      standalone:true,
      imports:[CommonModule, RouterOutlet],
      templateUrl:'./app.component.html',
      styleUrl:'./app.component.css'})exportclassAppComponent{
      length: WritableSignal<number>=signal(20);
      breadth: WritableSignal<number>=signal(40);
      area:any=0;calculate(){this.area =computed(()=>this.length()*this.breadth());}}

    HTML code (component.html)

    <div class="main"><div class="count"><h3>{{area()}}</h3></div><div class="btn"><button (click)="calculate()">Calculate area</button></div></div>

    Output

    The output of the above code −

    computed signals

    Note: When the Writable signals (length and breadth) values will change the Computed signal (area) value will change automatically.

    Effects

    In Angular, the effects is an “operation” that “runs” when “one or more signal values changed” at a time. The effect always runs at least once.

    Similar to the Angular signalseffects keep track of their dependencies dynamically.

    Hint: The good place to create effects is within the constructor because the effect function requests an “injection context”.

    Syntax

    Following is the syntax of the Angular effects −

    effect(()=>{//statement or expressions....})

    effect accepts a “function”, within which will perform all the tasks.

    Example of Effect in Angular Signal

    We will create “two effects” for count and color signal within the constructor, which will run when one or more signal values change or at least once when the application runs −

    TypeScript code (component.ts)

    import{ Component, effect, signal }from'@angular/core';import{ CommonModule }from'@angular/common';import{ RouterOutlet }from'@angular/router';@Component({
      selector:'app-root',
      standalone:true,
      imports:[CommonModule, RouterOutlet],
      templateUrl:'./app.component.html',
      styleUrl:'./app.component.css'})exportclassAppComponent{constructor(){//count signaleffect(()=>{console.log("Effect due to count signal is trigger: "+this.count());});//color signaleffect(()=>{console.log("Effect due to color signal is trigger: "+this.color());});}
      
      count =signal(0);
      color =signal(["red","green"]);display(){this.count.set(30);this.color.update(value =>[...value,"Yellow"]);}}

    HTML code (component.html)

    <div class="main"><div class="count"><h3>{{count()}}</h3></div><div class="btn"><button (click)="display()">Display</button></div></div>

    Output

    When the signal “values are not changed”, the effect runs at least once:

    effects

    When signal “values changed”:

    effects

    Why to use Signals in Angular?

    Here are some points that tell about why to use the Signals in Angular project:

    • Automatic updates: Signals are automatically update any dependent computed signals or view when their values changes.
    • Efficient Change Detection: Signals are optimized for minimal change detection cycles, which enhance the application performance.
    • Composable Logic: Signals and computed signals can be used together to build complex reactive logic in a flexible and reusable manner.

    Advantages of Signals in Angular

    Below is a list of the advantages of the Angular Signals −

    • Signals make Angular lighter and point the way to a future without Zone.js (used for change detection). They enable Angular to find out about components that need to be updated directly.
    • We will be notified when the signal value changes, and then do something in response to the new signal value.
    • It is avoiding unnecessary checks of components whose data didn’t change.
  • RxJS

    What is Reactive Programming?

    In computing, Reactive programming is a way of writing code, where you deal with “data streams” and “changes automatically”. It is telling the computer what you want to do, rather than how to do it step by step. This approach helps you to keep your program structured and easier to understand for others.

    Example

    In the following example we use the reactive programming, so the value of variable a is automatically updated whenever the values of b or c change, without the program having to explicitly re-state the statement a := b + c to re-assign the value of a:

    //normal programvar b =5;var c =7;var a = b + c;
    b =5;console.log(a);// 12//reactive programvar b =5;var c =7;var a $= b + c;
    b =5;console.log(a);// 17

    The other one is a reactive program, which emits real-time updates when the related or its own value propagates (changed).

    How does Reactive Programming work?

    Reactive programming is a programming paradigm that deals with asynchronous data streams and the propagation of changes. It allows developers to model and manage data flows in a better way. It is simplifying the handling of asynchronous tasks such as UI updates, event handling, and managing data that changes over time.

    What is RxJS?

    The RxJS stands for “Reactive Extensions for JavaScript”, which is a library for “reactive programming” using observable’s that make easier to compose “asynchronous” or “callback-based” code.

    In addition, the RxJS library is used to compose the “asynchronous” and “event-based” programs by using observable sequences. It provides one core type, the “Observable”, “satellite” types (Observer, Schedulers, Subjects), and “operators” inspired by Array methods (map, filter, reduce, every, etc) to allow handling asynchronous events as collections.

    Note! Asynchronous data refers to data that is processed or retrieved at different times, rather than in a sequential or synchronous manner.

    Key Concepts

    Here are some key concepts of the RxJS library that solve Async event management:

    • Observable: An Observable in Angular is a key part of reactive programming, providing support for passing messages (data) between publishers and subscribers asynchronously.
    • Observer: It is a collection of callbacks that knows how to “listen” to values delivered by the Observable.
    • Subscription: It represents the “execution of an Observable” and is primarily used to cancel the execution.
    • Operators: These are the pure functions that enable a functional programming style of dealing with collections with operations like map, filter, concat, reduce, etc.
    • Subject It’s “equivalent to an EventEmitter“, and it is the only way of multicasting a value or event to multiple Observers.
    • Schedulers: These are “centralized dispatchers” that control concurrency, allowing us to coordinate when computation happens.

    This library also provides utility functions for creating and working with “observables”. These utility functions can be used for:

    • Converting existing code for async operations into observables.
    • Iterating through the values in a stream.
    • Mapping values to different types.
    • Filtering streams.
    • Composing multiple streams.

    Examples of RxJS

    Here are a few examples that help you understand the “RxJS library”, “observable concept”, and “reactive programming” better:

    Example 1: Register Event Listener

    In HTML, you normally register an event listener using the addEventListener() method as:

    document.addEventListener('click',()=>console.log('You Clicked!'));

    But in the RxJS, you can create an observable instead of registering an “eventListener”:

    import{ fromEvent }from'rxjs';fromEvent(document,'click').subscribe(()=>console.log('You Clicked!'));

    Here, the subscribe() method is used to access the observable data. No changes will be reflected until you subscribe to it.

    Example 2: Purity (using the pure functions)

    What makes RxJS powerful is its ability to generate values ​​using pure functions. This means your code will have fewer errors.

    In RxJS, a pure function is one that, given the “same inputs”, always produces the “same outputs” and has no side effects.

    Usually, you would create an impure function, where other pieces of your code can mess up your state (fields).

    Here, is how you implement in JavaScript −

    let count =0;// initial value 0//adding event listener
    document.addEventListener('click',()=>console.log(Clicked ${++count} times));

    The above snippet of code will “count” the “number of clicks” on the “document” and log the count each time the document is clicked.

    Using RxJS you isolate the state (field):

    import{ fromEvent, scan }from'rxjs';fromEvent(document,'click').pipe(scan((count)=> count +1,0)).subscribe((count)=>console.log(Clicked ${count} times));

    Here,

    • The scan operator in RxJS works similarly to the reduce() function for arrays. It takes an initial value and a callback. Each time the callback runs, it returns a value that will be used as the input for the next iteration.

    Using RxJS with Angular

    The RxJS library provides several functions that can be used to “create new Observable” in Angular Project.

    These functions can simplify the process of creating observables from various sources such as events, timers, and promises. For example:

    Create an observable from a promise

    In the following snippet of code, we create an observable using the from operator with a promise returned by the “fetch API” in Angular −

    import{ from, Observable }from'rxjs';// Create an Observable from out of promiseconst data =from(fetch('/api/endpoint'));// Subscribe to start listening for async output
    data.subscribe({next(res){console.log(res);},error(err){console.error('Error: '+ err);},complete(){console.log('Completed');}});

    Create an observable from a counter

    In this example, we will create an observable that emits incrementing numbers every 1000 milliseconds (1 second) in Angular −

    import{ interval }from'rxjs';// Create an Observable const secondsCounter =interval(1000);// Subscribe to start interval valuesconst subscription = secondsCounter.subscribe(n =>console.log(It's been ${n + 1} seconds since the subscription started!));

    Why to use RxJS in Angular?

    Below is the list of several benefits that define why to use RxJS Library in Angular:

    • Reactive Programming: It allows for Reactive programming, which makes it easier to simplify the asynchronous code.
    • Error Handling: RxJS provides robust error-handling mechanisms, allowing you to smoothly handle and recover from errors in your asynchronous operations.
    • Data Transfer: Using the RxJS operators, you can easily transform data streams, such as mapping, filtering, and reducing data.
    • Angular Integration: Angular has built-in support for RxJS, and many Angular modules, such as HttpClient, are designed to work easily with observables.
  • PrimeNG

    What is PrimeNG?

    PrimeNG is a cohesiveUI component library specifically designed for Angular applications. It provides a collection of ready-to-use UI components (e.g., themes, icons, and components) such as “input fields,” “buttons,” “tables,” “lists,” “cards,” etc, for building user interfaces. It allows developers to integrate these into their applications rather than building them from scratch.

    However, PrimeNG is not directly compatible with “React”, “Vue”, or other front-end frameworks, as it is designed for Angular.

    Here are a few UI components of the PrimeNG library which code you can directly use in your angular application:

    PrimeNG UI Components

    Why to use a PrimeNG in Angular?

    Here are several reasons to use the PrimeNG library in your Angular project:

    • Easy Integration: PrimeNG is very easy to integrate with your Angular application.
    • Responsive and Mobile-friendly: Angular applications developed using PrimeNG UI components are very compatible and responsive across various screen sizes.
    • OpenSource & paid version: PrimeNG offers a free version with many useful and powerful components and a premium version (i.e., paid) as well for the advanced features.
    • Frequent Updates: The library is actively maintained and regularly updated, which enables the latest features with best practices.

    Installations and Setups

    The PrimeNG UI Component library is a third-party library. To use its components in your application or project, you need to install it and add all the required dependencies first; only then can you use it.

    Here is a step-by-step process for installing the PrimeNG library in your project:

    Step 1: Use the following command to install the PrimeNG library in your Angular project:

    npm install primeng@<version>
    

    Here, @<version> refers to the version you want to install, which should be compatible with your project. For example: npm install [email protected].

    Important! If you do not specify a specific version, it might throw an error because the project version could be different from the version of the library you are installing when using the simple npm install primeNG command without specifying a version.

    Step 2: Open the angular.json file and add the code below within the styles section, in both the build and test sections:

    "node_modules/primeng/resources/themes/lara-light-indigo/theme.css",
    "node_modules/primeng/resources/primeng.min.css",
    

    After completing the above steps, the installation is done, and now we are ready to use the PrimeNG library components in our project.

    Use the following command to install PrimeNG icons, which provide different icons such as “social media icons”, “trash”, “view”, “edit” icons, etc., and add the same inside the styles section:

    npm install primeng@version primeicons
    

    How to use PrimeNG in our Project?

    Follow these steps to use the PrimeNG components in your application as needed:

    Step 1: Open the primeNG website and explore all the components:

    PrimeNG1

    Adding InputText Component

    InputText is an extension to a standard input element with “theming” and “keyfiltering”. To add the InputText component to your project template, you need to follow these steps:

    Step 2: Open the InputText component documentation on the PrimeNG website that you want to use it in your template:

    PrimeNG Input Text

    Step 3: Import and add the InputText component API in your component or module to access and use it in your template:

    import{ Component }from'@angular/core';import{ CommonModule }from'@angular/common';import{ RouterOutlet }from'@angular/router';import{ InputTextModule }from'primeng/inputtext';@Component({
      selector:'app-root',
      standalone:true,
      imports:[CommonModule, RouterOutlet, InputTextModule],
      templateUrl:'./app.component.html',
      styleUrl:'./app.component.css'})exportclassAppComponent{
      title ='myApp';}

    Step 4: Add the below InputText inbuilt code in your template (e.g., app.component.html):

    <h3>Angular with PrimeNG</h3><input type="text" pInputText placeholder="Input text....."/>

    Step 5: After adding the above code, run the application using the following command:

    ng serve
    

    Output

    Navigate the URL localhost:4200 to see the output of the above code:

    PrimeNG Input Text1

    Adding Button Component

    Let’s see how to add a Button component to your project template:

    Step 1: Just like the InputText component, open the Button component on the PrimeNG website and go to the features section:

    PrimeNG Button

    Step 2: Import and add the API in your component or module that you want to use (e.g., app.component.ts):

    import{ Component }from'@angular/core';import{ CommonModule }from'@angular/common';import{ RouterOutlet }from'@angular/router';import{ InputTextModule }from'primeng/inputtext';import{ ButtonModule }from'primeng/button';@Component({
      selector:'app-root',
      standalone:true,
      imports:[CommonModule, RouterOutlet, InputTextModule, ButtonModule],
      templateUrl:'./app.component.html',
      styleUrl:'./app.component.css'})exportclassAppComponent{
      title ='myApp';}

    Step 3: Add the Button Component in your template (e.g., app.component.html):

    <h3>Angular with PrimeNG</h3><input type="text" pInputText placeholder="Input text....."/><p-button label="Submit"/>

    Output

    The output of the above code will be displayed as follows:

    PrimeNG Button1
  • Angular Material

    What is Angular Material?

    Angular Material is a UI component library developed by the Angular team to integrate easily with your Angular applications. This library is “specific” to the Angular framework and provides a set of reusable, accessible, well-tested components that help create a responsive modern user interface (UI).

    It also provides tools that help developers to create custom UI components with common interaction patterns. Angular applications developed using Angular Material components ensure “responsiveness” on different screen sizes, such as “phones”, “tablets”, and “laptops”.

    Notes! Angular Material provides a huge collection of high-quality and ready-made Angular components based on Material Design, such as input fields, forms, buttons, cards, tables, lists, etc.

    Let us learn how to install Angular Material Library in your Angular project and how to use its components.

    Important! This guide assumes that an Angular application has already been created and the Angular CLI has already been installed.

    How to Install Angular Material in an Angular Project?

    To install Angular Material Library in your Angular project or application, ensure that the Angular CLI is already installed and that the application has been created successfully.

    Follow the steps given below and implement each step in your existing project one by one to install Angular Material Library:

    Step 1: Open any “existing Angular project” in your preferred code editor (e.g., vs code) −

    cd /go/to/materialApp
    

    Here, materialApp is your project folder name.

    Step 2: Open the terminal in your editor and go to the application directory −

    cd material-app
    

    Step 3: Add Angular Material to your application by running the following command −

    ng add @angular/material
    

    The ng add command will “install Angular Material” in your application.

    Once you run the above command, Angular CLI will ask certain questions regarding “theme”, “gesture recognition”, and “browser animations”.

    Select any theme of your choice and then answer positively for gesture recognition and browser animation.

    ✔ Packages successfully installed.
    ? Choose a prebuilt theme name, or "custom" for a custom theme: (Use arrow keys)
    > Indigo/Pink        [Preview: https://material.angular.io?theme=indigo-pink]
      Deep Purple/Amber  [Preview: https://material.angular.io?theme=deeppurple-amber]
      Pink/Blue Grey     [Preview: https://material.angular.io?theme=pink-bluegrey]
      Purple/Green       [Preview: https://material.angular.io?theme=purple-green]
      Custom
    
    ? Choose a prebuilt theme name, or "custom" for a custom theme: Indigo/Pink 
    

    Set up “global Angular Material typography” styles:

    ? Set up global Angular Material typography styles? Yes
    

    Include browser animations for Angular Material:

    ? Include the Angular animations module? (Use arrow keys)
    > Include and enable animations 
      Include, but disable animations 
      Do not include 
    

    Hint! To choose different options use the down arrow key in your keyboard.

    Set up “browser animations” for Angular Material:

    Importing the BrowserAnimationsModule into your application enables Angular’s animation system.

    Once the Material gets installed successfully you will be able to see the message below:

    UPDATE package.json (1111 bytes)
    ✔ Packages installed successfully.
    UPDATE src/app/app.config.ts (338 bytes)
    UPDATE angular.json (2795 bytes)
    UPDATE src/index.html (520 bytes)
    UPDATE src/styles.css (181 bytes)
    

    The ng add command will additionally perform the following actions:

    • Add project dependencies to package.json.
    "@angular/material":"^17.3.10"

    Add the Roboto font to your index.html

    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
    

    Add the “Material Design icon font” to your index.html.

    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    

    Add a few global CSS styles to:

    • Remove margins from “body”.
    • Set height 100% on HTML and body.
    • Set Roboto as the default application font.
    html, body { height: 100%; }
    body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
    

    Completed! Angular Material is now configured to be used in your Angular application.

    How to use Angular Material in Angular Project?

    To use the Angular Material Components in your Angular project implement the following steps:

    Step 1: Open the “Angular Material” website on your browser:

    Angular Material Components

    Step 2: Open the component (e.g., button) which you want to use:

    Material Components

    Step 3: Go to the API section and copy the import:

    Material Components1

    Step 4: Import the “relevant API” in your component or module where you want to use:

    import{ Component }from'@angular/core';import{ CommonModule }from'@angular/common';import{ RouterOutlet }from'@angular/router';import{MatButtonModule}from'@angular/material/button';@Component({
      selector:'app-root',
      standalone:true,
      imports:[CommonModule, RouterOutlet, MatButtonModule],
      templateUrl:'./app.component.html',
      styleUrl:'./app.component.css'})exportclassAppComponent{
      title ='material-app';}

    Step 5: Go to the examples section and you will see various examples of button components:

    Material Components2

    Step 6: Open the AppComponent (i.e., app.component.htm) and place the code below to see the different types of buttons:

    <h2>Welcome to Angular Material Example</h2><button mat-button>Basic</button><button mat-raised-button>Basic</button><button mat-button disabled>Disabled</button><button mat-flat-button>Basic</button>

    Here,

    • mat-button is the class name for the “basic button”.
    • mat-button disabled is the class name for the ‘disabled button.

    Step 6: Run your application to see the changes:

    ng serve
    

    Then navigate your browser to http://localhost:4200 URL.

    Material Components3

    Here, the application clearly shows the Angular different Material buttons.

    List of Common used Components

    Below is the some of the important UI elements provided by Angular Material package:

    UI ElementDescription
    Form fieldThe <mat-form-field> is a component used to wrap several Angular Material components.
    InputThe matInput is a directive that allows native <input> and <textarea> elements to work with <mat-form-field>.
    CheckboxThe <mat-checkbox> provides the same functionality as a native <input type=”checkbox”> enhanced with Material Design styling and animations.
    Radio buttonThe <mat-radio-button> provides the same functionality as a native <input type=”radio”> enhanced with Material Design styling and animations.
    SelectThe <mat-select> is a form control for selecting a value from a set of options, similar to the native <select> element.
    ButtonThe Angular Material buttons are native <button> or <a> elements enhanced with Material Design styling and ink ripples.
    DatePickerThe datepicker allows users to enter a date either through text input, or by choosing a date from the calendar.
    ListThe <mat-list> is a container component that wraps and formats a series of <mat-list-item>.
    CardThe <mat-card> is a content container for text, photos, and actions in the context of a single subject.
    Grid listThe mat-grid-list is a “two-dimensional” list view that arranges cells into “grid-based” layout.
    TableThe mat-table provides a Material Design styled data-table that can be used to display rows of data.
    PaginatorThe <mat-paginator> provides navigation for paged information, typically used with a table.
    TabsAngular Material tabs organize content into separate views where only one view can be visible at a time.
    ToolbarThe <mat-toolbar> is a container for “headers”, “titles”, or “actions”.
    MenuThe <mat-menu> is a floating panel containing list of options.
    DialogThe MatDialog service can be used to “open modal dialogs” with Material Design styling and animations.
    SnackbarThe MatSnackBar is a service for displaying snack-bar notifications.
    Progress barThe <mat-progress-bar> is a horizontal progress-bar for indicating progress and activity.
    IconThe mat-icon makes it easier to use vector-based icons in your app.
    DividerThe <mat-divider> is a component that allows for Material styling of a line separator with various orientation options.

    Why to use Angular Material?

    Use Angular Material because it provides built-in UI components that are easy to integrate with Angular applications, saving developers time by offering ready-to-use elements like “buttons”, “cards”, and “input” fields. It also ensures the application is “responsive” and fully functional across various screen sizes.