distinctUntilChanged – RxJS

distinctUntilChanged is a very useful RxJS operator that comes in handy when you need to make sure that your observable emits value only when the current value it is about to emit is different from the last emitted value.

Let’s understand this in detail using following example;

import { from } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';

from([1, 2, 3, 3, 3, 3, 3, 3, 4, 5, 5])
  .pipe(distinctUntilChanged())
  .subscribe(num => console.log(num));
// output: 1, 2, 3, 4, 5

Although values 3 and 5 appears multiple times in the above code, these values will be logged only once as the distinctUntilChanged operator will emit the values for first time and will discard the duplicate ones.

Let’s consider one more example;

import { from } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';

const cities = [
  { name: 'Pune', country: 'India' },
  { name: 'Hyderabad', country: 'India' },
  { name: 'Pokhara', country: 'Nepal' },
  { name: 'Kathmandu', country: 'Nepal' }
];

from(cities)
.pipe(
  distinctUntilChanged((prevCity, nextCity) => prevCity.country === nextCity.country)
)
.subscribe(city => console.log(city));
 
// output:
// { name: 'Pune', country: 'India' }
// { name: 'Pokhara', country: 'Nepal' }

Above code will skip Hyderabad and Kathmandu since there is no change between previous object’s country and current object’s country.

Must Read: delay – RxJS

Angular Meta Service for HTML Meta Tags

HTML meta tags are used to provide metadata about the HTML web page such as page description, author name, important keywords or other metadata. Meta tags play an important role in search engine optimization.

Angular comes bundled with Meta service which allows us to deal with these HTML meta tags. In this post, we’re going to understand how we can leverage various methods available within this service to manage the meta tags more efficiently.

Usage

To use this service first you need to import it from @angular/platform-browser.

import { Meta } from '@angular/platform-browser';

Once the service is imported you need to inject it inside your component via the constructor like any other service.

constructor(private meta: Meta) {

}

Adding Meta Tags

Meta service comes bundled with two methods which allow you to add meta tags to your web page i.e. addTag and addTags.

addTag method accepts only a single object at once and generates only one meta tag.

import { Component } from '@angular/core';
import { Meta } from '@angular/platform-browser';

@Component({
  selector: 'app-main',
  templateUrl: './main.component.html',
  styleUrls: ['./main.component.scss']
})
export class MainComponent {
  constructor(private meta: Meta) {
    this.meta.addTag({ name: 'author', content: 'Harshal Limaye' });
  }
}

If you wish to create multiple tags using addTag you need invoke it multiple times.

constructor(private meta: Meta) {
  this.meta.addTag({ name: 'author', content: 'Harshal Limaye' });
  this.meta.addTag({ name: 'description', content: 'Front-end developer' });
}

You could use addTags method to set multiple tags in a single call. This method accepts array of objects that describes the meta tags.

constructor(private meta: Meta) {
  this.meta.addTags([
    { name: 'author', content: 'Harshal Limaye' },
    { name: 'description', content: 'Front-end developer' }
  ]);
}

Note: You could pass a second parameter as a boolean value to both addTag or addTags methods to determine if tag needs to be added even if it already exists. The default value is false.

this.meta.addTag({name: 'author', content: 'Harshal Limaye'}, true);

Retrieving Meta Tags

You can use getTag and getTags methods to retrieve the values of existing meta tags. the getTag method returns a single element whereas the getTags method returns an array of the element.

constructor(private meta: Meta) {
  const author: HTMLMetaElement = this.meta.getTag('name=author');
  console.log(author.content); // Harshal Limaye
}

If no meta tag is found for specified selector method returns null.

Updating Meta Tags

updateTag method could be used to update the value of a HTML meta tag.

constructor(private meta: Meta) {
  this.meta.updateTag({name: 'keywords', content: 'Angular, React, Vue, D3'});
}

The above code will update the value of keywords meta tag to “Angular, React, Vue, D3”

Removing Meta Tags

removeTag method could be used to remove existing HTML meta tags.

constructor(private meta: Meta) {
  this.meta.removeTag('name=author');
}

The above code removes author meta tag from the web page.

removeTagElement method could also be used to remove a meta tag. Unlike removeTag which accepts attribute selector it accepts HTMLTagElement as a parameter.

constructor(private meta: Meta) {
  const author: HTMLMetaElement = this.meta.getTag('name=author');
  this.meta.removeTagElement(author);
}

Conclusion

The Angular Meta service allows us to add, retrieve, update and remove HTML meta tags from the web page. This could be very helpful to dynamically update meta tags based on the currently active route in your application.

Must Read: Using Custom Pipes in a Component Class in Angular

Using Custom Pipes inside an Angular Component Class

In this tutorial, we’re going to learn to use Angular Pipes inside a component class. In one of my previous tutorials, we’ve created a custom pipe that accepts a number and returns its square. For this tutorial we’re going to inject that pipe inside a component

Before you can use your pipe inside a component class you need to add it to providers array of your module.

providers: [SquarePipe,...]

Next thing you need to do is you need to inject the pipe as service in the constructor of your component class.

// ...
import { SquarePipe } from './square.pipe';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {

  constructor(
    private square: SquarePipe
  ) { }

  // ...
}

And, To use this pipe you need to simply utilise the transform method on the instance of pipe object injected in the class.

getSquare(val): void {
  this.squareVal = this.square.transform(val);
  // ...
}

And that’s it. In case, you’ve any query or feedback feel free to drop a comment.

Custom Pipes – Angular

Pipes are used for transforming or formatting your data from within your templates. Angular comes bundled with a large number of built-in pipes including uppercase, lowercase, date, currency, and percent. However, there is a good chance that you might run into scenarios where you’ll need to create your own custom pipes.

In this post, we’re going to create our own custom pipe. We’re going to build pipe which accepts a number and returns it’s square. We’ll start by creating a new Typescript file ‘square.pipe.ts’.

Next thing we’ll do is import Pipe decorator and PipeTransform interface at the top of that file.

import { Pipe, PipeTransform } from '@angular/core';

Next, we’ll create a class SquarePipe which implements the PipeTransform interface and we’ll decorate it with Pipe decorator.

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'square'
})
export class SquarePipe implements PipeTransform {
 
}

The value of name property is used to refer to the pipe inside the template.

Now, we’ll create a method called transform which accepts the value that needs to be processed and returns it’s square.

transform (value: number): number {
    if (isNaN(value)) {
      return value;
    }

    return value * value;
  }

The if condition determines if the value to be processed is a number. If not we’ll return the original value.

The final code is as follows:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'square'
})
export class SquarePipe implements PipeTransform {
  transform (value: number): number {
    if (isNaN(value)) {
      return value;
    }

    return value * value;
  }
}

Before using the pipe, we need to make our Angular app aware of the pipe. We can do that by adding pipe to our declarations array in the module.

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

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SquarePipe } from './square.pipe';

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

You can use our custom pipe in following way.

{{ num | square }}

Passing arguments to the pipe

You can also pass parameters to your pipe. For example, we’re passing city name as parameter to greeter pipe.

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'greeter'
})
export class GreeterPipe implements PipeTransform {
  transform (value: string, city: string): string {

    return `Hello ${value}! Welcome to ${city}.`
  }
}

You can use the above pipe in following way.

{{ 'John' | greeter : 'Pune' }}

The above code will produce following output.

Hello John! Welcome to Pune.

I hope you found this post about Angular Pipes useful. If you have any query or feedback feel free to drop a comment.

Useful Read: Inject Document In Angular

How To Inject Document Object In Angular Service

In this short post, we’re going to understand how we can inject document object within an Angular service.

Angular comes bundled with a DI token that refers to the document object. We can use the @Inject decorator to inject this token within our service or component.

import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';

@Injectable()
export class MyCustomService {
  constructor(@Inject(DOCUMENT) private document: Document) {
  
  }
}

Must Read: Var, let and const- what’s the difference?