An Interest In:
Web News this Week
- April 2, 2024
- April 1, 2024
- March 31, 2024
- March 30, 2024
- March 29, 2024
- March 28, 2024
- March 27, 2024
Building Reactive Angular Templates with NgRx Component
In this article, we'll look into the @ngrx/component
library used to build reactive Angular templates in a performant way. It contains a set of declarables that are primarily used for rendering observable events and can work in both zone-full and zone-less mode.
Installation
To install the @ngrx/component
package, run one of the following commands:
// Angular CLIng add @ngrx/component// NPMnpm i @ngrx/component// Yarnyarn add @ngrx/component
Push Pipe
The ngrxPush
pipe is used for displaying observable values in the template. To use it, import the PushModule
to an Angular module or standalone component:
import { PushModule } from '@ngrx/component';@Component({ // ... other metadata standalone: true, imports: [ // ... other imports PushModule, ],})export class ProductDetailsComponent { readonly product$ = this.store.select(selectActiveProduct); constructor(private readonly store: Store) {}}
PushModule
is available since version 14. If you're using an older version of the@ngrx/component
package, import theReactiveComponentModule
.
The ngrxPush
pipe is an alternative to the async
pipe and can be used in the following way:
<ngrx-product-form [product]="product$ | ngrxPush"></ngrx-product-form>
Similar to the async
pipe, the ngrxPush
pipe returns the last emitted value of the passed observable or undefined
if there are no emitted values. However, there are two key differences compared to the async
pipe:
- The
ngrxPush
pipe will not trigger change detection when an observable emits the same values in a row. - The
ngrxPush
pipe will trigger change detection when an observable emits a new value in zone-less mode.
Since version 14, the
@ngrx/component
package uses the global rendering strategy in both zone-full and zone-less mode. In previous versions, it used the native local rendering strategy in zone-less mode, which caused performance issues.
Let Directive
The *ngrxLet
directive is used for rendering observable events in the template. To use it, import the LetModule
to an Angular module or standalone component:
import { LetModule } from '@ngrx/component';@Component({ // ... other metadata standalone: true, imports: [ // ... other imports LetModule, ],})export class ProductListComponent { readonly products$ = this.productsService.getProducts({ limit: 10 }); readonly totalCount$ = this.productsService.getTotalCount(); constructor(private readonly productsService: ProductsService) {}}
LetModule
is available since version 14. If you're using an older version of the@ngrx/component
package, import theReactiveComponentModule
.
The *ngrxLet
directive can be used in the following way:
<ng-container *ngrxLet="totalCount$ as totalCount"> <h2>Products ({{ totalCount }})</h2> <p *ngIf="!totalCount" class="info-alert"> There are no products. </p></ng-container>
At first, it seems that we can achieve the same result using the *ngIf
directive and async
pipe:
<ng-container *ngIf="totalCount$ | async as totalCount"> <h2>Products ({{ totalCount }})</h2> <p *ngIf="!totalCount" class="info-alert"> There are no products. </p></ng-container>
However, the *ngIf
directive will only create an embedded view if the totalCount
is not zero (truthy value), but not if it is zero (falsy value). On the other hand, the *ngrxLet
directive will create an embedded view when an observable emits a value, regardless of whether it is truthy or falsy.
Tracking Different Observable Events
The *ngrxLet
directive provides the ability to display different content based on the current observable state. For example, we can display an error alert if an observable emits the error event:
<ng-container *ngrxLet="products$ as products; $error as error"> <ngrx-product-card *ngFor="let product of products" [product]="product" ></ngrx-product-card> <p *ngIf="error" class="error-alert">{{ error.message }}</p></ng-container>
Displaying thrown error is possible since version 14. In previous versions, the value of
$error
istrue
when the passed observable emits the error event.
In addition to error, we can also track the complete event:
<ng-container *ngrxLet="saveProgress$ as progress; $complete as complete"> <mat-progress-spinner [value]="progress" mode="determinate" ></mat-progress-spinner> <p *ngIf="complete" class="success-alert"> Product is successfully saved! </p></ng-container>
Using Suspense Template
Also, there is an option to pass the suspense template to the *ngrxLet
directive:
<ng-container *ngrxLet="products$ as products; suspenseTpl: loading"> <ngrx-product-card *ngFor="let product of products" [product]="product" ></ngrx-product-card></ng-container><ng-template #loading> <mat-spinner></mat-spinner></ng-template>
The suspense template will be rendered when the passed observable is in a suspense state. In the example above, the loading spinner will be displayed until the products$
observable emits a list of products. When this happens, the loading spinner will be removed from the DOM and products will be displayed.
Using suspense template with the
*ngrxLet
directive is available since version 14.
Using Aliases for Non-Observable Values
In addition to observables and promises, the *ngrxLet
directive can also accept static (non-observable) values as an input argument. This feature provides the ability to create readable templates by using aliases for deeply nested properties:
<ng-container *ngrxLet="productForm.controls.price as price"> <input type="number" [formControl]="price" /> <ng-container *ngIf="price.errors && (price.touched || price.dirty)"> <p *ngIf="price.errors.required">Price is a required field.</p> <p *ngIf="price.errors.min">Price cannot be a negative number.</p> </ng-container></ng-container>
Passing non-observable values to the
*ngrxLet
directive is available since version 14.
Summary
Many new and powerful features have been added in version 14:
- Separate modules for
LetDirective
andPushPipe
- Displaying emitted error in the template
- Using aliases for non-observable values
- Handling suspense state in the template
- Strong typing for
LetDirective
andPushPipe
Also, this library has been almost completely rewritten for better performance. If you haven't used it before, give it a try and let us know your impressions!
By the way, the @ngrx/component
package recently reached 30k downloads per week on NPM!
Resources
Peer Reviewers
Big thanks to Brandon Roberts and Tim Deschryver for giving me helpful suggestions on this article!
Original Link: https://dev.to/ngrx/building-reactive-angular-templates-with-ngrx-component-4m1e
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To