Açıklama Yok
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

toast.service.ts 2.7KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import { Injectable, ComponentRef, createComponent, ApplicationRef, Injector } from '@angular/core';
  2. import { ToastComponent } from '../components/toast/toast.component';
  3. import { ToastType, ToastOptions } from '../models/toast.types';
  4. @Injectable({
  5. providedIn: 'root'
  6. })
  7. export class ToastService {
  8. private toasts: ComponentRef<ToastComponent>[] = [];
  9. private container: HTMLElement | null = null;
  10. constructor(
  11. private appRef: ApplicationRef,
  12. private injector: Injector
  13. ) {}
  14. private ensureContainer() {
  15. if (!this.container) {
  16. this.container = document.createElement('div');
  17. this.container.className = 'toast-container';
  18. // 添加一些内联样式
  19. this.container.style.position = 'fixed';
  20. this.container.style.top = '20px';
  21. this.container.style.right = '20px';
  22. this.container.style.zIndex = '9999';
  23. this.container.style.display = 'flex';
  24. this.container.style.flexDirection = 'column';
  25. this.container.style.alignItems = 'flex-end';
  26. document.body.appendChild(this.container);
  27. }
  28. }
  29. show(message: string, options?: ToastOptions) {
  30. this.ensureContainer();
  31. const type = options?.type || 'info';
  32. const duration = options?.duration || 3000;
  33. const toastRef = createComponent(ToastComponent, {
  34. environmentInjector: this.appRef.injector,
  35. elementInjector: this.injector
  36. });
  37. // 设置输入属性(类型安全)
  38. toastRef.instance.message = message;
  39. toastRef.instance.type = type;
  40. // 添加到DOM
  41. this.container?.appendChild(toastRef.location.nativeElement);
  42. this.appRef.attachView(toastRef.hostView);
  43. // 存储引用
  44. this.toasts.push(toastRef);
  45. // 自动移除
  46. setTimeout(() => {
  47. this.removeToast(toastRef);
  48. }, duration);
  49. return toastRef;
  50. }
  51. success(message: string, options?: Omit<ToastOptions, 'type'>) {
  52. return this.show(message, { ...options, type: 'success' });
  53. }
  54. error(message: string, options?: Omit<ToastOptions, 'type'>) {
  55. return this.show(message, { ...options, type: 'error' });
  56. }
  57. info(message: string, options?: Omit<ToastOptions, 'type'>) {
  58. return this.show(message, { ...options, type: 'info' });
  59. }
  60. warning(message: string, options?: Omit<ToastOptions, 'type'>) {
  61. return this.show(message, { ...options, type: 'warning' });
  62. }
  63. private removeToast(toastRef: ComponentRef<ToastComponent>) {
  64. const index = this.toasts.indexOf(toastRef);
  65. if (index > -1) {
  66. this.toasts.splice(index, 1);
  67. this.appRef.detachView(toastRef.hostView);
  68. toastRef.destroy();
  69. }
  70. }
  71. clearAll() {
  72. this.toasts.forEach(toastRef => {
  73. this.appRef.detachView(toastRef.hostView);
  74. toastRef.destroy();
  75. });
  76. this.toasts = [];
  77. }
  78. }