Angular structural directive for sharing data as local variable into html component template.
Sometime there is a need to share data into component template as local variable. This structural directive create local context of variable that can be used into html template.
See the stackblitz demo.
✅ Observable support
✅ Async pipe support
✅ NgModel support
✅ Type casting
Step 1: install ng-let
npm i ng-let
Step 2: Import NgLetModule
into your app module or imports of standalone component, eg.:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { NgLetModule } from 'ng-let';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
NgLetModule,
],
providers: [],
bootstrap: [AppComponent],
],
})
export class AppModule { }
Step 3: usage, eg.:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<ng-container *ngLet="(num1 + num2) as total"> <!-- single computation -->
<div>
1: {{ total }} <!-- 3 -->
</div>
<div>
2: {{ total }} <!-- 3 -->
</div>
</ng-container>
`,
})
export class AppComponent {
num1: number = 1;
num2: number = 2;
}
or with the implicit syntax:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<ng-container *ngLet="(num1 + num2); let total"> <!-- single computation -->
<div>
1: {{ total }} <!-- 3 -->
</div>
<div>
2: {{ total }} <!-- 3 -->
</div>
</ng-container>
`,
})
export class AppComponent {
num1: number = 1;
num2: number = 2;
}
Below there are some examples of use case.
Example of use with observable, eg.:
import { Component } from '@angular/core';
import { defer, Observable, timer } from 'rxjs';
@Component({
selector: 'app-root',
template: `
<ng-container *ngLet="timer$ | async as time"> <!-- single subscription -->
<div>
1: {{ time }}
</div>
<div>
2: {{ time }}
</div>
</ng-container>
`,
})
export class AppComponent {
timer$: Observable<number> = defer(() => timer(3000, 1000));
}
or with the implicit syntax:
import { Component } from '@angular/core';
import { defer, Observable, timer } from 'rxjs';
@Component({
selector: 'app-root',
template: `
<ng-container *ngLet="timer$ | async; let time"> <!-- single subscription -->
<div>
1: {{ time }}
</div>
<div>
2: {{ time }}
</div>
</ng-container>
`,
})
export class AppComponent {
timer$: Observable<number> = defer(() => timer(3000, 1000));
}
Example of use with signal, eg.:
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<ng-container *ngLet="mySignal() as time"> <!-- single computation -->
<div>
1: {{ time }}
</div>
<div>
2: {{ time }}
</div>
</ng-container>
`,
})
export class AppComponent {
mySignal = signal(1);
constructor() {
setInterval(() => this.mySignal.update(value => value + 1), 1000)
}
}
or with the implicit syntax:
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<ng-container *ngLet="mySignal(); let time"> <!-- single computation -->
<div>
1: {{ time }}
</div>
<div>
2: {{ time }}
</div>
</ng-container>
`,
})
export class AppComponent {
mySignal = signal(1);
constructor() {
setInterval(() => this.mySignal.update(value => value + 1), 1000)
}
}
This is an open-source project. Star this repository, if you like it, or even donate. Thank you so much!
I have published some other Angular libraries, take a look:
- NgSimpleState: Simple state management in Angular with only Services and RxJS
- NgHttpCaching: Cache for HTTP requests in Angular application
- NgGenericPipe: Generic pipe for Angular application for use a component method into component template.
- NgForTrackByProperty: Angular global trackBy property directive with strict type checking