diff --git a/docs/en/UI/Angular/Toaster-Service.md b/docs/en/UI/Angular/Toaster-Service.md index 3152eba1af..1dcb1b0153 100644 --- a/docs/en/UI/Angular/Toaster-Service.md +++ b/docs/en/UI/Angular/Toaster-Service.md @@ -47,7 +47,8 @@ const options: Partial = { closable: true, tapToDismiss: true, messageLocalizationParams: ['Demo', '1'], - titleLocalizationParams: [] + titleLocalizationParams: [], + iconClass: 'custom-icon-name'; }; this.toaster.error('AbpUi::EntityNotFoundErrorMessage', 'AbpUi::Error', options); @@ -60,6 +61,7 @@ const options: Partial = { - `yesText` is the text of the confirmation button. A localization key or localization object can be passed. Default value is `AbpUi::Yes`. - `messageLocalizationParams` is the interpolation parameters for the localization of the message. - `titleLocalizationParams` is the interpolation parameters for the localization of the title. +- `iconClass` is the CSS class assigned to the icon displayed on a toast overlay. With the options above, the toast overlay looks like this: diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/toast/toast.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/toast/toast.component.ts index fea028ebb6..4d842df02a 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/toast/toast.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/toast/toast.component.ts @@ -17,6 +17,12 @@ export class ToastComponent implements OnInit { } get iconClass(): string { + const { iconClass } = this.toast.options || {}; + + if (iconClass) { + return iconClass; + } + switch (this.toast.severity) { case 'success': return 'fa-check-circle'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/models/toaster.ts b/npm/ng-packs/packages/theme-shared/src/lib/models/toaster.ts index 5b8d07f108..7aabb583a1 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/models/toaster.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/models/toaster.ts @@ -10,6 +10,7 @@ export namespace Toaster { titleLocalizationParams?: string[]; id: any; containerKey?: string; + iconClass?: string; } export interface Toast { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts index 4e1b2830c7..3493d9c12a 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts @@ -1,7 +1,7 @@ import { CoreTestingModule } from '@abp/ng.core/testing'; import { NgModule } from '@angular/core'; import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest'; -import { timer } from 'rxjs'; +import { firstValueFrom, timer } from 'rxjs'; import { ToastContainerComponent } from '../components/toast-container/toast-container.component'; import { ToastComponent } from '../components/toast/toast.component'; import { ToasterService } from '../services/toaster.service'; @@ -34,7 +34,7 @@ describe('ToasterService', () => { test('should display a toast', async () => { service.show('MESSAGE', 'TITLE'); - await timer(0).toPromise(); + await firstValueFrom(timer(0)); service['containerComponentRef'].changeDetectorRef.detectChanges(); expect(selectToasterElement('.fa-exclamation-circle')).toBeTruthy(); @@ -51,7 +51,7 @@ describe('ToasterService', () => { `('should display $type toast', async ({ type, selector, icon }) => { service[type]('MESSAGE', 'TITLE'); - await timer(0).toPromise(); + await firstValueFrom(timer(0)); service['containerComponentRef'].changeDetectorRef.detectChanges(); expect(selectToasterContent(`.${toastClassPrefix}-title`)).toBe('TITLE'); expect(selectToasterContent(`.${toastClassPrefix}-message`)).toBe('MESSAGE'); @@ -63,7 +63,7 @@ describe('ToasterService', () => { service.show('MESSAGE_1', 'TITLE_1'); service.show('MESSAGE_2', 'TITLE_2'); - await timer(0).toPromise(); + await firstValueFrom(timer(0)); service['containerComponentRef'].changeDetectorRef.detectChanges(); const titles = document.querySelectorAll(`.${toastClassPrefix}-title`); @@ -77,7 +77,7 @@ describe('ToasterService', () => { service.show('MESSAGE'); service.remove(0); - await timer(0).toPromise(); + await firstValueFrom(timer(0)); service['containerComponentRef'].changeDetectorRef.detectChanges(); expect(selectToasterElement()).toBeNull(); @@ -87,7 +87,7 @@ describe('ToasterService', () => { service.show('MESSAGE'); service.clear(); - await timer(0).toPromise(); + await firstValueFrom(timer(0)); service['containerComponentRef'].changeDetectorRef.detectChanges(); expect(selectToasterElement()).toBeNull(); @@ -98,13 +98,22 @@ describe('ToasterService', () => { service.show('MESSAGE_2', 'TITLE_2', 'neutral', { containerKey: 'y' }); service.clear('x'); - await timer(0).toPromise(); + await firstValueFrom(timer(0)); service['containerComponentRef'].changeDetectorRef.detectChanges(); expect(selectToasterElement('.fa-exclamation-circle')).toBeTruthy(); expect(selectToasterContent(`.${toastClassPrefix}-title`)).toBe('TITLE_2'); expect(selectToasterContent(`.${toastClassPrefix}-message`)).toBe('MESSAGE_2'); }); + + test('should display custom icon when iconClass is provided', async () => { + service.show('MESSAGE', 'TITLE', 'neutral', { iconClass: 'custom-icon' }); + + await firstValueFrom(timer(0)); + service['containerComponentRef'].changeDetectorRef.detectChanges(); + + expect(selectToasterElement('.custom-icon')).toBeTruthy(); + }); }); function clearElements(selector = `.${toastClassPrefix}`) {