Introducing TransferState
Say Hello to TransferState, a key-value registry that is passed along with the application bundle, from the server-side angular to the browser-side part of the application. In this lesson you will learn how frontend can get to know what backend has already do (ie retrieving data from DB); thanks to that you can avoid repeating those steps and offload your application backend.
First, you need to provide the modules that contain the TransferState
service.
Update src/app/app.module.ts by adding BrowserTransferStateModule
to the @angular/platform-browser
import statement:
import {
BrowserModule,
BrowserTransferStateModule,
} from '@angular/platform-browser';
Add it to the imports
array of AppModule
:
imports: [
BrowserModule.withServerTransition({
appId: 'serverApp',
}),
AppRoutingModule,
HttpClientModule,
ReactiveFormsModule,
BrowserTransferStateModule,
],
Update src/app/app.server.module.ts by adding ServerTransferStateModule
to the @angular/platform-server
import statement:
import {
ServerModule,
ServerTransferStateModule,
} from '@angular/platform-server';
Add it to the imports
array of AppServerModule
:
imports: [
AppModule,
ServerModule,
ServerTransferStateModule,
],
Adjusting product services#
You need to prepare keys that you will use in services responsible for retrieving products. Create a new file, src/model/state-keys.ts, and add the following code:
import {
makeStateKey,
StateKey,
} from '@angular/platform-browser';
import { Product } from './product.model';
export class StateKeys {
public static get PRODUCTS(): StateKey<Product[]> {
return makeStateKey<Product[]>('products');
}
public static get PRODUCT(): StateKey<Product> {
return makeStateKey<Product>('product');
}
}
Import TransferState
and StateKeys
, and then add the tap
operator to the rxjs
import statement in src/app/products-server.service.ts:
import { map, tap } from 'rxjs/operators';
import { TransferState } from '@angular/platform-browser';
import { StateKeys } from 'src/model/state-keys';
Inject the TransferState
service, then update the getProducts()
and getProduct(productId)
methods to set entries to the TransferState
registry when data is returned from the database. You can do it by introducing the tap
operator into the observables returned by those methods:
constructor(
private ms: MongoService,
private ts: TransferState
) {}
public getProducts(): Observable<Product[]> {
return from(
this.ms.retrieveFromDb<Product>('products', {
description: 0,
})
).pipe(
tap((products) =>
this.ts.set(StateKeys.PRODUCTS, products)
)
);
}
public getProduct(
productId: string
): Observable<Product> {
return from(
this.ms.retrieveFromDb<Product>('products', {}, {
_id: ObjectId(productId),
})
).pipe(
map((products) => products[0]),
tap((product) =>
this.ts.set(StateKeys.PRODUCT, product)
)
);
}
The browser side#
Now you need to retrieve data from the TransferState
registry in the browser. Adjust import statements in src/app/products.service.ts by adding the following entries:
This page is a preview of The newline Guide to Angular Universal