Sign In Start Free Trial
Account

Add to playlist

Create a Playlist

Modal Close icon
You need to login to use this feature.
  • Book Overview & Buying Angular Cookbook
  • Table Of Contents Toc
  • Feedback & Rating feedback
Angular Cookbook

Angular Cookbook

By : Muhammad Ahsan Ayaz
4 (13)
close
close
Angular Cookbook

Angular Cookbook

4 (13)
By: Muhammad Ahsan Ayaz

Overview of this book

Angular has long been the framework of choice for web development projects of various scales, offering much-needed stability and a rich tooling ecosystem for building production-ready web and mobile apps. This recipe-based guide ensures high performance apps with the latest version of Angular, helping you to build up your Angular expertise with a wide range of recipes across key tasks in web development. In this second edition, the recipes have been updated, added, and improved based on developer feedback, new challenges, and Angular 17. The first few chapters will show you how to utilize core Angular concepts such as components, directives, and services to get you ready for building frontend web apps. You’ll then develop web components with Angular and go on to learn about advanced concepts such as dynamic components loading and state management with NgRx for achieving real-time performance. Later chapters will focus on recipes for effectively testing your Angular apps to make them fail-safe, before progressing to techniques for optimizing your app’s performance. Finally, you’ll create Progressive Web Apps (PWA) with Angular to provide an intuitive experience for users. By the end of this book, you’ll be able to create full-fledged, professional-looking Angular apps and have the skills you need for frontend development.
Table of Contents (16 chapters)
close
close
14
Other Books You May Enjoy
15
Index

Creating a directive to calculate the read time for articles

In this recipe, you’ll create an attribute directive to calculate the read time of an article, just like Medium (https://medium.com), which is a platform for sharing articles and blog posts. The code for this recipe is highly inspired by my existing repository on GitHub, which you can view at the following link: https://github.com/AhsanAyaz/ngx-read-time.

Getting ready

The app that we are going to work with resides in start/apps/chapter02/ng-read-time-directive inside the cloned repository:

  1. Open the code repository in your code editor.
  2. Open the terminal, navigate to the code repository directory, and run the following command to serve the project:
    npm run serve ng-read-time-directive
    

    This should open the app in a new browser tab and you should see the following:

    Figure 2.3: ng-read-time-directive app running on http://localhost:4200

How to do it…

Right now, we have a paragraph in our app.component.html file for which we need to calculate the read-time in minutes. Let’s get started:

  1. First, we’ll create an attribute directive named read-time. To do that, run the following command from the project root and select the @nx/angular:directive schematics when asked:
    cd start && nx g directive read-time --directory apps/chapter02/ng-read-time-directive/src/app/directives --standalone=false
    

    If asked, choose the @nx/angular:directive schematics and choose the “As provided” action.

    Note that we’re using --standalone = false in the command. That is because we have an NgModule based application and the AppComponent is not a standalone component.

  1. The preceding command creates a directive with the class name ReadTimeDirective and has appReadTime as the selector. We’ll apply this directive to the div that has id set to mainContent inside the app.component.html file as follows:
    ...
    <div class="content" role="main" id="mainContent"
      appReadTime>
    ...
    </div>
    
  2. Now, we’ll create a configuration object for our appReadTime directive. This configuration will contain a wordsPerMinute value, on the basis of which we’ll calculate the read time. Let’s create an input inside the read-time.directive.ts file with a ReadTimeConfig exported interface for the configuration, as follows:
    import { Directive, Input } from '@angular/core';
    export interface ReadTimeConfig {
      wordsPerMinute: number;
    }
    @Directive({
      selector: '[appReadTime]'
    })
    export class ReadTimeDirective {
      @Input() configuration: ReadTimeConfig = {
        wordsPerMinute: 200
      }
      constructor() { }
    }
    
  3. We can now move on to getting the text to calculate the read time. For this, we’ll use the ElementRef service to retrieve the textContent property of the element. We’ll extract the textContent property and assign it to a local variable named text in the ngOnInit life cycle hook, as follows:
    import { Directive, Input, ElementRef, OnInit } from '@angular/core';
    ...
    export class ReadTimeDirective implements OnInit {
      @Input() configuration: ReadTimeConfig = {
        wordsPerMinute: 200
      }
      constructor(private el: ElementRef) { }
      ngOnInit() {
        const text = this.el.nativeElement.textContent;
      }
    }
    
  4. Now that we have our text variable filled up with the element’s entire text content, we can calculate the time to read this text. For this, we’ll create a method named calculateReadTime by passing the text property to it, as follows:
    ...
    export class ReadTimeDirective implements OnInit {
      ...
      ngOnInit() {
        const text = this.el.nativeElement.textContent;
        const time = this.calculateReadTime(text);
        console.log({ readTime: time });
      }
      calculateReadTime(text: string) {
        const wordsCount = text.split(/\s+/g).length;
        const minutes = wordsCount / this.configuration.
          wordsPerMinute;
        return Math.ceil(minutes);
      }
    }
    

    If you look at the console now, you should see an object containing the readTime property being logged. The value of readTime is the time in minutes:

    Figure 2.4: Console log showing the time in minutes

  1. We’ve got the time now in minutes, but it’s not in a user-readable format at the moment since it is just a number. We need to show it in a way that is understandable for the end user. To do so, we’ll do some minor calculations and create an appropriate string to show on the UI. The code is shown here:
    ...
    @Directive({
      selector: '[appReadTime]'
    })
    export class ReadTimeDirective implements OnInit {
    ...
      ngOnInit() {
        const text = this.el.nativeElement.textContent;
        const time = this.calculateReadTime(text);
        const timeStr = this.createTimeString(time);
        console.log({ readTime: timeStr });
      }
    ...
      createTimeString(timeInMinutes: number) {
        if (timeInMinutes < 1) {
          return '< 1 minute';
        } else if (timeInMinutes === 1) {
          return '1 minute';
        } else {
          return `${timeInMinutes} minutes`;
        }
      }
    }
    

    Note that with the code so far, you should be able to see the minutes on the console when you refresh the application.

  1. Now, let’s add an @Output() to the directive so that we can get the read time in the parent component and display it on the UI. Let’s add it as follows in the read-time.directive.ts file:
    import { Directive, Input, ElementRef, OnInit, Output, EventEmitter } from '@angular/core';
    ...
    export class ReadTimeDirective implements OnInit {
      @Input() configuration: ReadTimeConfig = {
        wordsPerMinute: 200
      }
      @Output() readTimeCalculated = new EventEmitter<string>();
      constructor(private el: ElementRef) { }
    ...
    }
    
  2. Let’s use the readTimeCalculated output to emit the value of the timeStr variable from the ngOnInit method when we’ve calculated the read time:
    ...
    export class ReadTimeDirective {
    ...
      ngOnInit() {
        const text = this.el.nativeElement.textContent;
        const time = this.calculateReadTime(text);
        const timeStr = this.createTimeString(time);
        this.readTimeCalculated.emit(timeStr);
      }
    ...
    }
    
  3. Since we emit the read-time value using the readTimeCalculated output, we have to listen to this output’s event in the app.component.html file and assign it to a property of the AppComponent class so that we can show this on the view. But before that, we’ll create a local property in the app.component.ts file to store the output event’s value, and we’ll also create a method to be called upon when the output event is triggered. The code is shown here:
    ...
    export class AppComponent {
      readTime!: string;
      onReadTimeCalculated(readTimeStr: string) {
        this.readTime = readTimeStr;
      }
    }
    
  4. We can now listen to the output event in the app.component.html file, and we can then call the onReadTimeCalculated method when the readTimeCalculated output event is triggered:
    ...
    <div class="content" role="main" id="mainContent" appReadTime
      (readTimeCalculated)= "onReadTimeCalculated($event)">
    ...
    </div>
    
  5. Now, we can finally show the read time in the app.component.html file, as follows:
    <div class="content" role="main" id="mainContent" appReadTime
      (readTimeCalculated)="onReadTimeCalculated($event)">
      <h4 class="text-3xl">Read Time = {{readTime}}</h4>
      <p class="text-content">
        Silent sir say desire fat him letter. Whatever settling
        goodness too and honoured she building answered her. ...
      </p>
    ...
    </div>
    

    If you now go to http://localhost:4200, you should be able to see the read time in the app, as shown in the following image:

    Figure 2.5: Read time being displayed in the app

How it works…

The appReadTime directive is at the heart of this recipe. While creating the directive, we create it as a non-standalone directive because the application itself is bootstrapped using an NgModule instead of a standalone AppComponent. We use the ElementRef service inside the directive to get the native element that the directive is attached to and then we take out its text content. The only thing that remains then is to perform the calculation. We first split the entire text content into words by using the /\s+/g regular expression (regex), and thus we count the total words in the text content. Then, we divide the word count by the wordsPerMinute value we have in the configuration to calculate how many minutes it would take to read the entire text. Finally, we make it readable in a better way using the createTimeString method. Easy peasy, lemon squeezy.

See also

bookmark search playlist download font-size

Change the font size

margin-width

Change margin width

day-mode

Change background colour

Close icon Search
Country selected

Close icon Your notes and bookmarks

Delete Bookmark

Modal Close icon
Are you sure you want to delete it?
Cancel
Yes, Delete

Confirmation

Modal Close icon
claim successful

Buy this book with your credits?

Modal Close icon
Are you sure you want to buy this book with one of your credits?
Close
YES, BUY