ngx-light-modal
v0.0.3
Published
Lightweight and dependency-free Angular modal package using standalone components. Supports stacking, backdrops, dynamic injection, and custom content components.
Maintainers
Readme
Ngx Light Modal
NgxLightModal is a lightweight, dependency-free Angular modal package built with standalone components and fully dynamic rendering. It supports modal stacking, backdrop control, custom content components, and complete lifecycle observables — without requiring a host component in your templates.
Features
- ✅ No modal host required – Just call the service, and it works.
- 🧩 Standalone Components Support – Built for modern Angular architecture.
- 📦 Lightweight & Dependency-Free – Zero external dependencies, minimal size.
- 📚 Dynamic Component Injection – Display any component dynamically as a modal.
- 🔁 Stackable Modals – Open and manage multiple modals with ease.
- 🌙 Backdrop & ESC Handling – Configurable dismissal via backdrop click or ESC key.
- 🧠 Full Lifecycle Events – Hooks for open, close, submit, escape, and more.
- 🎨 Customizable via
modalClassand options
Installation
Install the package via npm:
npm install ngx-light-modalModalRef Lifecycle Methods
Once you open a modal using modalService.open(...), it returns a ModalRef<T> instance.
Here are all the lifecycle methods available on the ModalRef:
| Method | Description |
| ----------------------------------------- | ---------------------------------------------------------- |
| afterClosed$ | Emits once when the modal is closed, regardless of how |
| beforeClosed$ | Emits right before the modal begins closing |
| afterOpened$ | Emits once when the modal has been fully opened |
| onSubmitted() | Emits when modal closes using CloseState.SUBMITTED |
| onEscaped() | Emits when modal is closed using the ESC key |
| onBackdropDismiss() | Emits when user clicks the backdrop to dismiss |
| onCancelled() | Emits when modal closes using CloseState.CANCELLED |
| onStateClose(state: CloseState) | Listen for a specific CloseState only |
| onUserDismissed() | Emits when modal closes via ESC, backdrop, or close button |
| close(result?: any, state?: CloseState) | Manually close modal with optional result and reason |
CloseState Enum
enum CloseState {
CLOSED = 'CLOSED',
SUBMITTED = 'SUBMITTED',
CANCELLED = 'CANCELLED',
ESCAPED = 'ESCAPED',
BACKDROP_DISMISS = 'BACKDROP_DISMISS',
CLOSE_BUTTON = 'CLOSE_BUTTON',
EXITED = 'EXITED',
}Usage
Open a Modal from Any Component
import { Component, inject } from '@angular/core';
import { ModalService } from 'ngx-light-modal';
import { ExampleModalComponent } from './modal/example-modal/example-modal.component';
@Component({
standalone: true,
selector: 'app-root',
template: `<button (click)="openModal()">Open Modal</button>`,
})
export class AppComponent {
private modalService = inject(ModalService);
openModal() {
const modalRef = this.modalService.open(
ExampleModalComponent,
{ message: 'Hello from parent!' },
{
showBackdrop: true,
dismissOnBackdropClick: true,
showCloseButton: true,
modalClass: 'custom-modal-style',
}
);
modalRef.afterClosed$.subscribe((result) => {
console.log('Modal closed with:', result?.state);
});
modalRef.onSubmitted().subscribe((result) => {
console.log('Submitted data:', result.data);
});
modalRef.onEscaped().subscribe(() => {
console.log('User pressed ESC');
});
modalRef.afterOpened$.subscribe(() => {
console.log('Modal opened');
});
modalRef.beforeClosed$.subscribe(() => {
console.log('Modal will close');
});
modalRef.onBackdropDismiss().subscribe(() => console.log('Backdrop clicked'));
modalRef.onCancelled().subscribe(() => console.log('Cancelled by user'));
// More specific
modalRef.onStateClose(CloseState.CLOSE_BUTTON).subscribe(() => console.log('Close button used'));
// Aggregated
modalRef.onUserDismissed().subscribe((result) => console.log('Dismissed by user:', result.state));
}
}Example Modal Component
import { Component } from '@angular/core';
import { ModalService } from 'ngx-light-modal';
import { CloseState } from 'ngx-light-modal';
@Component({
selector: 'app-example-modal',
template: `
<h2>Custom Modal</h2>
<p>Data received: {{ message }}</p>
<p>Data received Signal: {{ messageSignal() }}</p>
<button (click)="close()">Close</button>
<button (click)="openForm()">Open Form Modal</button>
`,
})
export class ExampleModalComponent {
/**
* Supports both plain data and Angular signals and it's type-safe
*/
message: any;
messageSignal = signal<string>('');
constructor(private modalService: ModalService) {}
close() {
this.modalService.getModalRef(this)?.close(null, CloseState.CANCELLED);
}
openForm() {
this.modalService.open(FormComponent, {
data: { title: 'User Form', userId: 123 },
});
}
}API
ModalService
open(component: Type<T>, data?: any, options?: ModalOptions): ModalRef<T>
Opens a modal component with the specified data and options.
getModalRef(component: object): ModalRef | null
Returns the ModalRef for a given component instance.
ModalRef
Handles lifecycle and communication.
Observables
afterClosed$: Emits when modal is closed.beforeClosed$: Emits right before the modal is closed.afterOpened$: Emits after the modal is rendered.onSubmitted<T>(): Emits custom submit result.onEscaped(): Emits if user hits ESC.
Methods
close(data?: any, state?: CloseState): Closes the modal manually.submit<T>(data: T): Triggers the submit observable.escape(): Simulates ESC key behavior.
ModalOptions
interface ModalOptions {
showBackdrop?: boolean; // default: true
dismissOnBackdropClick?: boolean; // default: true
showCloseButton?: boolean; // default: true
modalClass?: string; // optional CSS class for modal
}CloseState
enum CloseState {
CLOSED = 'CLOSED',
SUBMITTED = 'SUBMITTED',
CANCELLED = 'CANCELLED',
ESCAPED = 'ESCAPED',
}License
This project is licensed under the MIT License - see the LICENSE file for details.
