You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Bootstrap 5.2与Angular 14实现右上角Toast通知及自定义服务

Angular 14 自定义Toast通知实现方案

方案一:基于Bootstrap 5.2实现

1. 安装依赖

首先安装Bootstrap:

npm install bootstrap

在angular.json的styles数组中添加Bootstrap CSS:

"styles": [
  "node_modules/bootstrap/dist/css/bootstrap.min.css",
  "src/styles.css"
]

2. 创建独立Toast组件

生成一个独立组件:

ng generate component toast --standalone

toast.component.ts

import { Component, Input, Output, EventEmitter } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-toast',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './toast.component.html',
  styleUrls: ['./toast.component.css']
})
export class ToastComponent {
  @Input() title!: string;
  @Input() message!: string;
  @Input() type!: 'success' | 'warning' | 'error' | 'info';
  @Output() close = new EventEmitter<void>();

  dismiss() {
    this.close.emit();
  }
}

toast.component.html

<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true" [ngClass]="type">
  <div class="toast-header">
    <strong class="me-auto">{{ title }}</strong>
    <button type="button" class="btn-close" aria-label="Close" (click)="dismiss()"></button>
  </div>
  <div class="toast-body">
    {{ message }}
  </div>
</div>

toast.component.css

.toast {
  margin-bottom: 1rem;
  min-width: 300px;
}

.toast.success .toast-header {
  background-color: #d1e7dd;
  color: #0f5132;
  border-bottom: 1px solid #badbcc;
}

.toast.warning .toast-header {
  background-color: #fff3cd;
  color: #856404;
  border-bottom: 1px solid #ffeaa7;
}

.toast.error .toast-header {
  background-color: #f8d7da;
  color: #721c24;
  border-bottom: 1px solid #f5c6cb;
}

.toast.info .toast-header {
  background-color: #d1ecf1;
  color: #0c5460;
  border-bottom: 1px solid #bee5eb;
}

3. 创建Toast服务

生成服务:

ng generate service toast

toast.service.ts

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

export interface Toast {
  id: string;
  title: string;
  message: string;
  type: 'success' | 'warning' | 'error' | 'info';
}

@Injectable({
  providedIn: 'root'
})
export class ToastService {
  private toastsSubject = new BehaviorSubject<Toast[]>([]);
  toasts$ = this.toastsSubject.asObservable();

  constructor() { }

  private addToast(title: string, message: string, type: 'success' | 'warning' | 'error' | 'info') {
    const id = Math.random().toString(36).substring(2, 15);
    const toast: Toast = { id, title, message, type };
    this.toastsSubject.next([...this.toastsSubject.value, toast]);

    // 5秒后自动关闭
    setTimeout(() => this.removeToast(id), 5000);
  }

  showSuccessToast(title: string, message: string) {
    this.addToast(title, message, 'success');
  }

  showWarningToast(title: string, message: string) {
    this.addToast(title, message, 'warning');
  }

  showErrorToast(title: string, message: string) {
    this.addToast(title, message, 'error');
  }

  showInfoToast(title: string, message: string) {
    this.addToast(title, message, 'info');
  }

  removeToast(id: string) {
    this.toastsSubject.next(this.toastsSubject.value.filter(toast => toast.id !== id));
  }
}

4. 添加Toast容器到根组件

在app.component.html中添加Toast容器:

<div class="toast-container position-fixed top-0 end-0 p-3">
  <app-toast 
    *ngFor="let toast of toasts$ | async"
    [title]="toast.title"
    [message]="toast.message"
    [type]="toast.type"
    (close)="toastService.removeToast(toast.id)"
  ></app-toast>
</div>

<!-- 示例按钮 -->
<button class="btn btn-success" (click)="showSuccess()">显示成功Toast</button>
<button class="btn btn-warning" (click)="showWarning()">显示警告Toast</button>
<button class="btn btn-danger" (click)="showError()">显示错误Toast</button>
<button class="btn btn-info" (click)="showInfo()">显示信息Toast</button>

在app.component.ts中导入必要模块和服务:

import { Component } from '@angular/core';
import { ToastComponent } from './toast/toast.component';
import { ToastService } from './toast.service';
import { AsyncPipe } from '@angular/common';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [ToastComponent, AsyncPipe],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  toasts$ = this.toastService.toasts$;

  constructor(public toastService: ToastService) { }

  showSuccess() {
    this.toastService.showSuccessToast('Success toast title', 'This is a success toast message.');
  }

  showWarning() {
    this.toastService.showWarningToast('Warning toast title', 'This is a warning toast message.');
  }

  showError() {
    this.toastService.showErrorToast('Error toast title', 'This is an error toast message.');
  }

  showInfo() {
    this.toastService.showInfoToast('Info toast title', 'This is an info toast message.');
  }
}

方案二:纯自定义实现(无需Bootstrap)

如果不想依赖Bootstrap,只需修改Toast组件的HTML和CSS:

修改toast.component.html

<div class="toast" [ngClass]="type">
  <div class="toast-header">
    <strong class="me-auto">{{ title }}</strong>
    <button type="button" class="btn-close" aria-label="Close" (click)="dismiss()">&times;</button>
  </div>
  <div class="toast-body">
    {{ message }}
  </div>
</div>

修改toast.component.css

.toast {
  position: relative;
  padding: 1rem;
  margin-bottom: 1rem;
  border-radius: 0.25rem;
  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
  min-width: 300px;
}

.toast-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}

.btn-close {
  background: none;
  border: none;
  font-size: 1.25rem;
  cursor: pointer;
  padding: 0;
  line-height: 1;
  color: inherit;
}

.toast.success {
  background-color: #d1e7dd;
  color: #0f5132;
  border-left: 4px solid #198754;
}

.toast.warning {
  background-color: #fff3cd;
  color: #856404;
  border-left: 4px solid #ffc107;
}

.toast.error {
  background-color: #f8d7da;
  color: #721c24;
  border-left: 4px solid #dc3545;
}

.toast.info {
  background-color: #d1ecf1;
  color: #0c5460;
  border-left: 4px solid #0dcaf0;
}

修改app.component.html中的容器

<div class="toast-container">
  <app-toast 
    *ngFor="let toast of toasts$ | async"
    [title]="toast.title"
    [message]="toast.message"
    [type]="toast.type"
    (close)="toastService.removeToast(toast.id)"
  ></app-toast>
</div>

<!-- 示例按钮 -->
<button (click)="showSuccess()">显示成功Toast</button>
<button (click)="showWarning()">显示警告Toast</button>
<button (click)="showError()">显示错误Toast</button>
<button (click)="showInfo()">显示信息Toast</button>

添加容器样式到app.component.css

.toast-container {
  position: fixed;
  top: 1rem;
  right: 1rem;
  z-index: 1050;
}

使用说明

在任意组件中,只需注入ToastService即可调用对应的方法显示Toast:

import { ToastService } from './toast.service';

constructor(private toastService: ToastService) { }

// 示例调用
showSuccess() {
  this.toastService.showSuccessToast('操作成功', '数据已保存');
}

内容的提问来源于stack exchange,提问作者Atique Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:00:46