Steps to reproduce:
npx @angular/cli@17.3.8 new ng-toaster
? Which stylesheet format would you like to use? Sass (SCSS) [ https://sass-lang.com/documentation/syntax#scss]
? Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)? Yes
√ Packages installed successfully.
npm install ngx-toastr --save
Installs ("ngx-toastr": "^19.0.0",)
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideClientHydration } from '@angular/platform-browser';
import { routes } from './app.routes';
import { provideAnimations } from '@angular/platform-browser/animations';
import { provideToastr } from 'ngx-toastr';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideClientHydration(),
provideAnimations(),
provideToastr({
timeOut: 2000,
progressBar: true,
progressAnimation: 'decreasing',
closeButton: true
})
]
};
@import 'ngx-toastr/toastr';
import { Component, inject } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { ToastrService } from 'ngx-toastr';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
title = 'ng-toaster';
private readonly _toasterService = inject(ToastrService);
constructor() {
this._toasterService.success('Close already!');
}
clear(){
console.log(`Clear`);
this._toasterService.clear();
}
}
<h1>{{title}}</h1>
<p>Toaster please close</p>
<button type="button" (click)="clear()">Clear</button>
<router-outlet />
npm run start
I tried setting the timeOut both on the provideToastr() but also in the AppComponent (this._toasterService.success) but it will not work. Clearing messages will also not work with this._toasterService.clear();
The toaster is also getting opened in SSR, which is causing this weird bug.
You can create a toaster wrapper service, that opens the popup when you are only on the browser. For this we use isPlatformBrowser
.
import { isPlatformBrowser } from '@angular/common';
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
import { ActiveToast, ToastrService } from 'ngx-toastr';
@Injectable({
providedIn: 'root',
})
export class ToasterManagerService {
isBrowser = false;
constructor(
private readonly _toasterService: ToastrService,
@Inject(PLATFORM_ID) private platformId: Object
) {
this.isBrowser = isPlatformBrowser(platformId);
}
success(message: string) {
if (!this.isBrowser) return;
return this._toasterService.success(message);
}
clear(toastId: number) {
if (!this.isBrowser) return;
this._toasterService.clear(toastId);
}
}
Then we can call the methods from this service on the component and it should start working.
import { afterNextRender, Component, inject, Optional } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { ActiveToast, ToastrModule, ToastrService } from 'ngx-toastr';
import { ToasterManagerService } from './toaster-service.service';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, ToastrModule],
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
})
export class AppComponent {
title = 'ng-toaster';
private readonly toasterManager = inject(ToasterManagerService);
toastId!: number;
constructor() {
const toast = this.toasterManager.success('Close already!') || null;
if (toast) {
this.toastId = toast.toastId;
}
}
clear() {
console.log(`Clear`);
this.toasterManager.clear(this.toastId);
}
}
cd test
-> npm i
-> npm run start