Angular 17.3.8独立模式SSR下ngx-toastr无法关闭该如何解决
Angular 17.3.8独立模式SSR环境下ngx-toastr无法关闭
在Angular 17.3.8独立模式SSR环境中使用ngx-toastr@19.0.0时,出现以下异常:
- 提示框的
timeOut设置不生效,进度条走完后提示框仍不消失 - 调用
toastrService.clear()无法清除提示框
复现步骤
1. 创建Angular SSR应用
npx @angular/cli@17.3.8 new ng-toaster ? Which stylesheet format would you like to use? Sass (SCSS) ? Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)? Yes
2. 安装ngx-toastr
npm install ngx-toastr --save
安装版本为"ngx-toastr": "^19.0.0"
3. 配置app.config.ts
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 }) ] };
4. 引入样式到styles.scss
@import 'ngx-toastr/toastr';
5. 修改app.component.ts
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(); } }
6. 修改app.component.html
<h1>{{title}}</h1> <p>Toaster please close</p> <button type="button" (click)="clear()">Clear</button> <router-outlet />
7. 运行应用
npm run start
问题现象
- 访问
http://localhost:4200/,提示框出现,进度条正常减少,但不会自动消失 - 点击「Clear」按钮,控制台打印
Clear,但提示框仍不消失
解决方案
问题根源是SSR环境下,toastr在服务端被渲染出来,但客户端的ToastrService实例无法关联到服务端生成的DOM元素,导致定时器和清除操作都无法作用于已渲染的提示框。
方法1:仅在浏览器环境中显示toastr
使用isPlatformBrowser判断当前环境,只在客户端初始化后显示提示框:
import { Component, inject, OnInit, PLATFORM_ID } from '@angular/core'; import { isPlatformBrowser } from '@angular/common'; 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 implements OnInit { title = 'ng-toaster'; private readonly _toasterService = inject(ToastrService); private readonly _platformId = inject(PLATFORM_ID); ngOnInit(): void { // 仅在浏览器环境中显示toastr if (isPlatformBrowser(this._platformId)) { this._toasterService.success('Close already!'); } } clear(){ console.log(`Clear`); this._toasterService.clear(); } }
方法2:延迟到客户端 hydration 完成后执行
利用Angular 16+支持的AfterNextRender钩子,确保在客户端完全初始化后再调用toastr:
import { Component, inject, AfterNextRender } 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 implements AfterNextRender { title = 'ng-toaster'; private readonly _toasterService = inject(ToastrService); ngAfterNextRender(): void { // 在客户端首次渲染完成后显示toastr this._toasterService.success('Close already!'); } clear(){ console.log(`Clear`); this._toasterService.clear(); } }
原理说明
在SSR模式下,服务端会先渲染页面并生成toastr的DOM元素,但此时客户端的ToastrService还未初始化,无法绑定到这些服务端生成的元素上。通过限制toastr仅在客户端环境中创建,确保DOM元素和服务实例一一对应,这样定时器和清除操作就能正常工作。
内容的提问来源于stack exchange,提问作者Dimitris
相关产品推荐
相关产品推荐

