Skip to content

Commit

Permalink
feat(NgxStatusService): add support for subtitle + fix "component alr…
Browse files Browse the repository at this point in the history
…eady have attached view" error
  • Loading branch information
Maxouhell committed Mar 3, 2025
1 parent 4f62721 commit f57e4c6
Showing 1 changed file with 26 additions and 17 deletions.
43 changes: 26 additions & 17 deletions projects/status/src/status.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DOCUMENT } from '@angular/common';
import { ApplicationRef, DestroyRef, EmbeddedViewRef, inject, Injectable, Injector, ViewContainerRef } from '@angular/core';
import { ApplicationRef, DestroyRef, EmbeddedViewRef, EventEmitter, inject, Injectable, Injector, ViewContainerRef } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { from, mergeWith, switchMap, take, tap, timer } from 'rxjs';

Expand Down Expand Up @@ -28,29 +28,37 @@ export class NgxStatusService {
/**
* Display an information message to the screen.
*/
public info(text: string, title = '', duration?: number, actions?: readonly NgxStatusAction[]): void {
this.showStatus({ type: 'info', title, text, duration, actions });
public info(text: string, title: string | { title: string; subtitle: string } = '', duration?: number, actions?: readonly NgxStatusAction[]): void {
const { title: mainTitle, subtitle = '' } = typeof title === 'string' ? { title } : title;

this.showStatus({ type: 'info', title: mainTitle, subtitle, text, duration, actions });
}

/**
* Display an information message to the screen.
*/
public success(text: string, title = '', duration?: number, actions?: readonly NgxStatusAction[]): void {
this.showStatus({ type: 'success', title, text, duration, actions });
public success(text: string, title: string | { title: string; subtitle: string } = '', duration?: number, actions?: readonly NgxStatusAction[]): void {
const { title: mainTitle, subtitle = '' } = typeof title === 'string' ? { title } : title;

this.showStatus({ type: 'success', title: mainTitle, subtitle, text, duration, actions });
}

/**
* Display a warning message to the screen.
*/
public warning(text: string, title = 'Attention', technicalText?: string, duration?: number, actions?: readonly NgxStatusAction[]): void {
this.showStatus({ type: 'warn', title, text, duration, technicalText, actions });
public warning(text: string, title: string | { title: string; subtitle: string } = 'Attention', technicalText?: string, duration?: number, actions?: readonly NgxStatusAction[]): void {
const { title: mainTitle, subtitle = '' } = typeof title === 'string' ? { title } : title;

this.showStatus({ type: 'warn', title: mainTitle, subtitle, text, duration, technicalText, actions });
}

/**
* Display an error message to the screen and send it to HugLog.
*/
public error(text: string, title = 'Erreur', technicalText?: string, duration?: number, actions?: readonly NgxStatusAction[]): void {
this.showStatus({ type: 'danger', title, text, duration, technicalText, actions });
public error(text: string, title: string | { title: string; subtitle: string } = 'Erreur', technicalText?: string, duration?: number, actions?: readonly NgxStatusAction[]): void {
const { title: mainTitle, subtitle = '' } = typeof title === 'string' ? { title } : title;

this.showStatus({ type: 'danger', title: mainTitle, subtitle, text, duration, technicalText, actions });
}

public showStatus(status: NgxStatus): void {
Expand All @@ -59,22 +67,23 @@ export class NgxStatusService {
switchMap(component => {
// Get the root view container ref of the application by injecting it into the root component
const applicationRef = this.injector.get(ApplicationRef);
const rootViewContainerRef = applicationRef.components[0].injector.get(ViewContainerRef);
const rootViewContainerRef = applicationRef.components[0]?.injector.get(ViewContainerRef);
// Insert the modal component into the root view container
const componentRef = rootViewContainerRef.createComponent(component.NgxStatusComponent);
componentRef.instance.status = status;
applicationRef.attachView(componentRef.hostView);
const componentRef = rootViewContainerRef?.createComponent(component.NgxStatusComponent);

const domElement = (componentRef.hostView as EmbeddedViewRef<unknown>).rootNodes[0] as HTMLElement;
this.document.body.appendChild(domElement);
if (componentRef) {
componentRef.instance.status = status;
const domElement = (componentRef?.hostView as EmbeddedViewRef<unknown>).rootNodes[0] as HTMLElement;
this.document.body.appendChild(domElement);
}

applicationRef.tick();

const duration = status.duration || (status.type === 'danger' && durationLong) || durationShort;
return timer(duration).pipe(
mergeWith(componentRef.instance.close),
mergeWith(componentRef?.instance.close ?? new EventEmitter<void>),
tap(() => {
componentRef.destroy();
componentRef?.destroy();
applicationRef.tick();
})
);
Expand Down

0 comments on commit f57e4c6

Please sign in to comment.