'How execute a piece of code only in the Browser using Angular Universal?
I have a piece of code that I want to execute only in the Browser, I know about the PlatformId so I made a Service:
I'm using Angular 12.2.13
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class ApplicationService {
public applicationLoaded$ = new BehaviorSubject<boolean>(undefined as any);
constructor(@Inject(PLATFORM_ID) private platformId: Object) {}
get isBrowser(): boolean {
return isPlatformBrowser(this.platformId);
}
get isServer(): boolean {
return isPlatformServer(this.platformId);
}
set currentApplicationLoadedValue(loaded: boolean) {
this.applicationLoaded$.next(loaded);
}
get currentApplicationLoadedValue(): boolean {
return this.applicationLoaded$.value;
}
}
The problem is everytime I go to a page the ngOnInit execute 100% on Server and if I use something like this:
ngOnInit(): void {
if(this.appService.isBrowser) {
console.log("START");
}
}
ngAfterViewInit(): void {
if(this.appService.isBrowser) {
console.log("START");
}
}
ngAfterViewChecked(): void {
if(this.appService.isBrowser) {
console.log("START");
}
}
The name from my component is RestaurantsComponent, this is the first page that is loaded, so my ngOnInit, ngAfterViewInit and ngAfterViewChecked, when I test it, my page is loaded with no problem but I can't have this console showing console.log("START"); in my Browser, because they execute only on server.
This is my app.module.ts
@NgModule({
declarations: [AppComponent, AppBrownserRenderer, AppServerRenderer],
imports: [
BrowserModule.withServerTransition({ appId: 'menap-app' }),
BrowserAnimationsModule,
CommonModule,
/* GoogleTagManagerModule, */
AppRoutingModule,
HttpClientModule,
MatSnackBarModule,
/* SplashScreenModule,
NgbModalModule,
FormsModule,
ReactiveFormsModule,
MatSnackBarModule,
MatBottomSheetModule,
ScrollToModule.forRoot(), */
],
providers: [
ApplicationGuard,
SnackBarService,
CartService,
LocationService,
CategoryService,
CompanyService,
UtilsService,
ApplicationService,
StorageService,
AuthStorageService,
UserService,
OrderService,
/* {
provide: APP_INITIALIZER,
useFactory: appInitializer,
multi: true,
deps: [AuthService, CompanyService, ApplicationService],
}, */
/* {
provide: 'googleTagManagerId',
useFactory: GoogleTagManagerId,
deps: [TrafficService],
}, */
/* { provide: MatPaginatorIntl, useFactory: getPaginatorI18n },
{ provide: ErrorHandler, useClass: GlobalErrorHandler },
{ provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
{ provide: LOCALE_ID, useValue: 'pt' }, */
],
bootstrap: [AppComponent],
})
export class AppModule {}
So in app.component.html for testing purpose I do this:
<!-- <app-splash-screen></app-splash-screen> -->
<!-- <router-outlet></router-outlet> -->
<div *AppServerRenderer>
LOADING....
</div>
<div *AppBrownserRenderer>
FINISH LOADING....
</div>
So when my application got to app.component.ts they never change to BrowserMode so the load stop in LOADING...
What is happening? I made this same code in a clean Angular Project and works fine!
Solution 1:[1]
The method you have followed here is right. The conditions will only be activated once you are on the browser. But now as the code is running on browser you will not get any console output for server. Rather the output will be shown on the browser console.
Updated
I ran the codes you have given. I changed the @Injectable() to @Injectable({ providedIn: 'root' }) in the ApplicationService. Then provided it to the module in which the component is declared. Afterwards injected to service to the component.
ApplicationService
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ApplicationService {
public applicationLoaded$ = new BehaviorSubject<boolean>(undefined as any);
constructor(@Inject(PLATFORM_ID) private platformId: Object) {}
get isBrowser(): boolean {
return isPlatformBrowser(this.platformId);
}
get isServer(): boolean {
return isPlatformServer(this.platformId);
}
set currentApplicationLoadedValue(loaded: boolean) {
this.applicationLoaded$.next(loaded);
}
get currentApplicationLoadedValue(): boolean {
return this.applicationLoaded$.value;
}
}
Provided the service in the component's module
providers: [
ApplicationService
],
Component
constructor(private appService: ApplicationService) { }
ngOnInit(): void {
if(this.appService.isBrowser) {
console.log("On Init");
}
}
ngAfterViewInit(): void {
if(this.appService.isBrowser) {
console.log("On After View Init");
}
}
ngAfterViewChecked(): void {
if(this.appService.isBrowser) {
console.log("After view Checked");
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |


