Modal and drawer helper services for creating dynamic Angular components with configuration options, Observable-based result handling, and comprehensive UI component management.
Service for creating and managing modal dialogs with dynamic component loading and result handling.
/**
* Modal helper service for creating dynamic modal dialogs
* Provides simplified API over ng-zorro-antd modal components
*/
class ModalHelper {
/**
* Create a modal dialog with component
* @param comp - Component class or template
* @param params - Data to pass to component
* @param options - Modal configuration options
* @returns Observable that emits result when modal closes
*/
create<T>(
comp: any,
params?: T,
options?: ModalHelperOptions
): Observable<any>;
/**
* Create a static modal dialog (no mask close)
* @param comp - Component class or template
* @param params - Data to pass to component
* @param options - Modal configuration options
* @returns Observable that emits result when modal closes
*/
createStatic<T>(
comp: any,
params?: T,
options?: ModalHelperOptions
): Observable<any>;
}
interface ModalHelperOptions {
/** Modal size preset or custom dimensions */
size?: 'sm' | 'md' | 'lg' | 'xl' | '' | number | string;
/** Native ng-zorro modal options */
modalOptions?: ModalOptions;
/** Success validation mode for result handling */
exact?: boolean;
/** Include tab spacing fix for better layout */
includeTabs?: boolean;
/** Enable drag functionality */
drag?: ModalHelperDragOptions | boolean;
/** Force use nzData for parameter passing */
useNzData?: boolean;
/** Focus button on open */
focus?: 'ok' | 'cancel';
}
interface ModalHelperDragOptions {
/** Enable dragging */
enabled?: boolean;
/** Drag handle selector */
handle?: string;
}Usage Examples:
import { Component, inject, Inject } from "@angular/core";
import { ModalHelper, NZ_MODAL_DATA } from "@delon/theme";
// Modal content component
@Component({
selector: "user-edit-modal",
template: `
<div class="modal-header">
<h3>Edit User</h3>
</div>
<div class="modal-body">
<form [formGroup]="form" (ngSubmit)="submit()">
<input
formControlName="name"
placeholder="Name"
[value]="data.name"
/>
<input
formControlName="email"
placeholder="Email"
[value]="data.email"
/>
<div class="modal-footer">
<button type="button" (click)="cancel()">Cancel</button>
<button type="submit">Save</button>
</div>
</form>
</div>
`
})
export class UserEditModalComponent {
form = this.fb.group({
name: [''],
email: ['']
});
constructor(
@Inject(NZ_MODAL_DATA) public data: any,
private fb: FormBuilder,
private modalRef: NzModalRef
) {}
submit() {
if (this.form.valid) {
// Return form data as result
this.modalRef.close(this.form.value);
}
}
cancel() {
this.modalRef.dismiss();
}
}
// Component using modal
@Component({
selector: "user-list",
template: `
<button (click)="editUser(user)">Edit User</button>
`
})
export class UserListComponent {
modalHelper = inject(ModalHelper);
editUser(user: any) {
this.modalHelper.create(
UserEditModalComponent,
{ name: user.name, email: user.email },
{
size: 'md',
modalOptions: {
nzTitle: 'Edit User',
nzMask: true,
nzMaskClosable: false
}
}
).subscribe(result => {
if (result) {
console.log('User updated:', result);
// Update user data
this.updateUser(user.id, result);
}
});
}
confirmDelete(user: any) {
this.modalHelper.createStatic(
ConfirmDeleteComponent,
{ item: user },
{ size: 'sm' }
).subscribe(confirmed => {
if (confirmed) {
this.deleteUser(user.id);
}
});
}
private updateUser(id: string, data: any) {
// Update user logic
}
private deleteUser(id: string) {
// Delete user logic
}
}Service for creating and managing drawer panels with dynamic component loading and state management.
/**
* Drawer helper service for creating dynamic drawer panels
* Provides simplified API over ng-zorro-antd drawer components
*/
class DrawerHelper {
/** Array of currently open drawer references */
readonly openDrawers: NzDrawerRef[];
/**
* Create a drawer panel with component
* @param title - Drawer title text
* @param comp - Component class or template
* @param params - Data to pass to component
* @param options - Drawer configuration options
* @returns Observable that emits result when drawer closes
*/
create<T>(
title: string,
comp: any,
params?: T,
options?: DrawerHelperOptions
): Observable<any>;
/**
* Create a static drawer panel (no mask close)
* @param title - Drawer title text
* @param comp - Component class or template
* @param params - Data to pass to component
* @param options - Drawer configuration options
* @returns Observable that emits result when drawer closes
*/
static<T>(
title: string,
comp: any,
params?: T,
options?: DrawerHelperOptions
): Observable<any>;
/** Close all open drawers */
closeAll(): void;
}
interface DrawerHelperOptions {
/** Drawer size preset or custom dimensions */
size?: 'sm' | 'md' | 'lg' | 'xl' | number;
/** Include footer with action buttons */
footer?: boolean;
/** Footer height in pixels */
footerHeight?: number;
/** Success validation mode for result handling */
exact?: boolean;
/** Native ng-zorro drawer options */
drawerOptions?: NzDrawerOptions;
}Usage Examples:
import { Component, inject, Inject } from "@angular/core";
import { DrawerHelper, NZ_DRAWER_DATA } from "@delon/theme";
// Drawer content component
@Component({
selector: "user-detail-drawer",
template: `
<div class="drawer-content">
<div class="user-info">
<img [src]="data.avatar" alt="Avatar" class="avatar" />
<h2>{{ data.name }}</h2>
<p>{{ data.email }}</p>
</div>
<div class="user-stats">
<div class="stat">
<span class="label">Posts</span>
<span class="value">{{ data.stats.posts }}</span>
</div>
<div class="stat">
<span class="label">Followers</span>
<span class="value">{{ data.stats.followers }}</span>
</div>
</div>
<div class="actions" *ngIf="showFooter">
<button (click)="editUser()">Edit</button>
<button (click)="close()">Close</button>
</div>
</div>
`
})
export class UserDetailDrawerComponent {
showFooter = true;
constructor(
@Inject(NZ_DRAWER_DATA) public data: any,
private drawerRef: NzDrawerRef
) {}
editUser() {
// Return edit action
this.drawerRef.close({ action: 'edit', user: this.data });
}
close() {
this.drawerRef.close();
}
}
// Component using drawer
@Component({
selector: "user-dashboard",
template: `
<div class="user-grid">
<div
*ngFor="let user of users"
class="user-card"
(click)="viewUserDetail(user)"
>
<img [src]="user.avatar" alt="Avatar" />
<span>{{ user.name }}</span>
</div>
</div>
`
})
export class UserDashboardComponent {
drawerHelper = inject(DrawerHelper);
users = [
{
id: 1,
name: 'John Doe',
email: 'john@example.com',
avatar: '/assets/john.png',
stats: { posts: 25, followers: 150 }
}
];
viewUserDetail(user: any) {
this.drawerHelper.create(
`User Details - ${user.name}`,
UserDetailDrawerComponent,
user,
{
size: 'md',
footer: true,
footerHeight: 60,
drawerOptions: {
nzPlacement: 'right',
nzMask: true,
nzMaskClosable: true
}
}
).subscribe(result => {
if (result?.action === 'edit') {
this.editUser(result.user);
}
});
}
showSettings() {
this.drawerHelper.create(
'Application Settings',
SettingsDrawerComponent,
{ currentSettings: this.getSettings() },
{ size: 'lg' }
).subscribe(newSettings => {
if (newSettings) {
this.updateSettings(newSettings);
}
});
}
closeAllDrawers() {
this.drawerHelper.closeAll();
}
private editUser(user: any) {
// Edit user logic
}
private getSettings() {
// Get current settings
return {};
}
private updateSettings(settings: any) {
// Update settings logic
}
}Complete configuration interfaces for modal and drawer customization.
/**
* Modal helper configuration options
* Extends native modal options with helper-specific features
*/
interface ModalHelperOptions {
/** Modal size preset or custom dimensions */
size?: 'sm' | 'md' | 'lg' | 'xl' | '' | number | string;
/** Native ng-zorro modal options */
modalOptions?: ModalOptions;
/** Success validation mode - exact match for success result */
exact?: boolean;
/** Include tab spacing fix for better form layout */
includeTabs?: boolean;
/** Enable drag functionality */
drag?: ModalHelperDragOptions | boolean;
/** Force use nzData for parameter passing instead of direct injection */
useNzData?: boolean;
/** Auto-focus button on modal open */
focus?: 'ok' | 'cancel';
}
/**
* Drawer helper configuration options
* Extends native drawer options with helper-specific features
*/
interface DrawerHelperOptions {
/** Drawer size preset or custom width in pixels */
size?: 'sm' | 'md' | 'lg' | 'xl' | number;
/** Include footer with action buttons */
footer?: boolean;
/** Footer height in pixels */
footerHeight?: number;
/** Success validation mode - exact match for success result */
exact?: boolean;
/** Native ng-zorro drawer options */
drawerOptions?: NzDrawerOptions;
}
/**
* Modal drag configuration options
* Configure draggable modal behavior
*/
interface ModalHelperDragOptions {
/** Enable dragging functionality */
enabled?: boolean;
/** CSS selector for drag handle element */
handle?: string;
/** Constrain dragging to parent bounds */
containment?: boolean;
}Usage Examples:
import { ModalHelper, DrawerHelper } from "@delon/theme";
// Advanced modal configuration
const modalOptions: ModalHelperOptions = {
size: 'lg',
exact: true, // Only treat explicit success results as success
includeTabs: true, // Better form spacing
drag: {
enabled: true,
handle: '.modal-header', // Drag by header only
containment: true
},
modalOptions: {
nzTitle: 'Advanced Settings',
nzMask: true,
nzMaskClosable: false,
nzClosable: true,
nzCentered: true,
nzWidth: '80%',
nzBodyStyle: { padding: '24px' }
}
};
// Advanced drawer configuration
const drawerOptions: DrawerHelperOptions = {
size: 800, // Custom width
footer: true,
footerHeight: 72,
exact: false, // Any truthy result is success
drawerOptions: {
nzPlacement: 'right',
nzMask: true,
nzMaskClosable: true,
nzClosable: true,
nzKeyboard: true,
nzBodyStyle: { padding: '16px' }
}
};
// Size presets
const sizes = {
sm: 300, // Small drawer/modal
md: 600, // Medium drawer/modal
lg: 900, // Large drawer/modal
xl: 1200 // Extra large drawer/modal
};