This guide help Angular Universal, a technology that renders dynamic content on the server in your Angular applications.
A normal Angular universal application view source does not display dynamic content in angular universal, rendering pages in the DOM before api call happened in component. Angular Universal executes on the server, generating static application pages that later get bootstrapped on the client. For rendering dynamic content in angular universal you have to resolve dynamic data before navigate to the route path.
Angular Universal and Server Side Rendering of dynamic content step by step
This example will show you one route path that resolve your dynamic content from your backend.
Step:1=> AppRoutingModule Setup
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LayoutComponent } from './layouts';
import { RouteResolver} from './resolvers';
const appRoutes: Routes = [
{
path: '',
component: LayoutComponent,
children: [
{
path: '',
resolve: { result: RouteResolver },
data: {},
loadChildren: () =>
import(
'./pages/home-page/homePage.module'
).then((m) => m.HomePageModule)
}
]
}
]
@NgModule({
imports: [
RouterModule.forRoot(appRoutes, {
initialNavigation: 'enabled',
onSameUrlNavigation: 'reload'
})
],
exports: [RouterModule]
})
export class AppRoutingModule {}
Step:2 => Route Resolver service setup
import { map, Observable } from 'rxjs';
import { HttpService } from './http';
import { Injectable } from '@angular/core';
import {
Resolve,
RouterStateSnapshot,
ActivatedRouteSnapshot
} from '@angular/router';
@Injectable()
export class RouteResolver implements Resolve<any> {
constructor(private _http: HttpService) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any> | undefined {
const param = route.data;
return this._http.get('homePageContent']).pipe(
map((result) => {
return result.response.dataset;
})
);
}
}
Step: 3 => Dynamic data display in component
@Component({
selector: 'home-page',
templateUrl: './home-page.component.html',
styleUrls: ['./home-page.component.scss']
})
export class HomePageComponent implements OnInit {
public homePageContent:any;
constructor(private _route: ActivatedRoute
) {
}
ngOnInit(): void {
this.homePageContent = this._route.snapshot.data['result'];
}
}
Step: 4 => Common Http Service setup
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { environment } from '@env/environment';
import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http';
import FormData from 'form-data';
export type IRequestType = 'DELETE' | 'GET' | 'HEAD' | 'POST' | 'PATCH' | 'PUT';
export interface IRequestOptions {
useUrlPrefix?: boolean;
headers?: any;
observe?: 'body' | 'events' | 'response';
reportProgress?: boolean;
}
export function isObject(arg: any) {
return typeof arg === 'object' && arg !== null && !(arg instanceof Array)
? arg
: false;
}
@Injectable({
providedIn: 'root',
})
export class HttpService {
constructor(private _http: HttpClient) {}
private request(
method: IRequestType,
url: string,
params?: Object | null,
options?: IRequestOptions
): Observable<any> {
let data;
let reqUrl = url;
let request$: Observable<any>;
let reqOptions: any = { useUrlPrefix: true };
if (isObject(options)) reqOptions = Object.assign(reqOptions, options);
// Creating request headers
if (reqOptions.headers) {
reqOptions.headers = new HttpHeaders(reqOptions.headers);
}
// Assigninig params
if (params !== null && isObject(params)) {
if (params instanceof FormData) {
data = params;
reqOptions.reportProgress = reqOptions.reportProgress || true;
}
data = params;
}
// Checking url prefix
if (reqOptions.useUrlPrefix === true) {
const urlHost =
urlType === 'D' ? environment.host : environment.hostBooking;
reqUrl = urlHost + '/' + url;
}
reqOptions.body = data;
reqOptions.observe = reqOptions.observe || 'body';
// Final Request
request$ = this._http.request(method, reqUrl, reqOptions);
request$.pipe(
map((response: HttpResponse<any>) => {
const responseObject = response.body;
return responseObject;
})
);
return request$;
}
public post(
url: string,
params?: any,
options?: IRequestOptions
) {
return this.request('POST', url, params, options);
}
public get(url: string, options?: IRequestOptions) {
return this.request('GET', url, null, options);
}
}
Step: 5 => AppModule setup
import { NgModule } from '@angular/core';
import {
BrowserModule,
BrowserTransferStateModule
} from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { TransferHttpCacheModule } from '@nguniversal/common';
@NgModule({
declarations: [AppComponent],
imports: [
AppRoutingModule,
TransferHttpCacheModule,
BrowserAnimationsModule,
BrowserTransferStateModule,
BrowserModule.withServerTransition({ appId: 'serverApp' })
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
Related Articles
- API REQUEST IS CALLING TWICE IN ANGULAR UNIVERSAL
- HOW TO DEPLOY ANGULAR UNIVERSAL TO PRODUCTION?
- WINDOW IS NOT DEFINED IN ANGULAR UNIVERSAL?
- LOCALSTORAGE IS NOT DEFINED IN ANGULAR UNIVERSAL?
- ANGULAR UNIVERSAL SERVER SIDE RENDERING
- HOW TO SET ANGULAR CANONICAL URL LINK
- DYNAMICALLY SEO META TAGS SETUP IN ANGULAR
References
Thank you! Like our Facebook page to get more updates.