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

Using attribute directives to handle the appearance of elements

In this recipe, you’ll work with an Angular attribute directive named highlight. With this directive, you’ll be able to search words and phrases within a paragraph and highlight them on the go. The whole paragraph’s container background will also be changed when we have a search in action. For example, by using the following code:

<p class="text-content max-w-2xl m-auto" appHighlight
  [highlightText]="'de'">
  <!--text here -->

The result will appear as an output as shown in Figure 2.1:

Figure 2.1: The result when using the highlight directive

Getting ready

The app that we are going to work with resides in start/apps/chapter02/ng-attribute-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-attribute-directive
    

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

    Figure 2.2: ng-attribute-directive app running on http://localhost:4200

How to do it…

The application has a search input and a paragraph of text. We want to be able to type a search query in the input so that we can highlight and find all the matching occurrences in the paragraph. Here are the steps to achieve this:

  1. We’ll create a property named searchText in the app.component.ts file that we’ll use as a model for the search-text input:
    ...
    export class AppComponent {
      searchText = '';
    }
    
  2. Then, we use the searchText property in the template, i.e., in the app.component.html file, with the search input as an ngModel, as follows:
    ...
    <div class="content" role="main">
      ...
         <input [(ngModel)]="searchText" type="text"
           placeholder="Quick Search..." class="pr-4 !pl-10
           py-2">
      </div>
    
  3. You will notice that ngModel doesn’t work yet. This is because we’re missing the FormsModule in our application. Let’s import it into the app.component.ts file as follows:
    ...
    import { FormsModule } from '@angular/forms';
     @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      standalone: true,
      styleUrls: ['./app.component.scss'],
      imports: [CommonModule, RouterModule, FormsModule],
    })
    export class AppComponent {
      searchText = '';
    }
    
  4. Now, we’ll create an attribute directive named highlight by using the following command from the workspace root:
    cd start && nx g directive highlight --directory apps/chapter02/ng-attribute-directive/src/app --standalone
    

    If asked, choose the @nx/angular:directive schematics and choose the “As provided” action. The preceding command generates a standalone directive that has a selector called appHighlight. See the How it works… section for why that happens, and for a brief explanation of the standalone API.

  1. Now that we have the directive in place, we’ll create two inputs for the directive to be passed from AppComponent (from app.component.html)—one for the search text and another for the highlight color. The code should look like this in the highlight.directive.ts file:
    import { Directive, Input } from '@angular/core';
    @Directive({
      selector: '[appHighlight]',
      standalone: true
    })
    export class HighlightDirective {
      @Input() highlightText = '';
      @Input() highlightColor = 'yellow';
    }
    
  2. Let’s use the appHighlight directive in app.component.html and pass the searchText model from there to the appHighlight directive as follows:
    <div class="content" role="main">
      ...
      <p class="text-content" appHighlight   
        [highlightText]="searchText">
        ...
      </p>
    </div>
    
  3. We’ll listen to the input changes now for the searchText input, using ngOnChanges. Please see the Using ngOnChanges to intercept input property changes recipe in Chapter 1, Winning Component Communication, for how to listen to input changes. For now, we’ll only do a console.log when the input changes. Let’s update the highlight.directive.ts as follows:
    import { Directive, Input, OnChanges, SimpleChanges } from '@angular/core';
    ...
    export class HighlightDirective implements OnChanges {
      @Input() highlightText = '';
      @Input() highlightColor = 'yellow';
      ngOnChanges(changes: SimpleChanges) {
        if (changes['highlightText']?.firstChange) {
          return;
        }
        const { currentValue } = changes['highlightText'];
        console.log({ currentValue });
      }
    }
    

    If you type in the search input and see the console logs, you’ll see the new value being logged whenever you change the value.

  1. Now, we’ll write the logic for highlighting the search text. We’ll first import the ElementRef service so that we can get access to the template element on which our directive is applied. Here’s how we’ll do this:
    import { Directive, Input, SimpleChanges, OnChanges, ElementRef } from '@angular/core';
    @Directive({
      selector: '[appHighlight]'
    })
    export class HighlightDirective implements OnChanges {
      @Input() highlightText = '';
      @Input() highlightColor = 'yellow';
      constructor(private el: ElementRef) { }
      ...
    }
    
  2. Now we’ll replace every matching text in our el element with a custom <span> tag with some hardcoded styles. Update your ngOnChanges code in highlight.directive.ts as follows, and see the result:
    ngOnChanges(changes: SimpleChanges) {
        if (changes.highlightText.firstChange) {
          return;
        }
        const { currentValue } = changes.highlightText;
        if (currentValue) {
          const regExp = new RegExp(`(${currentValue})`,'gi')
          this.el.nativeElement.innerHTML = this.el
            .nativeElement.innerHTML.replace(regExp, `<span
            style="background-color: ${this.highlightColor}"
            >\$1</span>`)
        }
    }
    

    TIP

    You’ll notice that if you type a word, it will still show only one letter highlighted. That’s because whenever we replace the innerHTML property, we end up changing the original text. Let’s fix that in the next step.

  1. To keep the original text intact, let’s create a property named originalHTML and assign an initial value to it on the first change. We’ll also use the originalHTML property while replacing the values:
    ...
    export class HighlightDirective implements OnChanges {
      @Input() highlightText = '';
      @Input() highlightColor = 'yellow';
      originalHTML = '';
      constructor(private el: ElementRef) { }
      ngOnChanges(changes: SimpleChanges) {
        if (changes.highlightText.firstChange) {
          this.originalHTML = this.el
            .nativeElement.innerHTML;
          return;
        }
        const { currentValue } = changes.highlightText;
        if (currentValue) {
          const regExp = new RegExp(`(${currentValue})`,'gi')
          this.el.nativeElement.innerHTML = this.originalHTML
            .replace(regExp, `<span style="background-color:
            ${this.highlightColor}">\$1</span>`)
        }
      }
    }
    
  2. Now, we’ll write some logic to reset everything back to the originalHTML property when we remove our search query (when the search text is empty). In order to do so, let’s add an else condition, as follows:
    ...
    export class HighlightDirective implements OnChanges {
      ...
      ngOnChanges(changes: SimpleChanges) {
       ...
        if (currentValue) {
          const regExp = new RegExp(`(${currentValue})`,'gi')
          this.el.nativeElement.innerHTML = this.originalHTML
            .replace(regExp, `<span       style="background-
            color: ${this.highlightColor}">\$1</span>`)
        } else {
          this.el.nativeElement.innerHTML = 
            this.originalHTML;
        }
      }
    }
    

How it works…

We created an attribute directive named highlight (appHighlight) that takes two inputs: highlightText and highlightColor. The directive listens to the input changes for the highlightText input using the SimpleChanges from the ngOnChanges life cycle hook by Angular. Every property in this SimpleChanges object is a SimpleChange object that contains the following properties:

  • previousValue: any
  • currentValue: any
  • firstChange: boolean
  • isFirstChange(): boolean

First, we make sure to save the original content of the target element by getting the attached element using the ElementRef service. We get it using the .nativeElement.innerHTML property on the element we apply the directive to. We save the initial value to the originalHTML property of the directive.

Whenever the input changes, we assign a replaced version of the originalHTML by replacing all the instances of the searched term in the paragraph with an additional HTML element (a <span> element). We also add the background color to this <span> element. The background color applied comes from the highlightColor input. You can modify it to highlight using a different color. Play around and make this example your own.

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