Introduction to BidiModule in Angular CDK
Angular CDK provides great common features that we developers can use to make our applications better. They can be amazing base for our future components.
Motivation
You may want support different languages in your application and one of this language can be RTL, such as: Arabic, Hebrew or Persian. For that, your application need to know which current direction in selected language is used RTL or LTR.
Using BidiModule
Firstly, we need to install package to use it in your existing Angular application by using this command:
ng add @angular/material
This command automatically update your package.json file and install all required dependencies including @angular/cdk.
Next step is importing BidiModule into your AppModule:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';import { BidiModule } from '@angular/cdk/bidi';import { AppComponent } from './app.component';@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
BidiModule,
],
bootstrap: [
AppComponent,
],
})
export class AppModule {}
Okay, we setup our project to using BidiModule features!
Querying current direction
We can query which current direction document has by injecting Directionality service and reading its value property.
import { Component } from '@angular/core';import { Directionality, Direction } from '@angular/cdk/bidi';
@Component({
selector: 'app',
template: '<p>Current direction is: {{ direction }}!</p>',
})
export class AppComponent {
public constructor(
private readonly dir: Directionality,
) {
this.direction = dir.value;
} public direction: Direction;
}
In this case we inject Directionality and request its value property to assign our direction property for displaying it in template.
Direction type can have only two possible values:
export type Direction = 'ltr' | 'rtl';
Directionality service under the hood injects DOCUMENT token to get current’s document dir attribute on body or documentElement properties which is <body> and <html> tags. If dir attribute exists at <body> element then <html> element is ignored and if dir attribute are not presented or doesn’t match with one of two possible values of Direction type, default value assigned as ltr.
Subscribing to direction changes
You can also track dir attribute changes subscribing to change EventEmitter<Direction> of Directionality service!
import { Component } from '@angular/core';
import { Observable } from 'rxjs';import { Directionality, Direction } from '@angular/cdk/bidi';@Component({
selector: 'app',
template: '<p>Current direction is: {{ direction | async }}!</p>',
})
export class AppComponent {
public constructor(
private readonly dir: Directionality,
) {
this.direction = dir.change;
} public direction: Observable<Direction>;
}
We use AsyncPipe to subscribe into Observable, so we don’t need think about unsubscription and write another boilerplate code. We just get current document direction and displaying it in our component template.
Another great use case
We can easily add dir attribute to our document.
import { Component, Inject, OnDestroy } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';
import { Subscription } from 'rxjs';import { Directionality, Direction } from '@angular/cdk/bidi';
@Component({
selector: 'app',
template: '<some-cmp></some-cmp>',
})
export class AppComponent implements OnDestroy {
public constructor(
private readonly dir: Directionality,
@Inject(DOCUMENT) private readonly document: Document,
) {
this.direction = dir.change.subscribe((direction: Direction) =>
{
this.document.dir = direction;
});
} public direction$: Subscription = Subscription.EMPTY; public ngOnDestroy(): void {
this.direction$.unsubcribe();
}
}
Conclusion
Big thanks for reading this article! I hope this was helpful for you! Another articles will be coming!