
Syncfusion Angular Popups
- 172 installs
- Updated August 4, 2026
- syncfusion/angular-ui-components-skills
Use syncfusion-angular-popups for development tasks
About
syncfusion-angular-popups: A skill for development. This provides functionality for development workflows.
- syncfusion-angular-popups
Syncfusion Angular Popups by the numbers
- 172 all-time installs (skills.sh)
- +11 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #2,264 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/angular-ui-components-skills --skill syncfusion-angular-popupsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 172 |
|---|---|
| Last updated | August 4, 2026 |
| Repository | syncfusion/angular-ui-components-skills ↗ |
What it does
Use syncfusion-angular-popups for development tasks
Files
Implementing Syncfusion Angular Popups
Dialog
The Dialog component is a window that displays information to the user and is used to get user input. It supports both modal dialogs (blocking parent interaction) and modeless dialogs (allowing parent interaction).
Component Overview
Key Features
- Modal & Modeless modes - Block or allow parent interaction
- Templates - Customizable headers, content, and footers
- Positioning - 9 built-in positions or custom placement
- Animations - Smooth open/close effects (Fade, Zoom, Slide)
- Draggable & Resizable - Allow users to move and resize dialogs
- Forms Integration - Reactive and template-driven forms
- Accessibility - Full WCAG 2.2 Level AA support with ARIA
- Keyboard Navigation - Tab, Escape, Enter, and arrow keys
- Responsive - Full-screen mode on mobile devices
Documentation and Navigation Guide
When you need to implement Dialog features, follow these references:
Getting Started
📄 Read: references/dialog-getting-started.md
- Installation and setup in Angular 21+
- Basic dialog implementation
- CSS imports and themes
- Opening and closing dialogs
- Built-in button support
Dialog Modes & Types
📄 Read: references/dialog-modal-vs-modeless.md
- Modal dialog behavior (blocks parent interaction)
- Modeless dialog behavior (allows parent interaction)
- Use cases and when to use each mode
- Toggling between modes
- Overlay customization and styling
Content & Templates
📄 Read: references/dialog-templates-and-content.md
- Header templates and customization
- Content as strings, HTML, or ng-template
- Footer templates with buttons
- Using ng-content for dynamic content
- Button binding and click events
- Dynamic button arrays
Positioning & Sizing
📄 Read: references/dialog-positioning-and-sizing.md
- Built-in positions (9 locations: Top, Center, Bottom, etc.)
- Custom positioning with X, Y coordinates
- Width and height configuration
- Min/max height constraints
- Responsive sizing on different screen sizes
- Full-screen mode on mobile devices
Styling & Customization
📄 Read: references/dialog-styling-and-customization.md
- CSS class customization (header, content, footer, overlay)
- Theme integration (Material, Bootstrap, Tailwind, Fluent)
- Dark mode support
- Animation effects (Fade, Zoom, SlideLeft, SlideRight, etc.)
- Icon customization (close button, resize handles)
- RTL (Right-to-Left) language support
Accessibility & Forms
📄 Read: references/dialog-accessibility-and-forms.md
- WCAG 2.2 Level AA compliance standards
- ARIA attributes (aria-labelledby, aria-describedby, aria-modal, aria-grabbed)
- Keyboard navigation patterns (Tab, Shift+Tab, Escape, Enter)
- Screen reader support and best practices
- Form validation with FormValidator
- Reactive forms patterns
- Template-driven forms patterns
- Custom validation rules and error handling
Interaction & Events
📄 Read: references/dialog-interaction-and-events.md
- Dialog open/close events
- Draggable dialogs (allow users to move dialogs)
- Resizable dialogs (allow users to resize)
- Button click events and handling
- Content interaction patterns
- Preventing dialog closure
- Focus management
- Dialog lifecycle events
Advanced Patterns
📄 Read: references/dialog-advanced-patterns.md
- Nested dialogs (dialog within dialog)
- Ajax-loaded content dynamically
- Utility functions for programmatic creation
- Complex layouts (Rich Text Editor, multi-step forms)
- Scroll handling and auto-centering
- Custom event emitters
- Routing integration patterns
API Reference (Complete)
📄 Read: references/dialog-api-reference.md
- Complete Dialog API documentation
- All valid properties with types and examples
- All methods (show, hide, refresh, destroy)
- All events (beforeOpen, beforeClose, drag, resize, etc.)
- Interfaces and models (AnimationSettingsModel, ButtonPropsModel, etc.)
- Valid enumerations (DialogEffect, ResizeDirections)
- Official Syncfusion documentation links
Quick Start Example
Here's a minimal example to open a basic modal dialog:
import { Component, ViewChild } from '@angular/core';
import { DialogModule, DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
selector: 'app-root',
imports: [DialogModule],
template: `
<div id="dialog-container" style="height: 500px;">
<button class="e-control e-btn" (click)="onOpenDialog()">
Open Dialog
</button>
<ejs-dialog
#ejDialog
target="#dialog-container"
[showCloseIcon]="true"
width="400px"
content="This is a Dialog content"
>
<ng-template #header>
<div class="e-dlg-header-content">
<span>Dialog Title</span>
</div>
</ng-template>
</ejs-dialog>
</div>
`
})
export class AppComponent {
@ViewChild('ejDialog') ejDialog!: DialogComponent;
onOpenDialog(): void {
this.ejDialog.show();
}
}CSS:
#dialog-container {
height: 500px;
}Common Patterns
Pattern 1: Modal Confirmation Dialog
// Create a modal dialog for confirmation
<ejs-dialog
[isModal]="true"
[showCloseIcon]="true"
width="350px"
content="Are you sure you want to delete this item?"
>
<ng-template #footer>
<button class="e-control e-btn e-primary" (click)="onConfirm()">
Yes, Delete
</button>
<button class="e-control e-btn" (click)="onCancel()">
Cancel
</button>
</ng-template>
</ejs-dialog>Pattern 2: Dialog with Form (Reactive Forms)
// Dialog containing a reactive form
<ejs-dialog [showCloseIcon]="true" width="450px">
<form [formGroup]="form">
<div class="e-dlg-content">
<input formControlName="name" placeholder="Enter name" />
<input formControlName="email" placeholder="Enter email" />
</div>
</form>
<ng-template #footer>
<button class="e-control e-btn e-primary" (click)="onSubmit()">
Submit
</button>
</ng-template>
</ejs-dialog>Pattern 3: Positioned Dialog
// Dialog positioned at a specific location
<ejs-dialog
[position]="{ X: 100, Y: 50 }"
width="400px"
content="Positioned Dialog"
>
</ejs-dialog>Key Props Quick Reference
| Property | Type | Purpose | Example |
|---|---|---|---|
isModal | boolean | Block parent interaction | [isModal]="true" |
showCloseIcon | boolean | Show close button in header | [showCloseIcon]="true" |
width | string \ | number | Set dialog width |
height | string \ | number | Set dialog height |
minHeight | string \ | number | Minimum height constraint |
position | PositionDataModel | Set position (X, Y) or preset | [position]="{ X: 'center', Y: 'center' }" |
target | HTMLElement \ | string | Set container element |
content | string \ | HTMLElement | Set content text or HTML |
header | string \ | HTMLElement | Set header text or element |
buttons | ButtonPropsModel[] | Add footer buttons | [buttons]="buttonArray" |
closeOnEscape | boolean | Close on Escape key | [closeOnEscape]="true" |
allowDragging | boolean | Enable header dragging | [allowDragging]="true" |
enableResize | boolean | Enable resizing | [enableResize]="true" |
resizeHandles | ResizeDirections[] | Specify resize directions | [resizeHandles]="['All']" |
cssClass | string | Custom CSS class(es) | cssClass="custom-dialog" |
animationSettings | AnimationSettingsModel | Configure animations | [animationSettings]="{ effect: 'FadeZoom' }" |
enablePersistence | boolean | Save state between reloads | [enablePersistence]="true" |
zIndex | number | Z-order for layering | [zIndex]="1000" |
Common Use Cases
1. Confirmation before delete - Modal dialog asking user to confirm deletion 2. Form submission - Dialog with form for user to submit data 3. Alerts and notifications - Display important information to users 4. Multi-step processes - Use nested dialogs for workflows 5. Settings panels - Modeless dialog for settings that don't block interaction 6. Help and guidance - Display help content in a draggable dialog 7. Loading states - Show progress in a dialog while processing 8. Error handling - Display error messages in a modal
---
Related Skills
- Dialog Animation - Customize open/close animations
- Form Validation - Validate user input in dialogs
- Routing Integration - Use dialogs with Angular routing
Predefined Dialogs
This skill covers building alert, confirm, and prompt dialogs using Syncfusion's DialogUtility — a zero-template, utility-first approach to displaying modal feedback and user-input dialogs in Angular applications.
Which Dialog Type?
| Need | Dialog Type | API |
|---|---|---|
| Warn/inform user, single OK | Alert | DialogUtility.alert(...) |
| Ask for confirmation (OK + Cancel) | Confirm | DialogUtility.confirm(...) |
| Collect user input (HTML content + OK + Cancel) | Prompt | DialogUtility.confirm(...) with input in content |
Key insight: Angular's predefined dialogs have no separate "prompt" method — useDialogUtility.confirm()with custom HTML in thecontentproperty to build a prompt pattern.
Quick Start
ng add @syncfusion/ej2-angular-popups// src/app/app.ts
import { Component } from '@angular/core';
import { DialogModule } from '@syncfusion/ej2-angular-popups';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons';
import { DialogUtility } from '@syncfusion/ej2-popups';
@Component({
selector: 'app-root',
standalone: true,
imports: [DialogModule, ButtonModule],
template: `
<button ejs-button cssClass="e-danger" (click)="showAlert()">Alert</button>
<button ejs-button cssClass="e-success" (click)="showConfirm()" style="margin-left:8px">Confirm</button>
<button ejs-button [isPrimary]="true" (click)="showPrompt()" style="margin-left:8px">Prompt</button>
`
})
export class App {
showAlert(): void {
DialogUtility.alert({
title: 'Warning',
content: 'Disk space is running low.',
width: '280px'
});
}
showConfirm(): void {
const dlg = DialogUtility.confirm({
title: 'Delete Item',
content: 'Are you sure you want to delete this item?',
width: '300px',
okButton: { text: 'Yes', click: () => { dlg.hide(); /* handle confirm */ } },
cancelButton: { text: 'No', click: () => { dlg.hide(); } }
});
}
showPrompt(): void {
const dlg = DialogUtility.confirm({
title: 'Enter Name',
content: '<p>Your name:</p><input id="nameInput" class="e-input" type="text" placeholder="Type here..." />',
width: '300px',
okButton: {
text: 'Submit',
click: () => {
const value = (document.getElementById('nameInput') as HTMLInputElement).value;
dlg.hide();
// use value
}
},
cancelButton: { text: 'Cancel', click: () => dlg.hide() }
});
}
}/* styles.css */
@import '../node_modules/@syncfusion/ej2-base/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-icons/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-angular-popups/styles/material3.css';Common Patterns
Pattern 1 — Delete confirmation with icons:
DialogUtility.confirm({
title: 'Delete Files',
content: 'Permanently delete selected files?',
width: '300px',
okButton: { text: 'Yes', icon: 'e-icons e-check' },
cancelButton: { text: 'No', icon: 'e-icons e-close' }
});Pattern 2 — Alert with close button + ESC support:
DialogUtility.alert({
title: 'Session Expired',
content: 'Your session has expired. Please log in again.',
width: '300px',
showCloseIcon: true,
closeOnEscape: true
});Pattern 3 — Positioned modal confirm:
DialogUtility.confirm({
title: 'Confirm Action',
content: 'Submit the form?',
isModal: true,
position: { X: 'center', Y: 'center' },
animationSettings: { effect: 'Zoom' },
isDraggable: true,
width: '280px'
});Key Properties at a Glance
| Property | Purpose | Default |
|---|---|---|
title | Dialog header text | — |
content | Body text or HTML string | — |
width | Dialog width (px or %) | '100%' |
isModal | Overlay + modal behavior | false |
isDraggable | Allow header drag to reposition | false |
showCloseIcon | Show × close button | false |
closeOnEscape | Close on ESC key | false |
position | { X, Y } — predefined or offset | center/center |
animationSettings | { effect, duration, delay } | Fade, 400ms |
okButton | OK button config { text, icon, click } | — |
cancelButton | Cancel button config { text, icon, click } | — |
cssClass | Custom CSS class on dialog root | '' |
zIndex | Stacking order | 1000 |
open | Callback after dialog opens | — |
close | Callback after dialog closes | — |
Documentation
Getting Started
📄 Read: references/getting-started.md
- Installation and package setup
- CSS imports and theme options
- Basic alert, confirm, and prompt examples
- All
DialogUtilityoption properties
Customization
📄 Read: references/customization.md
- Button text and icon customization
- Show/hide close icon and ESC behavior
- Custom HTML content in dialogs
- Programmatic dialog close with
hide()
Position and Dimension
📄 Read: references/position-and-dimension.md
- Position X/Y values and offset usage
- Width and height properties
- Max-width/max-height via
cssClass - Min-width/min-height via
cssClass
Animation and Draggable
📄 Read: references/animation-and-draggable.md
animationSettingseffect options (Zoom, Fade, FadeZoom, etc.)- Duration and delay configuration
isDraggablefor all dialog types
Events and Patterns
📄 Read: references/events-and-patterns.md
openandcloseevent callbacksisModal,zIndex,cssClassadvanced usage- Common real-world patterns (delete confirm, form prompt, info alert)
- Managing multiple dialog instances
API Reference
📄 Read: references/api.md
- Complete
DialogUtility.alert()andDialogUtility.confirm()options okButton/cancelButtonButtonArgs propertiesAnimationSettingsModelpropertiesPositionDataModelpropertiesDialogComponentproperties, methods, and events
Tooltip
The Syncfusion Angular Tooltip (ejs-tooltip) displays a pop-up with information or a message when you hover, click, focus, or touch a target element. It supports 12 positions, animations, HTML/template/AJAX content, sticky mode, mouse trailing, and full accessibility compliance.
Navigation Guide
Getting Started
📄 Read: references/getting-started.md
- Installation and package setup (
ng add @syncfusion/ej2-angular-popups) - CSS theme imports
- Basic single-target tooltip
- Multi-target tooltip with
targetproperty - Standalone (Angular 19+) and module-based setup
Content
📄 Read: references/content.md
- Static text and HTML string content
- Template content using
ng-template - Dynamic content via AJAX/Fetch in
beforeRenderevent - Loading HTML elements (iframes, videos) in tooltip
enableHtmlParseandenableHtmlSanitizeroptions
Position & Dimensions
📄 Read: references/position-and-dimension.md
- All 12 position values (
TopCenter,BottomLeft, etc.) - Tip pointer show/hide and position
- Mouse trailing
- Offset values (
offsetX,offsetY) - Width, height, and scroll mode
- Window collision handling
Open Modes
📄 Read: references/open-mode.md
opensOn: Auto, Hover, Click, Focus, Custom- Combining multiple open modes
- Custom mode with programmatic
open()/close() - Sticky mode (
isSticky) - Open/close delay
Animation
📄 Read: references/animation.md
animationproperty with open/close settings- All supported animation effects
- Applying animations via
open()/close()methods - Custom transition effects
Customization & Style
📄 Read: references/customization-and-style.md
cssClassfor custom styles- CSS class reference for tooltip structure
- Tip pointer customization
- Fancy tips (curved, bubble)
- SVG and canvas tooltips
- Tooltips on disabled elements
- Container, RTL, htmlAttributes
Accessibility
📄 Read: references/accessibility.md
- WCAG 2.2, Section 508 compliance
- WAI-ARIA attributes
- Keyboard navigation
- Screen reader support
API Reference
📄 Read: references/api.md
- All properties, methods, and events
- Type definitions and defaults
TooltipEventArgs,AnimationModel,TooltipAnimationSettingsPosition,TipPointerPosition, andEffectenumerations
Quick Start
ng add @syncfusion/ej2-angular-popups// src/app/app.ts (Angular 19+ standalone)
import { Component, ViewEncapsulation } from '@angular/core';
import { TooltipModule } from '@syncfusion/ej2-angular-popups';
@Component({
standalone: true,
imports: [TooltipModule],
selector: 'app-root',
encapsulation: ViewEncapsulation.None,
template: `
<ejs-tooltip content="Hello, I am a Tooltip!" position="BottomCenter">
<button>Hover me</button>
</ejs-tooltip>
`
})
export class App {}/* styles.css */
@import "@syncfusion/ej2-base/styles/material3.css";
@import "@syncfusion/ej2-angular-buttons/styles/material3.css";
@import "@syncfusion/ej2-angular-popups/styles/material3.css";Common Patterns
Multi-target tooltip (single instance)
<!-- Wraps a container; target selector picks which children get tooltips -->
<ejs-tooltip target=".has-tip">
<div id="container">
<button class="has-tip" title="Save your work">Save</button>
<button class="has-tip" title="Delete selected item">Delete</button>
<button>No tooltip here</button>
</div>
</ejs-tooltip>Tooltip that opens on click
<ejs-tooltip content="Clicked!" opensOn="Click" position="RightCenter">
<button>Click me</button>
</ejs-tooltip>Sticky tooltip with close button
<ejs-tooltip content="I stay until you close me." [isSticky]="true">
<span>Hover and pin me</span>
</ejs-tooltip>HTML content tooltip
public htmlContent: string = '<b>Bold</b> and <i>italic</i> text with a <a href="#">link</a>.';<ejs-tooltip [content]="htmlContent">
<button>Rich content</button>
</ejs-tooltip>Programmatic open/close (custom mode)
@ViewChild('tooltip') tooltip!: TooltipComponent;
openTip(): void {
this.tooltip.open(this.tooltip.element);
}
closeTip(): void {
this.tooltip.close();
}<ejs-tooltip #tooltip content="Custom trigger" opensOn="Custom">
<span>Target</span>
</ejs-tooltip>
<button (click)="openTip()">Show</button>
<button (click)="closeTip()">Hide</button>Key Properties at a Glance
| Property | Type | Default | Purpose |
|---|---|---|---|
content | `string \ | HTMLElement` | — |
position | Position | 'TopCenter' | Where tooltip appears |
opensOn | string | 'Auto' | Trigger: Auto/Hover/Click/Focus/Custom |
isSticky | boolean | false | Keep open until manually closed |
mouseTrail | boolean | false | Follow mouse pointer |
openDelay | number | 0 | Delay (ms) before opening |
closeDelay | number | 0 | Delay (ms) before closing |
animation | AnimationModel | FadeIn/FadeOut 150ms | Open/close animation |
target | string | — | Selector for multi-target |
cssClass | string | null | Custom CSS class |
showTipPointer | boolean | true | Show/hide arrow tip |
width / height | `string \ | number` | 'auto' |
For full property, method, and event reference, read references/api.md.
Accessibility and Forms
Table of Contents
- WCAG 2.2 Level AA Compliance
- ARIA Attributes
- Keyboard Navigation
- Screen Reader Support
- Form Validation Patterns
- Reactive Forms
- Template-Driven Forms
- Examples
WCAG 2.2 Level AA Compliance
The Dialog component follows WCAG 2.2 Level AA standards for accessibility:
Accessibility Standards Met
- ✅ Perceivable - Dialog is visible and distinguishable
- ✅ Operable - Keyboard and mouse navigation supported
- ✅ Understandable - Clear content and instructions
- ✅ Robust - Compatible with assistive technologies
ADA & Section 508 Compliance
The Dialog is compliant with:
- Americans with Disabilities Act (ADA)
- Section 508 (US Federal requirement)
- EN 301 549 (EU accessibility standard)
Implementation Checklist
@Component({
template: `
<div role="main">
<!-- Dialog with accessibility attributes -->
<ejs-dialog
role="dialog"
[aria-labelledby]="'dialog-title'"
[aria-describedby]="'dialog-description'"
[aria-modal]="true"
[showCloseIcon]="true"
>
<ng-template #header>
<h2 id="dialog-title">Important Information</h2>
</ng-template>
<ng-template #content>
<p id="dialog-description">
This dialog contains important accessibility features.
</p>
</ng-template>
</ejs-dialog>
</div>
`
})
export class AccessibleDialogComponent {}ARIA Attributes
aria-labelledby
Connects the dialog header/title to the dialog element:
@Component({
template: `
<ejs-dialog
[aria-labelledby]="'dialog-header-id'"
width="400px"
>
<ng-template #header>
<h2 id="dialog-header-id">Delete Confirmation</h2>
</ng-template>
<ng-template #content>
<p>Are you sure you want to delete this item?</p>
</ng-template>
</ejs-dialog>
`
})
export class AriaLabelledByComponent {}aria-describedby
Provides additional description for the dialog:
@Component({
template: `
<ejs-dialog
[aria-describedby]="'dialog-description'"
width="400px"
>
<ng-template #content>
<p id="dialog-description">
This is a modal dialog that requires your interaction.
Press Tab to navigate between elements,
Escape to close, and Enter to confirm.
</p>
</ng-template>
</ejs-dialog>
`
})
export class AriaDescribedByComponent {}aria-modal
Indicates whether the dialog is modal or not:
@Component({
template: `
<!-- Modal dialog -->
<ejs-dialog
[isModal]="true"
[aria-modal]="true"
content="Modal dialog - blocks interaction"
>
</ejs-dialog>
<!-- Modeless dialog -->
<ejs-dialog
[isModal]="false"
[aria-modal]="false"
content="Modeless dialog - allows interaction"
>
</ejs-dialog>
`
})
export class AriaModalComponent {}Keyboard Navigation
Tab Navigation
Focus moves through dialog elements in order:
@Component({
template: `
<ejs-dialog
[showCloseIcon]="true"
content="Tab through elements"
>
<ng-template #content>
<form>
<div>
<label for="name">Name:</label>
<input id="name" type="text" placeholder="Enter name" />
</div>
<div>
<label for="email">Email:</label>
<input id="email" type="email" placeholder="Enter email" />
</div>
<textarea id="message" placeholder="Enter message"></textarea>
</form>
</ng-template>
</ejs-dialog>
`
})
export class TabNavigationComponent {}Escape Key
Close dialog with Escape:
@Component({
template: `
<ejs-dialog
#dialog
[closeOnEscape]="true"
content="Press Escape to close"
>
</ejs-dialog>
`
})
export class EscapeKeyComponent {
@ViewChild('dialog') dialog!: DialogComponent;
}Enter Key
Trigger primary action:
@Component({
template: `
<ejs-dialog #dialog>
<ng-template #content>
<form (ngSubmit)="onSubmit()">
<input type="text" placeholder="Enter text" />
<!-- Pressing Enter in input triggers primary button -->
</form>
</ng-template>
<ng-template #footer>
<button
class="e-control e-btn e-primary"
(click)="onSubmit()"
>
Submit
</button>
<button
class="e-control e-btn"
(click)="dialog.hide()"
>
Cancel
</button>
</ng-template>
</ejs-dialog>
`
})
export class EnterKeyComponent {
@ViewChild('dialog') dialog!: DialogComponent;
onSubmit(): void {
console.log('Form submitted');
this.dialog.hide();
}
}Shift+Tab
Navigate backwards through elements:
@Component({
template: `
<ejs-dialog content="Shift+Tab navigates backwards">
<ng-template #content>
<button>Button 1</button>
<button>Button 2</button>
<button>Button 3</button>
<!-- Shift+Tab goes backwards -->
</ng-template>
</ejs-dialog>
`
})
export class ShiftTabComponent {}Screen Reader Support
Labeling Dialog Content
@Component({
template: `
<ejs-dialog
[aria-labelledby]="'dialog-title'"
[aria-describedby]="'dialog-desc'"
>
<ng-template #header>
<h2 id="dialog-title">User Profile</h2>
</ng-template>
<ng-template #content>
<div id="dialog-desc">
<p>Update your user profile information below:</p>
<form>
<div>
<label for="fname">First Name:</label>
<input id="fname" type="text" />
</div>
<div>
<label for="lname">Last Name:</label>
<input id="lname" type="text" />
</div>
</form>
</div>
</ng-template>
</ejs-dialog>
`
})
export class ScreenReaderComponent {}Live Regions
Announce dynamic content to screen readers:
@Component({
template: `
<ejs-dialog>
<ng-template #content>
<div aria-live="polite" aria-atomic="true">
{{ statusMessage }}
</div>
<button (click)="performAction()">Perform Action</button>
</ng-template>
</ejs-dialog>
`
})
export class LiveRegionComponent {
statusMessage = 'Ready';
performAction(): void {
this.statusMessage = 'Processing...';
setTimeout(() => {
this.statusMessage = 'Action completed successfully!';
}, 2000);
}
}Focus Management
Ensure focus returns to trigger element:
@Component({
template: `
<button
#triggerButton
(click)="openDialog()"
>
Open Dialog
</button>
<ejs-dialog
#dialog
(close)="returnFocus()"
>
</ejs-dialog>
`
})
export class FocusManagementComponent {
@ViewChild('dialog') dialog!: DialogComponent;
@ViewChild('triggerButton') triggerButton!: ElementRef;
openDialog(): void {
this.dialog.show();
}
returnFocus(): void {
// Return focus to trigger button after dialog closes
this.triggerButton.nativeElement.focus();
}
}Form Validation Patterns
Basic Form with Validation
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
template: `
<ejs-dialog #dialog>
<ng-template #header>
<h2>User Registration</h2>
</ng-template>
<ng-template #content>
<form [formGroup]="form">
<div>
<label for="email">Email:</label>
<input
id="email"
type="email"
formControlName="email"
placeholder="Enter email"
aria-describedby="email-error"
/>
<span
id="email-error"
*ngIf="form.get('email')?.hasError('required')"
role="alert"
>
Email is required
</span>
</div>
<div>
<label for="password">Password:</label>
<input
id="password"
type="password"
formControlName="password"
placeholder="Enter password"
aria-describedby="password-error"
/>
<span
id="password-error"
*ngIf="form.get('password')?.hasError('minlength')"
role="alert"
>
Password must be at least 6 characters
</span>
</div>
</form>
</ng-template>
<ng-template #footer>
<button
class="e-control e-btn e-primary"
[disabled]="!form.valid"
(click)="onSubmit()"
>
Register
</button>
</ng-template>
</ejs-dialog>
`
})
export class BasicValidationComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
email: ['', [Validators.required, Validators.email]],
password: ['', [Validators.required, Validators.minLength(6)]]
});
}
onSubmit(): void {
if (this.form.valid) {
console.log(this.form.value);
}
}
}Reactive Forms
Complete Reactive Form in Dialog
import { Component, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
selector: 'app-reactive-form-dialog',
standalone: true,
imports: [DialogModule, ReactiveFormsModule, CommonModule],
template: `
<div id="dialog-container" style="height: 600px;">
<button class="e-control e-btn" (click)="openDialog()">
Edit Profile
</button>
<ejs-dialog
#profileDialog
[showCloseIcon]="true"
width="500px"
>
<ng-template #header>
<h2>Edit User Profile</h2>
</ng-template>
<ng-template #content>
<form [formGroup]="profileForm">
<div class="form-group">
<label for="firstname">First Name:</label>
<input
id="firstname"
type="text"
formControlName="firstName"
placeholder="Enter first name"
/>
<span *ngIf="profileForm.get('firstName')?.invalid && profileForm.get('firstName')?.touched">
First name is required
</span>
</div>
<div class="form-group">
<label for="lastname">Last Name:</label>
<input
id="lastname"
type="text"
formControlName="lastName"
placeholder="Enter last name"
/>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input
id="email"
type="email"
formControlName="email"
placeholder="Enter email"
/>
<span *ngIf="profileForm.get('email')?.invalid && profileForm.get('email')?.touched">
Invalid email format
</span>
</div>
<div class="form-group">
<label for="country">Country:</label>
<select id="country" formControlName="country">
<option>Select country</option>
<option value="us">United States</option>
<option value="uk">United Kingdom</option>
<option value="ca">Canada</option>
</select>
</div>
</form>
</ng-template>
<ng-template #footer>
<button
class="e-control e-btn e-primary"
[disabled]="!profileForm.valid"
(click)="onSaveProfile()"
>
Save Changes
</button>
<button
class="e-control e-btn"
(click)="profileDialog.hide()"
>
Cancel
</button>
</ng-template>
</ejs-dialog>
</div>
`,
styles: [`
#dialog-container { height: 600px; padding: 20px; }
.form-group { margin-bottom: 15px; }
label { display: block; font-weight: bold; margin-bottom: 5px; }
input, select { width: 100%; padding: 8px; border: 1px solid #ddd; }
span { color: red; font-size: 12px; margin-top: 3px; display: block; }
`]
})
export class ReactiveFormDialogComponent {
@ViewChild('profileDialog') dialog!: DialogComponent;
profileForm: FormGroup;
constructor(private fb: FormBuilder) {
this.profileForm = this.fb.group({
firstName: ['', Validators.required],
lastName: [''],
email: ['', [Validators.required, Validators.email]],
country: ['']
});
}
openDialog(): void {
this.dialog.show();
}
onSaveProfile(): void {
if (this.profileForm.valid) {
console.log('Profile saved:', this.profileForm.value);
this.dialog.hide();
}
}
}Template-Driven Forms
Complete Template-Driven Form in Dialog
@Component({
selector: 'app-template-form-dialog',
standalone: true,
imports: [DialogModule, FormsModule],
template: `
<div id="dialog-container" style="height: 600px;">
<button class="e-control e-btn" (click)="openDialog()">
Add New Item
</button>
<ejs-dialog
#itemDialog
[showCloseIcon]="true"
width="450px"
>
<ng-template #header>
<h2>Add New Item</h2>
</ng-template>
<ng-template #content>
<form #itemForm="ngForm" (ngSubmit)="onSubmitItem()">
<div class="form-group">
<label for="itemname">Item Name:</label>
<input
id="itemname"
type="text"
name="itemName"
[(ngModel)]="item.name"
required
placeholder="Enter item name"
/>
</div>
<div class="form-group">
<label for="itemdesc">Description:</label>
<textarea
id="itemdesc"
name="description"
[(ngModel)]="item.description"
placeholder="Enter description"
></textarea>
</div>
<div class="form-group">
<label for="quantity">Quantity:</label>
<input
id="quantity"
type="number"
name="quantity"
[(ngModel)]="item.quantity"
required
/>
</div>
<div class="form-group">
<label for="price">Price:</label>
<input
id="price"
type="number"
name="price"
[(ngModel)]="item.price"
required
/>
</div>
<div class="form-group checkbox">
<input
id="instock"
type="checkbox"
name="inStock"
[(ngModel)]="item.inStock"
/>
<label for="instock">In Stock</label>
</div>
</form>
</ng-template>
<ng-template #footer>
<button
class="e-control e-btn e-primary"
[disabled]="!itemForm.valid"
(click)="onSubmitItem()"
>
Add Item
</button>
<button
class="e-control e-btn"
(click)="itemDialog.hide()"
>
Cancel
</button>
</ng-template>
</ejs-dialog>
</div>
`,
styles: [`
#dialog-container { height: 600px; padding: 20px; }
.form-group { margin-bottom: 15px; }
label { display: block; font-weight: bold; margin-bottom: 5px; }
input, textarea { width: 100%; padding: 8px; border: 1px solid #ddd; }
.checkbox { display: flex; align-items: center; }
.checkbox input { width: auto; margin-right: 8px; }
`]
})
export class TemplateFormDialogComponent {
@ViewChild('itemDialog') dialog!: DialogComponent;
item = {
name: '',
description: '',
quantity: 0,
price: 0,
inStock: false
};
openDialog(): void {
this.dialog.show();
}
onSubmitItem(): void {
console.log('Item added:', this.item);
this.dialog.hide();
}
}Examples
Example 1: Accessible Confirmation Dialog
@Component({
template: `
<ejs-dialog
[isModal]="true"
[closeOnEscape]="true"
role="alertdialog"
[aria-labelledby]="'confirm-title'"
[aria-describedby]="'confirm-desc'"
>
<ng-template #header>
<h2 id="confirm-title">⚠️ Confirm Action</h2>
</ng-template>
<ng-template #content>
<p id="confirm-desc">This action cannot be undone.</p>
</ng-template>
<ng-template #footer>
<button class="e-control e-btn" (click)="onCancel()">
Cancel (Esc)
</button>
<button class="e-control e-btn e-primary" (click)="onConfirm()">
Confirm (Enter)
</button>
</ng-template>
</ejs-dialog>
`
})
export class AccessibleConfirmComponent {}Advanced Patterns
Table of Contents
- Nested Dialogs
- Ajax-Loaded Content
- Utility Functions
- Complex Layouts
- Scroll Handling & Centering
- Custom Event Emitters
- Routing Integration
- Examples
Nested Dialogs
Creating Nested Dialogs
Nested dialogs are dialogs within dialogs - useful for multi-level workflows:
import { Component, ViewChild } from '@angular/core';
import { DialogModule, DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
selector: 'app-nested-dialogs',
standalone: true,
imports: [DialogModule],
template: `
<div id="dialog-container" style="height: 600px;">
<button class="e-control e-btn" (click)="openParent()">
Open Parent Dialog
</button>
<!-- Parent Dialog -->
<ejs-dialog
#parentDialog
[showCloseIcon]="true"
width="500px"
position="TopLeft"
content="This is the parent dialog"
>
<ng-template #header>
<span>Parent Dialog</span>
</ng-template>
<ng-template #content>
<p>Parent dialog content</p>
<button
class="e-control e-btn"
(click)="openChild()"
>
Open Child Dialog
</button>
<!-- Nested Child Dialog -->
<ejs-dialog
#childDialog
[showCloseIcon]="true"
width="350px"
position="Center"
content="This is the child dialog"
>
<ng-template #header>
<span>Child Dialog (Nested)</span>
</ng-template>
</ejs-dialog>
</ng-template>
</ejs-dialog>
</div>
`
})
export class NestedDialogsComponent {
@ViewChild('parentDialog') parentDialog!: DialogComponent;
@ViewChild('childDialog') childDialog!: DialogComponent;
openParent(): void {
this.parentDialog.show();
}
openChild(): void {
this.childDialog.show();
}
}Cascading Nested Dialogs
Multiple dialogs at different positions:
@Component({
template: `
<div id="dialog-container" style="height: 600px;">
<button (click)="openDialog1()">Level 1</button>
<ejs-dialog
#dialog1
[position]="{ X: 50, Y: 50 }"
width="300px"
[allowDragging]="true"
>
<ng-template #header><span>Dialog 1</span></ng-template>
<ng-template #content>
<button (click)="openDialog2()">Open Level 2</button>
</ng-template>
</ejs-dialog>
<ejs-dialog
#dialog2
[position]="{ X: 150, Y: 150 }"
width="250px"
[allowDragging]="true"
>
<ng-template #header><span>Dialog 2</span></ng-template>
<ng-template #content>
<button (click)="openDialog3()">Open Level 3</button>
</ng-template>
</ejs-dialog>
<ejs-dialog
#dialog3
[position]="{ X: 250, Y: 250 }"
width="200px"
[allowDragging]="true"
>
<ng-template #header><span>Dialog 3</span></ng-template>
<ng-template #content>
<p>Deepest level</p>
</ng-template>
</ejs-dialog>
</div>
`
})
export class CascadingDialogsComponent {
@ViewChild('dialog1') dialog1!: DialogComponent;
@ViewChild('dialog2') dialog2!: DialogComponent;
@ViewChild('dialog3') dialog3!: DialogComponent;
openDialog1(): void { this.dialog1.show(); }
openDialog2(): void { this.dialog2.show(); }
openDialog3(): void { this.dialog3.show(); }
}Ajax-Loaded Content
Loading Content from Server
import { HttpClient } from '@angular/common/http';
import { Component, ViewChild } from '@angular/core';
import { DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
selector: 'app-ajax-content',
standalone: true,
imports: [DialogModule],
template: `
<div id="dialog-container" style="height: 600px;">
<button (click)="openDialog()">Load Content</button>
<ejs-dialog
#dialog
[showCloseIcon]="true"
(open)="onDialogOpen()"
width="500px"
>
<ng-template #header>
<span>{{ dialogTitle }}</span>
</ng-template>
<ng-template #content>
<div *ngIf="isLoading" class="loading">
<p>Loading content...</p>
</div>
<div *ngIf="!isLoading && content" [innerHTML]="content">
</div>
</ng-template>
</ejs-dialog>
</div>
`,
styles: [`
.loading {
text-align: center;
padding: 20px;
}
`]
})
export class AjaxContentComponent {
@ViewChild('dialog') dialog!: DialogComponent;
content: string | null = null;
dialogTitle = 'Loading...';
isLoading = false;
constructor(private http: HttpClient) {}
openDialog(): void {
this.dialog.show();
}
onDialogOpen(): void {
if (!this.content) {
this.loadContent();
}
}
loadContent(): void {
this.isLoading = true;
this.http.get('/api/dialog-content', { responseType: 'text' })
.subscribe({
next: (data) => {
this.content = data;
this.dialogTitle = 'Content Loaded';
this.isLoading = false;
},
error: () => {
this.content = '<p>Error loading content</p>';
this.isLoading = false;
}
});
}
}Progressive Content Loading
@Component({
template: `
<ejs-dialog (open)="onOpen()">
<ng-template #content>
<div *ngFor="let section of sections">
<h3>{{ section.title }}</h3>
<p *ngIf="section.content">{{ section.content }}</p>
<p *ngIf="!section.content" class="loading">Loading...</p>
</div>
</ng-template>
</ejs-dialog>
`
})
export class ProgressiveLoadingComponent {
sections = [
{ title: 'Section 1', content: null },
{ title: 'Section 2', content: null },
{ title: 'Section 3', content: null }
];
constructor(private http: HttpClient) {}
onOpen(): void {
this.sections.forEach((section, index) => {
setTimeout(() => {
this.http.get(`/api/content/${index}`, { responseType: 'text' })
.subscribe(data => {
section.content = data;
});
}, index * 500);
});
}
}Utility Functions
Programmatic Dialog Creation
import { Component } from '@angular/core';
import { DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
template: `
<div id="dialog-container" style="height: 600px;">
<button (click)="createDialog()">Create Dialog Dynamically</button>
<button (click)="showAlert()">Show Alert</button>
<button (click)="showConfirm()">Show Confirm</button>
</div>
`
})
export class DialogUtilityComponent {
createDialog(): void {
const dialogElement = document.createElement('ejs-dialog');
dialogElement.id = 'dynamic-dialog';
dialogElement.setAttribute('content', 'Dynamically created dialog');
dialogElement.setAttribute('[showCloseIcon]', 'true');
const container = document.getElementById('dialog-container');
container?.appendChild(dialogElement);
}
showAlert(message: string): void {
alert(message || 'Alert dialog');
}
showConfirm(): void {
const confirmed = confirm('Are you sure?');
console.log('User confirmed:', confirmed);
}
}Dialog Manager Service
import { Injectable, ViewContainerRef } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class DialogService {
private dialogs: DialogComponent[] = [];
openDialog(config: {
title: string;
content: string;
buttons?: any[];
width?: string;
}): DialogComponent {
// Create dialog instance
const dialog = new DialogComponent();
dialog.header = config.title;
dialog.content = config.content;
dialog.buttons = config.buttons;
dialog.width = config.width || '400px';
this.dialogs.push(dialog);
dialog.show();
return dialog;
}
closeDialog(dialog: DialogComponent): void {
dialog.hide();
const index = this.dialogs.indexOf(dialog);
if (index > -1) {
this.dialogs.splice(index, 1);
}
}
closeAllDialogs(): void {
this.dialogs.forEach(d => d.hide());
this.dialogs = [];
}
getOpenDialogsCount(): number {
return this.dialogs.length;
}
}Complex Layouts
Dialog with Rich Text Editor
@Component({
template: `
<ejs-dialog #dialog width="600px">
<ng-template #header>
<span>Rich Content Editor</span>
</ng-template>
<ng-template #content>
<div class="editor-container">
<textarea id="editor" [(ngModel)]="content"></textarea>
</div>
</ng-template>
<ng-template #footer>
<button class="e-control e-btn e-primary" (click)="onSave()">
Save
</button>
</ng-template>
</ejs-dialog>
`,
styles: [`
.editor-container {
min-height: 300px;
border: 1px solid #ddd;
padding: 10px;
}
textarea {
width: 100%;
min-height: 300px;
border: none;
font-family: monospace;
}
`]
})
export class RichContentDialogComponent {
@ViewChild('dialog') dialog!: DialogComponent;
content = '';
onSave(): void {
console.log('Saved content:', this.content);
this.dialog.hide();
}
}Multi-Column Dialog
@Component({
template: `
<ejs-dialog width="800px">
<ng-template #content>
<div class="multi-column-layout">
<div class="column-left">
<h3>Options</h3>
<ul>
<li *ngFor="let option of options">
{{ option }}
</li>
</ul>
</div>
<div class="column-right">
<h3>Preview</h3>
<p>Selected option preview</p>
</div>
</div>
</ng-template>
</ejs-dialog>
`,
styles: [`
.multi-column-layout {
display: flex;
gap: 20px;
}
.column-left, .column-right {
flex: 1;
}
.column-left ul {
list-style: none;
padding: 0;
}
.column-left li {
padding: 8px;
background: #f5f5f5;
margin-bottom: 5px;
cursor: pointer;
}
`]
})
export class MultiColumnDialogComponent {
options = ['Option 1', 'Option 2', 'Option 3', 'Option 4'];
}Scroll Handling & Centering
Auto-Center on Scroll
@Component({
template: `
<div id="dialog-container" style="height: 1000px;">
<div style="height: 500px;">Scroll down...</div>
<ejs-dialog
#dialog
position="Center"
content="This stays centered during scroll"
>
</ejs-dialog>
</div>
`
})
export class AutoCenterComponent {
@ViewChild('dialog') dialog!: DialogComponent;
@HostListener('window:scroll', [])
onScroll(): void {
// Dialog automatically centers in viewport
}
}Manual Centering Function
@Component({
template: `
<ejs-dialog #dialog width="500px">
<ng-template #header>
<span>Centered Dialog</span>
</ng-template>
</ejs-dialog>
`
})
export class ManualCenterComponent {
@ViewChild('dialog') dialog!: DialogComponent;
centerDialog(): void {
const dialogElement = document.querySelector('.e-dialog') as HTMLElement;
if (dialogElement) {
const windowHeight = window.innerHeight;
const windowWidth = window.innerWidth;
const dialogHeight = dialogElement.offsetHeight;
const dialogWidth = dialogElement.offsetWidth;
const top = (windowHeight - dialogHeight) / 2;
const left = (windowWidth - dialogWidth) / 2;
dialogElement.style.top = `${top}px`;
dialogElement.style.left = `${left}px`;
}
}
}Custom Event Emitters
Dialog Events with Output
import { Component, EventEmitter, Output, ViewChild } from '@angular/core';
import { DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
selector: 'app-custom-dialog',
standalone: true,
imports: [DialogModule],
template: `
<ejs-dialog
#dialog
(open)="onOpen()"
(close)="onClose()"
>
</ejs-dialog>
`
})
export class CustomDialogComponent {
@ViewChild('dialog') dialog!: DialogComponent;
@Output() dialogOpened = new EventEmitter<void>();
@Output() dialogClosed = new EventEmitter<void>();
onOpen(): void {
this.dialogOpened.emit();
}
onClose(): void {
this.dialogClosed.emit();
}
}
// Usage in parent
@Component({
template: `
<app-custom-dialog
(dialogOpened)="onDialogOpened()"
(dialogClosed)="onDialogClosed()"
>
</app-custom-dialog>
`
})
export class ParentComponent {
onDialogOpened(): void {
console.log('Custom dialog opened event received');
}
onDialogClosed(): void {
console.log('Custom dialog closed event received');
}
}Routing Integration
Dialog with Route Parameters
import { ActivatedRoute } from '@angular/router';
import { Component, ViewChild } from '@angular/core';
import { DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
selector: 'app-route-dialog',
standalone: true,
imports: [DialogModule],
template: `
<ejs-dialog
#dialog
(open)="onOpen()"
>
<ng-template #header>
<span>{{ itemName }}</span>
</ng-template>
<ng-template #content>
<p>Details for item ID: {{ itemId }}</p>
</ng-template>
</ejs-dialog>
`
})
export class RouteDialogComponent {
@ViewChild('dialog') dialog!: DialogComponent;
itemId: string | null = null;
itemName: string = 'Item';
constructor(private route: ActivatedRoute) {}
ngOnInit(): void {
this.route.queryParams.subscribe(params => {
this.itemId = params['id'];
this.itemName = params['name'] || 'Item';
this.dialog.show();
});
}
onOpen(): void {
console.log('Dialog opened for item:', this.itemId);
}
}Dialog in Modal Routing
@Component({
selector: 'app-modal-route',
template: `
<ejs-dialog
#dialog
[isModal]="true"
(beforeClose)="onBeforeClose($event)"
>
<ng-template #header>
<span>Modal Dialog Route</span>
</ng-template>
<ng-template #content>
<p>This dialog is shown as a modal route.</p>
</ng-template>
<ng-template #footer>
<button class="e-control e-btn" (click)="closeAndNavigate()">
Done
</button>
</ng-template>
</ejs-dialog>
`
})
export class ModalRouteComponent {
@ViewChild('dialog') dialog!: DialogComponent;
constructor(
private route: Router,
private activatedRoute: ActivatedRoute
) {}
closeAndNavigate(): void {
this.dialog.hide();
this.route.navigate(['..'], { relativeTo: this.activatedRoute });
}
onBeforeClose(args: any): void {
if (!this.isDataSaved()) {
args.cancel = true;
alert('Save your changes before closing');
}
}
isDataSaved(): boolean {
return true;
}
}Examples
Example 1: Confirmation Dialog with Async Operation
@Component({
template: `
<ejs-dialog
#dialog
[isModal]="true"
(beforeClose)="onBeforeClose($event)"
>
<ng-template #header>
<span>Confirm Action</span>
</ng-template>
<ng-template #content>
<p>{{ message }}</p>
<div *ngIf="isProcessing" class="spinner">
Processing...
</div>
</ng-template>
<ng-template #footer>
<button
class="e-control e-btn"
[disabled]="isProcessing"
(click)="dialog.hide()"
>
Cancel
</button>
<button
class="e-control e-btn e-primary"
[disabled]="isProcessing"
(click)="confirmAction()"
>
{{ isProcessing ? 'Processing...' : 'Confirm' }}
</button>
</ng-template>
</ejs-dialog>
`
})
export class ConfirmationWithAsyncComponent {
@ViewChild('dialog') dialog!: DialogComponent;
message = 'Are you sure you want to proceed?';
isProcessing = false;
confirmAction(): void {
this.isProcessing = true;
// Simulate async operation
this.performAsyncOperation()
.then(() => {
console.log('Operation completed');
this.dialog.hide();
})
.catch(error => {
alert('Error: ' + error);
})
.finally(() => {
this.isProcessing = false;
});
}
performAsyncOperation(): Promise<void> {
return new Promise(resolve => {
setTimeout(() => resolve(), 2000);
});
}
onBeforeClose(args: any): void {
if (this.isProcessing) {
args.cancel = true;
}
}
}Dialog Component - Complete API Reference
Official Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/
This document provides comprehensive API reference for the Syncfusion Angular Dialog component, extracted from the official Syncfusion documentation.
Table of Contents
---
Component Overview
The DialogComponent represents the Angular Dialog Component from the Syncfusion Popups library. It provides a flexible window for displaying information, collecting user input, or confirming actions.
Module: @syncfusion/ej2-angular-popups Import: import { DialogModule, DialogComponent } from '@syncfusion/ej2-angular-popups';
---
Properties
allowDragging: boolean
Description: Specifies whether the dialog component can be dragged by the end-user. The dialog allows dragging by selecting the header and moving it to reposition the dialog.
Default: false
Example:
<ejs-dialog [allowDragging]="true" header="Draggable Dialog">
</ejs-dialog>Related Documentation: https://ej2.syncfusion.com/angular/documentation/dialog/getting-started/#draggable
---
animationSettings: AnimationSettingsModel
Description: Specifies the animation settings of the dialog component. The animation effect can be applied when opening and closing the dialog with configurable duration and delay.
Type: AnimationSettingsModel
Properties:
effect: Animation effect type (Fade, Zoom, FadeZoom, SlideLeft, SlideRight, SlideUp, SlideDown, Flip, Bounce)duration: Duration of animation in millisecondsdelay: Delay before animation starts in milliseconds
Example:
animationSettings: AnimationSettingsModel = {
effect: 'FadeZoom',
duration: 400
};
<ejs-dialog [animationSettings]="animationSettings">
</ejs-dialog>Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/animationsettingsmodel
---
buttons: ButtonPropsModel[]
Description: Configures the action buttons that contain button properties with primary attributes and click events. One or more action buttons can be configured to the dialog.
Type: ButtonPropsModel[]
Properties:
text: Display text of the buttoncssClass: CSS class for styling (e.g., 'e-primary', 'e-danger', 'e-outline')click: Click event handler functiondisabled: Whether button is disabled
Example:
buttons = [
{
text: 'Save',
cssClass: 'e-primary',
click: () => this.onSave()
},
{
text: 'Cancel',
click: () => this.dialog.hide()
}
];
<ejs-dialog [buttons]="buttons">
</ejs-dialog>Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/buttonpropsmodel
---
closeOnEscape: boolean
Description: Specifies whether the dialog can be closed by pressing the Escape key. This is used to control the dialog's closing behavior via keyboard.
Default: true
Example:
<ejs-dialog [closeOnEscape]="true">
</ejs-dialog>---
content: string | HTMLElement | Function
Description: Specifies the value that can be displayed in the dialog's content area. Can be plain text, HTML string, or HTML elements. Content can be loaded dynamically (database, AJAX, etc.).
Type: string | HTMLElement | Function
Example:
// String content
<ejs-dialog content="This is dialog content">
</ejs-dialog>
// HTML content
content = '<h3>Welcome</h3><p>This is HTML content</p>';
<ejs-dialog [content]="content">
</ejs-dialog>
// Template content
<ejs-dialog>
<ng-template #content>
<div>Template-based content</div>
</ng-template>
</ejs-dialog>---
cssClass: string
Description: Specifies CSS class name(s) that can be appended to the root element of the dialog. One or more custom CSS classes can be added for styling.
Type: string
Example:
<ejs-dialog cssClass="custom-dialog-class e-dialog-custom">
</ejs-dialog>
// CSS
.e-dialog.custom-dialog-class {
background-color: #f0f0f0;
}---
enableHtmlSanitizer: boolean
Description: Defines whether to allow or prevent cross-site scripting (XSS) by sanitizing HTML content.
Default: true
Example:
<ejs-dialog [enableHtmlSanitizer]="true">
</ejs-dialog>---
enablePersistence: boolean
Description: Enables or disables persistence of the dialog's dimensions and position state between page reloads.
Default: false
Example:
<ejs-dialog [enablePersistence]="true">
</ejs-dialog>---
enableResize: boolean
Description: Specifies whether the dialog component can be resized by the end-user. If enabled, the dialog creates a grip to resize in diagonal directions.
Default: false
Example:
<ejs-dialog [enableResize]="true">
</ejs-dialog>Related: Use with resizeHandles property
---
enableRtl: boolean
Description: Enable or disable rendering the component in right-to-left (RTL) direction for RTL languages.
Default: false
Example:
<ejs-dialog [enableRtl]="true">
</ejs-dialog>---
footerTemplate: HTMLElement | string | Function
Description: Specifies the template value that can be displayed in the dialog's footer area. This is optional and used when the footer contains custom information or components. If configured, the action buttons property is disabled.
Type: HTMLElement | string | Function
Example:
<ejs-dialog>
<ng-template #footer>
<div style="padding: 10px;">
<button (click)="onCustomAction()">Custom Button</button>
</div>
</ng-template>
</ejs-dialog>Related Documentation: https://ej2.syncfusion.com/angular/documentation/dialog/template/#footer
---
header: string | HTMLElement | Function
Description: Specifies the value that can be displayed in the dialog's title area, configured with plain text or HTML elements. This is optional; the dialog can be displayed without a header if null.
Type: string | HTMLElement | Function
Example:
// String header
<ejs-dialog header="Dialog Title">
</ejs-dialog>
// Template header
<ejs-dialog>
<ng-template #header>
<div class="custom-header">
<span>Custom Title</span>
</div>
</ng-template>
</ejs-dialog>---
height: string | number
Description: Specifies the height of the dialog component. Can be in pixels (px) or as a number.
Type: string | number
Example:
<ejs-dialog height="400px">
</ejs-dialog>
// Or as number (interpreted as pixels)
<ejs-dialog [height]="400">
</ejs-dialog>---
isModal: boolean
Description: Specifies whether the dialog is displayed as modal or non-modal (modeless).
Values:
true(Modal): Creates overlay that disables interaction with parent application. User must respond to the modal.false(Modeless): Does not prevent user interaction with parent application.
Default: false
Example:
// Modal dialog (blocks parent interaction)
<ejs-dialog [isModal]="true">
</ejs-dialog>
// Modeless dialog (allows parent interaction)
<ejs-dialog [isModal]="false" [allowDragging]="true">
</ejs-dialog>Related Documentation: https://ej2.syncfusion.com/angular/documentation/dialog/getting-started/
---
locale: string
Description: Overrides the global culture and localization value for this component. Defaults to global culture 'en-US'.
Type: string
Example:
<ejs-dialog locale="fr-FR">
</ejs-dialog>---
minHeight: string | number
Description: Specifies the minimum height of the dialog component. Prevents the dialog from being resized below this value.
Type: string | number
Example:
<ejs-dialog [minHeight]="200">
</ejs-dialog>
// Or with string
<ejs-dialog minHeight="200px">
</ejs-dialog>---
position: PositionDataModel
Description: Specifies where the dialog is positioned within the document or target element. Can use pre-configured positions or specific X and Y values.
Type: PositionDataModel
Pre-configured Positions:
TopLeft,TopCenter,TopRightMiddleLeft,Center,MiddleRightBottomLeft,BottomCenter,BottomRight
X Value: left, center, right, or numeric offset Y Value: top, center, bottom, or numeric offset
Example:
// Pre-configured position
<ejs-dialog position="Center">
</ejs-dialog>
// Custom X and Y
position: PositionDataModel = { X: 'center', Y: 'top' };
<ejs-dialog [position]="position">
</ejs-dialog>
// Pixel offset
position: PositionDataModel = { X: 100, Y: 50 };
<ejs-dialog [position]="position">
</ejs-dialog>Related Documentation: https://ej2.syncfusion.com/angular/documentation/dialog/getting-started/#positioning
---
resizeHandles: ResizeDirections[]
Description: Specifies the resize handles direction in the dialog that can be resized by the end-user.
Type: ResizeDirections[]
Valid Values:
'All'- All directions'NorthEast','NorthWest','SouthEast','SouthWest'- Corners'North','South','East','West'- Sides
Example:
// All resize handles
<ejs-dialog [resizeHandles]="['All']" [enableResize]="true">
</ejs-dialog>
// Specific handles
<ejs-dialog [resizeHandles]="['SouthEast', 'South', 'East']" [enableResize]="true">
</ejs-dialog>Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/resizedirections
---
showCloseIcon: boolean
Description: Specifies whether the close icon is shown in the dialog component's header.
Default: false
Example:
<ejs-dialog [showCloseIcon]="true">
</ejs-dialog>---
target: HTMLElement | string
Description: Specifies the target element in which to display the dialog. Defaults to document.body if not specified.
Type: HTMLElement | string
⚠️ Height Calculation: The Dialog'smax-heightis calculated based on the height of the target element. Iftargetis not set,document.bodyis used — ensure the body has a proper height. If the dialog's height exceeds the target's height, the dialog height will not render correctly.
Target Container Requirements:
- The target element must have
position: relative(orabsolute/fixed) - The target element must have an explicit
heightormin-height - When using
document.body(default), sethtml, body { height: 100%; }in CSS
Example:
// Target by ID — container must have explicit height and position: relative
<div id="dialog-container" style="height: 500px; position: relative;">
<ejs-dialog target="#dialog-container">
</ejs-dialog>
</div>When the target is `document.body` (default):
/* styles.css — required for correct dialog height when no target is set */
html, body {
height: 100%;
margin: 0;
}Issue to avoid: If the dialog's height is larger than the body's height and no explicit target is configured, the dialog height will not be set correctly.
---
visible: boolean
Description: Specifies whether the dialog component is visible.
Default: true
Example:
<ejs-dialog [visible]="true">
</ejs-dialog>---
width: string | number
Description: Specifies the width of the dialog.
Type: string | number
Example:
// Pixel width
<ejs-dialog width="400px">
</ejs-dialog>
// Percentage width
<ejs-dialog width="80%">
</ejs-dialog>
// As number (interpreted as pixels)
<ejs-dialog [width]="400">
</ejs-dialog>---
zIndex: number
Description: Specifies the z-order for rendering that determines whether the dialog is displayed in front or behind of another component.
Type: number
Example:
<ejs-dialog [zIndex]="1000">
</ejs-dialog>---
Methods
show()
Description: Opens the dialog if it is in hidden state. To open the dialog with full screen width, set the optional parameter to true.
Parameters:
isFullScreen(optional):boolean— Enable the fullScreen Dialog.
Return Type: void
Example:
@ViewChild('dialog') dialog!: DialogComponent;
openDialog() {
this.dialog.show();
}
openFullScreen() {
this.dialog.show(true);
}---
hide()
Description: Closes/hides the dialog component.
Return Type: void
Example:
closeDialog() {
this.dialog.hide();
}---
refreshPosition()
Description: Refreshes the dialog's position when the user changes its header and footer height/width dynamically.
Return Type: void
Example:
refreshDialogPosition() {
this.dialog.refreshPosition();
}---
getButtons()
Description: Returns the dialog button instances. Based on that, you can dynamically change the button states.
Parameters:
index(optional):number— Index of the button.
Return Type: Button[] | Button
Example:
// Get all buttons
const buttons = this.dialog.getButtons();
// Get button at index 0
const firstButton = this.dialog.getButtons(0);
firstButton.disabled = true;---
getDimension()
Description: Returns the current width and height of the Dialog.
Return Type: DialogDimension
Example:
const dimension = this.dialog.getDimension();
console.log(dimension.width, dimension.height);---
destroy()
Description: Destroys the dialog component and releases its resources.
Return Type: void
Example:
destroyDialog() {
this.dialog.destroy();
}---
Events
beforeClose: BeforeCloseEventArgs
Description: Triggered before the dialog is closed. Set cancel to true to prevent closure.
Arguments:
cancel: Boolean to cancel the close actionevent: Original event
Example:
<ejs-dialog (beforeClose)="onBeforeClose($event)">
</ejs-dialog>
onBeforeClose(args: BeforeCloseEventArgs) {
if (this.formDirty) {
args.cancel = true;
console.log('Close cancelled - unsaved changes');
}
}Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/beforecloseeventargs
---
beforeOpen: BeforeOpenEventArgs
Description: Triggered when the dialog is being opened. Set cancel to true to prevent opening.
Arguments:
cancel: Boolean to cancel the open actionevent: Original event
Example:
<ejs-dialog (beforeOpen)="onBeforeOpen($event)">
</ejs-dialog>
onBeforeOpen(args: BeforeOpenEventArgs) {
if (!this.isAllowedToOpen()) {
args.cancel = true;
}
}Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/beforeopeneventargs
---
beforeSanitizeHtml: BeforeSanitizeHtmlArgs
Description: Triggered before HTML content is sanitized for XSS prevention.
Example:
<ejs-dialog (beforeSanitizeHtml)="onBeforeSanitize($event)">
</ejs-dialog>
onBeforeSanitize(args: BeforeSanitizeHtmlArgs) {
console.log('Sanitizing HTML:', args);
}Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/beforesanitizehtmlargs
---
close: Object
Description: Triggered after the dialog has been closed.
Example:
<ejs-dialog (close)="onClose()">
</ejs-dialog>
onClose() {
console.log('Dialog closed');
}---
created: Object
Description: Triggered when the dialog is created.
Example:
<ejs-dialog (created)="onCreated()">
</ejs-dialog>
onCreated() {
console.log('Dialog created');
}---
destroyed: Event
Description: Triggered when the dialog is destroyed.
Example:
<ejs-dialog (destroyed)="onDestroyed()">
</ejs-dialog>
onDestroyed() {
console.log('Dialog destroyed');
}---
drag: Object
Description: Triggered when the user is dragging the dialog.
Example:
<ejs-dialog (drag)="onDrag()">
</ejs-dialog>
onDrag() {
console.log('Dialog is being dragged');
}Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/drageventargs
---
dragStart: Object
Description: Triggered when the user begins dragging the dialog.
Example:
<ejs-dialog (dragStart)="onDragStart()">
</ejs-dialog>
onDragStart() {
console.log('Drag started');
}Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/dragstarteventargs
---
dragStop: Object
Description: Triggered when the user stops dragging the dialog.
Example:
<ejs-dialog (dragStop)="onDragStop()">
</ejs-dialog>
onDragStop() {
console.log('Drag stopped');
}Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/dragstopeventargs
---
open: Object
Description: Triggered when the dialog is opened.
Example:
<ejs-dialog (open)="onOpen()">
</ejs-dialog>
onOpen() {
console.log('Dialog opened');
}Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/openeventargs
---
overlayClick: Object
Description: Triggered when the overlay/backdrop of the dialog is clicked.
Example:
<ejs-dialog (overlayClick)="onOverlayClick()">
</ejs-dialog>
onOverlayClick() {
console.log('Overlay clicked');
}---
resizeStart: Object
Description: Triggered when the user begins resizing the dialog.
Example:
<ejs-dialog (resizeStart)="onResizeStart()">
</ejs-dialog>
onResizeStart() {
console.log('Resize started');
}---
resizeStop: Object
Description: Triggered when the user stops resizing the dialog.
Example:
<ejs-dialog (resizeStop)="onResizeStop()">
</ejs-dialog>
onResizeStop() {
console.log('Resize stopped');
}---
resizing: Object
Description: Triggered when the user is actively resizing the dialog.
Example:
<ejs-dialog (resizing)="onResizing()">
</ejs-dialog>
onResizing() {
console.log('Dialog is being resized');
}---
Interfaces & Models
AnimationSettingsModel
Properties:
effect: DialogEffect (Animation effect type)duration: number (Duration in milliseconds)delay: number (Delay in milliseconds)
Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/animationsettingsmodel
---
ButtonPropsModel
Properties:
text: string (Button display text)cssClass: string (CSS class for styling)click: Function (Click event handler)disabled: boolean (Disabled state)
Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/buttonpropsmodel
---
ButtonProps
Alias for ButtonPropsModel
Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/buttonprops
---
PositionDataModel
Properties:
X: string | number (Horizontal position)Y: string | number (Vertical position)
---
DialogDimension
Description: Returned by the getDimension() method. Represents the current dimensions of the dialog.
Properties:
width: number | string (Current width of the dialog)height: number | string (Current height of the dialog)
---
Enumerations
DialogEffect
Values:
FadeZoomFadeZoomSlideLeftSlideRightSlideUpSlideDownFlipBounce
Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/dialogeffect
---
ResizeDirections
Values:
AllNorthEastNorthWestSouthEastSouthWestNorthSouthEastWest
Related Documentation: https://ej2.syncfusion.com/angular/documentation/api/dialog/resizedirections
---
Code Examples
Basic Modal Dialog
import { Component, ViewChild } from '@angular/core';
import { DialogComponent, DialogModule } from '@syncfusion/ej2-angular-popups';
@Component({
selector: 'app-basic-dialog',
standalone: true,
imports: [DialogModule],
template: `
<div id="dialog-container" style="height: 500px;">
<button class="e-control e-btn" (click)="openDialog()">
Open Dialog
</button>
<ejs-dialog
#basicDialog
[isModal]="true"
[showCloseIcon]="true"
width="400px"
content="This is a basic modal dialog"
>
<ng-template #header>
<span>Dialog Title</span>
</ng-template>
</ejs-dialog>
</div>
`
})
export class BasicDialogComponent {
@ViewChild('basicDialog') dialog!: DialogComponent;
openDialog() {
this.dialog.show();
}
}Dialog with Buttons
buttons = [
{
text: 'OK',
cssClass: 'e-primary',
click: () => this.onOk()
},
{
text: 'Cancel',
click: () => this.dialog.hide()
}
];
<ejs-dialog [buttons]="buttons">
</ejs-dialog>Draggable and Resizable
<ejs-dialog
[allowDragging]="true"
[enableResize]="true"
[resizeHandles]="['All']"
[minHeight]="200"
>
</ejs-dialog>With Animation
animationSettings = {
effect: 'FadeZoom',
duration: 400
};
<ejs-dialog [animationSettings]="animationSettings">
</ejs-dialog>---
Best Practices
1. Always specify a target container for proper positioning 2. Use modeless dialogs for floating panels to allow background interaction 3. Implement proper focus management for accessibility 4. Use event handlers for beforeClose and beforeOpen to control dialog behavior 5. Sanitize HTML content when loading dynamic content (enabled by default) 6. Test keyboard navigation (Tab, Escape) for accessibility 7. Set appropriate z-index if using multiple dialogs
---
Related Links
- Official Documentation: https://ej2.syncfusion.com/angular/documentation/dialog/
- Getting Started: https://ej2.syncfusion.com/angular/documentation/dialog/getting-started/
- API Overview: https://ej2.syncfusion.com/angular/documentation/api/dialog/overview
- GitHub Repository: https://github.com/syncfusion/ej2-angular-ui-components
---
Last Updated: March 24, 2026 API Version: Syncfusion EJ2 Angular Latest Status: Complete - Valid APIs from Official Documentation
Getting Started with Dialog
Table of Contents
- Installation & Setup
- Basic Implementation
- Minimal Example
- CSS Imports & Themes
- Running the Application
- Troubleshooting
Installation & Setup
Prerequisites
Ensure your development environment meets the System Requirements for Syncfusion Angular UI Components.
Install Angular CLI
If you haven't already, install Angular CLI globally:
npm install -g @angular/cliFor a specific version (e.g., Angular 21):
npm install -g @angular/cli@21.0.0Create a New Angular Application
Generate a new Angular application:
ng new syncfusion-dialog-app
cd syncfusion-dialog-appWhen prompted, select your preferred CSS framework and choose the appropriate configuration options.
Install Syncfusion Popups Package
The Dialog component is part of the Syncfusion Popups package. Install it using:
ng add @syncfusion/ej2-angular-popupsThis command automatically:
- Adds
@syncfusion/ej2-angular-popupsand dependencies topackage.json - Imports the Dialog component in your application
- Registers the default Material theme in
angular.json
Alternative Installation (Manual):
npm install @syncfusion/ej2-angular-popups
npm install @syncfusion/ej2-base @syncfusion/ej2-buttons @syncfusion/ej2-popupsBasic Implementation
Import DialogModule
In your component, import the Dialog module:
import { Component, ViewChild } from '@angular/core';
import { DialogModule, DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
selector: 'app-root',
imports: [DialogModule],
template: `...`
})
export class AppComponent {
// Component code
}Define the Dialog
Use the <ejs-dialog> selector to create a dialog:
<div id="dialog-container">
<button (click)="onOpenDialog()">Open Dialog</button>
<ejs-dialog
#ejDialog
target="#dialog-container"
content="Hello from Dialog!"
>
</ejs-dialog>
</div>Control the Dialog
Use @ViewChild to reference the dialog and call its methods:
export class AppComponent {
@ViewChild('ejDialog') ejDialog!: DialogComponent;
onOpenDialog(): void {
this.ejDialog.show();
}
onCloseDialog(): void {
this.ejDialog.hide();
}
}Minimal Example
Here's a complete minimal example:
Component (app.component.ts):
import { Component, ViewChild } from '@angular/core';
import { DialogModule, DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
selector: 'app-root',
standalone: true,
imports: [DialogModule],
template: `
<div id="dialog-container" style="height: 500px;">
<button class="e-control e-btn" (click)="onOpenDialog()">
Open Dialog
</button>
<ejs-dialog
#ejDialog
target="#dialog-container"
[showCloseIcon]="true"
width="350px"
content="This is a Dialog content"
>
<ng-template #header>
<span>Simple Dialog</span>
</ng-template>
</ejs-dialog>
</div>
`,
styles: [`
#dialog-container {
height: 500px;
padding: 20px;
}
`]
})
export class AppComponent {
@ViewChild('ejDialog') ejDialog!: DialogComponent;
onOpenDialog(): void {
this.ejDialog.show();
}
}Bootstrap (main.ts):
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import 'zone.js';
bootstrapApplication(AppComponent)
.catch(err => console.error(err));CSS (styles.css):
html, body {
height: 100%;
margin: 0;
padding: 0;
}CSS Imports & Themes
Adding Theme Styles
Syncfusion Dialog requires theme styles to render correctly. Add the theme CSS to your styles.css or angular.json:
Option 1: Import in styles.css (Recommended)
/* Material theme (default) */
@import '../node_modules/@syncfusion/ej2-base/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-icons/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-angular-popups/styles/material3.css';Option 2: Configure in angular.json
"styles": [
"node_modules/@syncfusion/ej2-base/styles/material3.css",
"node_modules/@syncfusion/ej2-icons/styles/material3.css",
"node_modules/@syncfusion/ej2-buttons/styles/material3.css",
"node_modules/@syncfusion/ej2-angular-popups/styles/material3.css",
"src/styles.css"
]Available Themes
material3.css- Material Design 3 (recommended)bootstrap5.css- Bootstrap 5tailwind.css- Tailwind CSSfluent.css- Fluent Design
Using SCSS
If your project uses SCSS, import SCSS variables:
@import '../node_modules/@syncfusion/ej2-base/styles/material3.scss';
@import '../node_modules/@syncfusion/ej2-icons/styles/material3.scss';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material3.scss';
@import '../node_modules/@syncfusion/ej2-angular-popups/styles/material3.scss';Running the Application
Start Development Server
Run the application:
ng serveOr with a specific port:
ng serve --port 4200Open in Browser
Navigate to http://localhost:4200 in your browser.
Build for Production
Create a production build:
ng build --configuration productionThe build output will be in the dist/ folder.
Important Notes
Container Element
The Dialog must have a target element. If not specified, it uses document.body:
<div id="dialog-container">
<!-- Dialog needs this container -->
<ejs-dialog target="#dialog-container">
...
</ejs-dialog>
</div>Container Height
The dialog's max-height is calculated based on the target element's height. Set a min-height on the container:
#dialog-container {
height: 500px; /* Required for proper dialog sizing */
}If rendering against body, set CSS on html and body:
html, body {
height: 100%;
}Standalone Components
Angular 21+ uses standalone components by default. Always include DialogModule in your component's imports:
@Component({
imports: [DialogModule],
...
})Troubleshooting
Dialog Not Showing
Problem: Dialog doesn't appear when calling show()
Solutions: 1. Verify the target element exists and has a height 2. Check that CSS imports are included 3. Ensure @ViewChild reference is correctly typed
// Correct
@ViewChild('ejDialog') ejDialog!: DialogComponent;
// Incorrect
@ViewChild('ejDialog') ejDialog: any; // Missing typeStyles Not Applied
Problem: Dialog appears but styles are missing
Solutions: 1. Verify theme CSS is imported in the correct order 2. Check angular.json styles configuration 3. Ensure all dependencies are installed:
npm install @syncfusion/ej2-base
npm install @syncfusion/ej2-buttons
npm install @syncfusion/ej2-popupsModule Import Error
Problem: DialogModule is not defined
Solution: Import from the correct package:
// Correct
import { DialogModule } from '@syncfusion/ej2-angular-popups';
// Incorrect
import { DialogModule } from '@syncfusion/ej2-popups'; // Wrong packageContent Not Rendering
Problem: Dialog opens but content is empty
Solutions: 1. Use content property for strings:
<ejs-dialog content="Hello World"></ejs-dialog>2. Or use ng-template for HTML:
<ejs-dialog>
<ng-template #content>
<div>Hello World</div>
</ng-template>
</ejs-dialog>Dialog Position Issues
Problem: Dialog appears offscreen or overlaps
Solutions: 1. Verify target element exists and is visible 2. Check window height is sufficient 3. Use custom positioning if needed:
<ejs-dialog [position]="{ X: 100, Y: 100 }">
...
</ejs-dialog>Interaction and Events
Table of Contents
- Dialog Events
- Draggable Dialogs
- Resizable Dialogs
- Button Events
- Content Interaction
- Preventing Dialog Closure
- Focus Management
- Examples
Dialog Events
Open Event
Triggered when the dialog is opened:
@Component({
template: `
<ejs-dialog
#dialog
(open)="onDialogOpen()"
content="Dialog opened"
>
</ejs-dialog>
`
})
export class OpenEventComponent {
@ViewChild('dialog') dialog!: DialogComponent;
onDialogOpen(): void {
console.log('Dialog opened');
// Perform setup when dialog opens
}
}Close Event
Triggered when the dialog is closed:
@Component({
template: `
<ejs-dialog
#dialog
(close)="onDialogClose()"
content="Dialog closing"
>
</ejs-dialog>
`
})
export class CloseEventComponent {
@ViewChild('dialog') dialog!: DialogComponent;
onDialogClose(): void {
console.log('Dialog closed');
// Cleanup when dialog closes
}
}Dialog Opening Event (Cancelable)
Triggered before the dialog opens - can be canceled:
@Component({
template: `
<ejs-dialog
(beforeOpen)="onBeforeOpen($event)"
content="Try to open"
>
</ejs-dialog>
`
})
export class BeforeOpenComponent {
onBeforeOpen(args: any): void {
console.log('Dialog is about to open');
// Cancel opening if condition is met
if (!this.isAllowedToOpen()) {
args.cancel = true;
console.log('Dialog opening cancelled');
}
}
isAllowedToOpen(): boolean {
// Custom logic
return true;
}
}Dialog Closing Event (Cancelable)
Triggered before the dialog closes - can be canceled:
@Component({
template: `
<ejs-dialog
(beforeClose)="onBeforeClose($event)"
content="Try to close"
>
</ejs-dialog>
`
})
export class BeforeCloseComponent {
@ViewChild('dialog') dialog!: DialogComponent;
onBeforeClose(args: any): void {
// Prevent closing if form has unsaved changes
if (this.hasUnsavedChanges()) {
args.cancel = true;
console.log('Dialog closing prevented - unsaved changes');
}
}
hasUnsavedChanges(): boolean {
return true; // Custom logic
}
}Draggable Dialogs
Enable Dragging
@Component({
template: `
<div id="dialog-container" style="height: 600px;">
<button (click)="openDialog()">Open Draggable Dialog</button>
<ejs-dialog
#dialog
[allowDragging]="true"
[showCloseIcon]="true"
width="400px"
position="TopLeft"
content="Drag me around!"
>
</ejs-dialog>
</div>
`
})
export class DraggableDialogComponent {
@ViewChild('dialog') dialog!: DialogComponent;
openDialog(): void {
this.dialog.show();
}
}Handle Drag Events
@Component({
template: `
<ejs-dialog
#dialog
[allowDragging]="true"
(dragStart)="onDragStart()"
(drag)="onDrag()"
(dragStop)="onDragStop()"
content="Monitor drag events"
>
</ejs-dialog>
`
})
export class DragEventComponent {
@ViewChild('dialog') dialog!: DialogComponent;
onDragStart(): void {
console.log('Dragging started');
}
onDrag(): void {
console.log('Currently dragging');
}
onDragStop(): void {
console.log('Dragging stopped');
}
}Custom Drag Handle
@Component({
template: `
<ejs-dialog
#dialog
[allowDragging]="true"
content="Drag by the header"
>
<ng-template #header>
<div class="custom-drag-handle">
<span class="drag-icon">≡</span>
<span>Draggable Header</span>
</div>
</ng-template>
</ejs-dialog>
`,
styles: [`
.custom-drag-handle {
display: flex;
align-items: center;
gap: 8px;
cursor: move;
}
.drag-icon {
font-size: 18px;
color: #666;
}
`]
})
export class CustomDragHandleComponent {}Resizable Dialogs
Enable Resizing
@Component({
template: `
<div id="dialog-container" style="height: 600px;">
<ejs-dialog
#dialog
[resizeHandles]="['All']"
width="400px"
height="300px"
content="Try to resize me"
>
</ejs-dialog>
</div>
`
})
export class ResizableDialogComponent {}Specific Resize Handles
@Component({
template: `
<ejs-dialog
[resizeHandles]="['SouthEast', 'South', 'East']"
width="400px"
height="300px"
content="Resize from right and bottom"
>
</ejs-dialog>
`
})
export class SpecificHandlesComponent {}Resize with Constraints
@Component({
template: `
<ejs-dialog
[resizeHandles]="['All']"
width="500px"
height="400px"
[minHeight]="200"
content="Resize within min/max bounds"
>
</ejs-dialog>
`
})
export class ConstrainedResizeComponent {}Handle Resize Events
@Component({
template: `
<ejs-dialog
#dialog
[resizeHandles]="['All']"
(resizeStart)="onResizeStart()"
(resize)="onResize()"
(resizeStop)="onResizeStop()"
content="Monitor resize events"
>
</ejs-dialog>
`
})
export class ResizeEventComponent {
onResizeStart(): void {
console.log('Resize started');
}
onResize(): void {
console.log('Currently resizing');
}
onResizeStop(): void {
console.log('Resize stopped');
}
}Button Events
Button Click from Array
@Component({
template: `
<ejs-dialog
#dialog
[buttons]="dialogButtons"
content="Click a button"
>
</ejs-dialog>
`
})
export class ButtonArrayComponent {
@ViewChild('dialog') dialog!: DialogComponent;
dialogButtons = [
{
text: 'Save',
cssClass: 'e-primary',
click: this.onSave.bind(this)
},
{
text: 'Delete',
cssClass: 'e-danger',
click: this.onDelete.bind(this)
},
{
text: 'Cancel',
cssClass: 'e-outline',
click: this.onCancel.bind(this)
}
];
onSave(): void {
console.log('Saved');
this.dialog.hide();
}
onDelete(): void {
console.log('Deleted');
this.dialog.hide();
}
onCancel(): void {
console.log('Cancelled');
this.dialog.hide();
}
}Button Click from Template
@Component({
template: `
<ejs-dialog #dialog>
<ng-template #footer>
<button
class="e-control e-btn e-primary"
(click)="onYes()"
>
Yes
</button>
<button
class="e-control e-btn"
(click)="onNo()"
>
No
</button>
</ng-template>
</ejs-dialog>
`
})
export class TemplateButtonComponent {
@ViewChild('dialog') dialog!: DialogComponent;
onYes(): void {
console.log('Yes clicked');
this.dialog.hide();
}
onNo(): void {
console.log('No clicked');
this.dialog.hide();
}
}Content Interaction
Interact with Form Content
@Component({
template: `
<ejs-dialog #dialog>
<ng-template #content>
<form [formGroup]="form">
<input formControlName="username" placeholder="Enter username" />
<input formControlName="password" type="password" placeholder="Enter password" />
</form>
</ng-template>
<ng-template #footer>
<button (click)="login()">Login</button>
</ng-template>
</ejs-dialog>
`
})
export class FormInteractionComponent {
@ViewChild('dialog') dialog!: DialogComponent;
form = new FormGroup({
username: new FormControl(''),
password: new FormControl('')
});
login(): void {
const values = this.form.value;
console.log('Logging in with:', values);
this.dialog.hide();
}
}Handle Content Events
@Component({
template: `
<ejs-dialog>
<ng-template #content>
<div (click)="onContentClick($event)">
<button (click)="onButtonClick($event)">Click Me</button>
<input (change)="onInputChange($event)" />
</div>
</ng-template>
</ejs-dialog>
`
})
export class ContentEventComponent {
onContentClick(event: Event): void {
console.log('Content clicked:', event);
}
onButtonClick(event: Event): void {
console.log('Inner button clicked');
event.stopPropagation();
}
onInputChange(event: Event): void {
console.log('Input value changed');
}
}Preventing Dialog Closure
Cancel Close Event
@Component({
template: `
<ejs-dialog
(beforeClose)="onBeforeClose($event)"
content="Try to close with unsaved changes"
>
</ejs-dialog>
`
})
export class PreventCloseComponent {
formDirty = true;
onBeforeClose(args: any): void {
if (this.formDirty) {
args.cancel = true;
const confirmed = confirm('You have unsaved changes. Are you sure?');
if (confirmed) {
args.cancel = false;
}
}
}
}Conditional Closure
@Component({
template: `
<ejs-dialog #dialog>
<ng-template #content>
<form [formGroup]="form">
<input formControlName="email" type="email" />
</form>
</ng-template>
<ng-template #footer>
<button (click)="tryClose()">Close</button>
</ng-template>
</ejs-dialog>
`
})
export class ConditionalCloseComponent {
@ViewChild('dialog') dialog!: DialogComponent;
form = new FormGroup({
email: new FormControl('', Validators.email)
});
tryClose(): void {
if (this.form.valid) {
this.dialog.hide();
} else {
alert('Please enter a valid email before closing');
}
}
}Focus Management
Focus on Open
@Component({
template: `
<ejs-dialog
#dialog
(open)="onDialogOpen()"
>
<ng-template #content>
<input #firstInput type="text" placeholder="This gets focus" />
<input type="text" placeholder="Other input" />
</ng-template>
</ejs-dialog>
`
})
export class FocusOnOpenComponent {
@ViewChild('dialog') dialog!: DialogComponent;
@ViewChild('firstInput') firstInput!: ElementRef;
onDialogOpen(): void {
setTimeout(() => {
this.firstInput.nativeElement.focus();
}, 100);
}
}Return Focus on Close
@Component({
template: `
<button #openBtn (click)="openDialog()">Open Dialog</button>
<ejs-dialog
#dialog
(close)="returnFocus()"
>
</ejs-dialog>
`
})
export class ReturnFocusComponent {
@ViewChild('dialog') dialog!: DialogComponent;
@ViewChild('openBtn') openBtn!: ElementRef;
openDialog(): void {
this.dialog.show();
}
returnFocus(): void {
this.openBtn.nativeElement.focus();
}
}Examples
Example 1: Multi-step Form Dialog
@Component({
template: `
<ejs-dialog #dialog [showCloseIcon]="true">
<ng-template #header>
<h2>Registration - Step {{ currentStep }} of 3</h2>
</ng-template>
<ng-template #content>
<form [ngSwitch]="currentStep">
<!-- Step 1 -->
<div *ngSwitchCase="1">
<input placeholder="First Name" [(ngModel)]="formData.firstName" />
<input placeholder="Last Name" [(ngModel)]="formData.lastName" />
</div>
<!-- Step 2 -->
<div *ngSwitchCase="2">
<input type="email" placeholder="Email" [(ngModel)]="formData.email" />
<input type="tel" placeholder="Phone" [(ngModel)]="formData.phone" />
</div>
<!-- Step 3 -->
<div *ngSwitchCase="3">
<input type="password" placeholder="Password" [(ngModel)]="formData.password" />
<input type="password" placeholder="Confirm Password" [(ngModel)]="formData.confirmPassword" />
</div>
</form>
</ng-template>
<ng-template #footer>
<button
class="e-control e-btn"
[disabled]="currentStep === 1"
(click)="previousStep()"
>
Back
</button>
<button
class="e-control e-btn e-primary"
(click)="nextStep()"
>
{{ currentStep === 3 ? 'Finish' : 'Next' }}
</button>
</ng-template>
</ejs-dialog>
`
})
export class MultiStepFormComponent {
@ViewChild('dialog') dialog!: DialogComponent;
currentStep = 1;
formData = {
firstName: '',
lastName: '',
email: '',
phone: '',
password: '',
confirmPassword: ''
};
nextStep(): void {
if (this.currentStep < 3) {
this.currentStep++;
} else {
console.log('Form submitted:', this.formData);
this.dialog.hide();
}
}
previousStep(): void {
if (this.currentStep > 1) {
this.currentStep--;
}
}
}Example 2: Dynamic Content Dialog with Events
@Component({
template: `
<ejs-dialog
#dialog
[allowDragging]="true"
[resizeHandles]="['All']"
(open)="onOpen()"
(close)="onClose()"
>
<ng-template #header>
<h2>{{ title }}</h2>
</ng-template>
<ng-template #content>
<p>{{ message }}</p>
<p *ngIf="isLoading">Loading...</p>
<div *ngIf="data">
{{ data }}
</div>
</ng-template>
<ng-template #footer>
<button
class="e-control e-btn e-primary"
(click)="onAction()"
[disabled]="isLoading"
>
{{ actionLabel }}
</button>
<button
class="e-control e-btn"
(click)="dialog.hide()"
>
Close
</button>
</ng-template>
</ejs-dialog>
`
})
export class DynamicDialogComponent {
@ViewChild('dialog') dialog!: DialogComponent;
title = 'Loading Data';
message = 'Please wait...';
actionLabel = 'Save';
isLoading = false;
data = null;
onOpen(): void {
console.log('Dialog opened - loading data');
this.loadData();
}
onClose(): void {
console.log('Dialog closed');
this.isLoading = false;
}
loadData(): void {
this.isLoading = true;
setTimeout(() => {
this.data = 'Data loaded successfully';
this.isLoading = false;
}, 2000);
}
onAction(): void {
console.log('Action performed');
}
}Modal vs Modeless Dialogs
Table of Contents
- Modal Dialog Behavior
- Modeless Dialog Behavior
- Comparison & Use Cases
- Toggling Between Modes
- Overlay Customization
- Best Practices
Modal Dialog Behavior
What is a Modal Dialog?
A modal dialog prevents the user from interacting with the parent application until the dialog is closed. It's blocking and demands user attention.
Key Characteristics
- Blocks parent interaction - User cannot click outside or interact with background elements
- Overlay/backdrop - Dark overlay covers the parent content
- Focus trapped - Tab navigation stays within the dialog
- Requires action - User must interact with the dialog (close, submit, cancel)
- Common use - Confirmations, critical decisions, forms
Example: Basic Modal Dialog
import { Component, ViewChild } from '@angular/core';
import { DialogModule, DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
selector: 'app-modal-dialog',
standalone: true,
imports: [DialogModule],
template: `
<div id="dialog-container" style="height: 500px;">
<button class="e-control e-btn" (click)="openConfirmation()">
Delete Item
</button>
<ejs-dialog
#confirmDialog
[isModal]="true"
[showCloseIcon]="true"
width="400px"
content="Are you sure you want to delete this item? This action cannot be undone."
>
<ng-template #header>
<span>Confirm Delete</span>
</ng-template>
<ng-template #footer>
<button
class="e-control e-btn e-primary"
(click)="onConfirm()"
>
Delete
</button>
<button
class="e-control e-btn"
(click)="confirmDialog.hide()"
>
Cancel
</button>
</ng-template>
</ejs-dialog>
</div>
`
})
export class ModalDialogComponent {
@ViewChild('confirmDialog') confirmDialog!: DialogComponent;
openConfirmation(): void {
this.confirmDialog.show();
}
onConfirm(): void {
console.log('Item deleted');
this.confirmDialog.hide();
}
}CSS for Modal Dialog
/* The overlay is automatically styled */
.e-dlg-overlay {
background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent black */
opacity: 0.6;
}
/* Modal dialog container */
.e-dialog {
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}Modeless Dialog Behavior
What is a Modeless Dialog?
A modeless dialog (also called non-modal) allows users to interact with the parent application while the dialog is open. It's informational and doesn't block interaction.
Key Characteristics
- Allows parent interaction - User can click outside and interact with background
- No overlay - Transparent background or light overlay
- No focus trap - User can tab outside the dialog
- No required action - User can ignore the dialog
- Common use - Floating toolbars, help panels, settings panels, notifications
Example: Basic Modeless Dialog
import { Component, ViewChild } from '@angular/core';
import { DialogModule, DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
selector: 'app-modeless-dialog',
standalone: true,
imports: [DialogModule],
template: `
<div id="dialog-container" style="height: 500px;">
<h2>Main Application Content</h2>
<p>You can still interact with this content while the dialog is open.</p>
<button class="e-control e-btn" (click)="openSettings()">
Open Settings
</button>
<ejs-dialog
#settingsDialog
[isModal]="false"
[showCloseIcon]="true"
[allowDragging]="true"
width="350px"
position="TopRight"
content="Settings panel content goes here"
>
<ng-template #header>
<span>Settings</span>
</ng-template>
</ejs-dialog>
</div>
`,
styles: [`
#dialog-container {
height: 500px;
padding: 20px;
background-color: #f5f5f5;
}
`]
})
export class ModelessDialogComponent {
@ViewChild('settingsDialog') settingsDialog!: DialogComponent;
openSettings(): void {
this.settingsDialog.show();
}
}CSS for Modeless Dialog
/* Modeless dialogs have transparent or light overlay */
.e-dlg-overlay {
background-color: transparent; /* No overlay */
opacity: 0;
}
/* Or light overlay for visibility */
.e-dlg-overlay {
background-color: rgba(0, 0, 0, 0.1); /* Very light overlay */
opacity: 0.1;
}Comparison & Use Cases
| Feature | Modal | Modeless |
|---|---|---|
| Blocks parent interaction | ✅ Yes | ❌ No |
| Shows overlay/backdrop | ✅ Yes (dark) | ❌ No (or light) |
| Traps focus | ✅ Yes (Tab stays in dialog) | ❌ No (Tab can leave) |
| Requires user action | ✅ Yes | ❌ No |
| Urgency | High | Low |
| Draggable | Less common | Common |
| Multiple instances | Rare | Common |
Use Cases for Modal
1. Confirmation dialogs - "Are you sure?" before delete/permanent action 2. Critical errors - Display errors that block workflow 3. Form submission - Collect required data before proceeding 4. Login/authentication - Require user to complete action 5. System alerts - Important system messages that need acknowledgment
// Example: Modal for critical action
<ejs-dialog
[isModal]="true"
content="This action will delete all data. This cannot be undone."
[buttons]="[
{ text: 'Delete', cssClass: 'e-danger' },
{ text: 'Cancel', cssClass: 'e-outline' }
]"
>
</ejs-dialog>Use Cases for Modeless
1. Floating toolbars - Tools that don't block main workflow 2. Help panels - Assistance that users can reference 3. Settings/preferences - Non-blocking configuration 4. Real-time notifications - Information updates 5. Draggable windows - Multi-window interfaces 6. Progress monitoring - Background task tracking
// Example: Modeless for settings
<ejs-dialog
[isModal]="false"
[allowDragging]="true"
content="Configure your preferences"
>
</ejs-dialog>Toggling Between Modes
Dynamic Modal/Modeless Toggle
You can change the dialog mode at runtime:
import { Component, ViewChild } from '@angular/core';
import { DialogModule, DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
selector: 'app-toggle-mode',
standalone: true,
imports: [DialogModule],
template: `
<div id="dialog-container" style="height: 500px;">
<button class="e-control e-btn" (click)="toggleMode()">
Toggle Mode: {{ isModal ? 'Modal' : 'Modeless' }}
</button>
<ejs-dialog
#toggleDialog
[isModal]="isModal"
[showCloseIcon]="true"
width="400px"
content="This dialog can be modal or modeless"
>
<ng-template #header>
<span>Toggle Mode Dialog</span>
</ng-template>
</ejs-dialog>
</div>
`
})
export class ToggleModeComponent {
@ViewChild('toggleDialog') toggleDialog!: DialogComponent;
isModal: boolean = true;
toggleMode(): void {
this.isModal = !this.isModal;
// Close and reopen to apply the change
this.toggleDialog.hide();
// Reopen with new mode
setTimeout(() => {
this.toggleDialog.show();
}, 300);
}
}Programmatic Control
// Get current modal state
const currentMode = this.dialog.isModal;
// Set modal state
this.dialog.isModal = false; // Make modeless
// Apply changes
this.dialog.refresh();Overlay Customization
Customizing Modal Overlay
// Typescript
@Component({
template: `
<ejs-dialog
[isModal]="true"
[showCloseIcon]="true"
content="Custom overlay example"
>
</ejs-dialog>
`,
styles: [`
/* Dark overlay with custom color */
:host ::ng-deep .e-dlg-overlay {
background-color: rgba(25, 118, 210, 0.7); /* Blue overlay */
}
/* Overlay with blur effect */
:host ::ng-deep .e-dlg-overlay {
backdrop-filter: blur(5px);
background-color: rgba(0, 0, 0, 0.3);
}
/* Semi-transparent overlay */
:host ::ng-deep .e-dlg-overlay {
background-color: rgba(0, 0, 0, 0.4);
opacity: 0.8;
}
`]
})
export class CustomOverlayComponent {}Removing Overlay for Modeless
/* Remove overlay for modeless dialogs */
.e-dialog.e-modeless .e-dlg-overlay {
display: none;
}
/* Or make it fully transparent */
.e-dialog.e-modeless .e-dlg-overlay {
background-color: transparent;
pointer-events: none;
}Overlay Click Behavior
// Control what happens when overlay is clicked
@Component({
template: `
<ejs-dialog
[isModal]="true"
[closeOnEscape]="true"
(overlayClick)="onOverlayClick()"
content="Click overlay to close"
>
</ejs-dialog>
`
})
export class OverlayClickComponent {
onOverlayClick(): void {
console.log('Overlay clicked');
// Custom logic here
}
}Best Practices
Choose Modal When:
- ✅ Action requires confirmation or immediate response
- ✅ Interruption of main workflow is acceptable
- ✅ Decision is critical or time-sensitive
- ✅ Error condition needs to be addressed
// Good: Modal for confirmation
<ejs-dialog [isModal]="true">
Are you sure you want to submit this order?
</ejs-dialog>Choose Modeless When:
- ✅ Information is supplementary
- ✅ User should remain focused on main task
- ✅ Multiple dialogs might be open
- ✅ Non-blocking notifications or tools
// Good: Modeless for help
<ejs-dialog [isModal]="false" [allowDragging]="true">
Help and tips for current feature
</ejs-dialog>Avoid Anti-patterns:
- ❌ Modal dialogs for informational content
- ❌ Multiple modal dialogs at once
- ❌ Modeless for critical decisions
- ❌ Modal dialogs that can be dismissed without action
Positioning and Sizing
Table of Contents
- Built-in Positions
- Custom Positioning
- Width and Height Configuration
- Min/Max Constraints
- Height Calculation and Target Container Requirements
- Responsive Sizing
- Full-screen Mode
- Examples
Built-in Positions
9 Built-in Position Options
The Dialog provides 9 predefined positions:
TopLeft TopCenter TopRight
MiddleLeft Center MiddleRight
BottomLeft BottomCenter BottomRightUsing Position Property
@Component({
template: `
<div id="dialog-container" style="height: 600px;">
<ejs-dialog
position="Center"
content="Center positioned dialog"
>
</ejs-dialog>
</div>
`
})
export class PositionedDialogComponent {
// Valid position values: TopLeft, TopCenter, TopRight, MiddleLeft, Center,
// MiddleRight, BottomLeft, BottomCenter, BottomRight
// Or use custom position with { X: 100, Y: 50 }
}All Built-in Positions Example
import { Component, ViewChild } from '@angular/core';
import { DialogModule, DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
selector: 'app-positions',
standalone: true,
imports: [DialogModule, CommonModule],
template: `
<div id="dialog-container" style="height: 600px;">
<div class="button-grid">
<button
*ngFor="let pos of positions"
class="e-control e-btn"
(click)="showDialog(pos)"
>
{{ pos }}
</button>
</div>
<ejs-dialog
#dialog
[position]="currentPosition"
[showCloseIcon]="true"
width="300px"
[content]="'Dialog at ' + currentPosition"
>
</ejs-dialog>
</div>
`,
styles: [`
.button-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
padding: 20px;
}
`]
})
export class PositionsComponent {
@ViewChild('dialog') dialog!: DialogComponent;
positions = [
'TopLeft', 'TopCenter', 'TopRight',
'MiddleLeft', 'Center', 'MiddleRight',
'BottomLeft', 'BottomCenter', 'BottomRight'
];
currentPosition = 'Center';
showDialog(position: string): void {
this.currentPosition = position;
this.dialog.show();
}
}Position Reference
| Position | Location |
|---|---|
TopLeft | Top-left corner |
TopCenter | Center of top edge |
TopRight | Top-right corner |
MiddleLeft | Left edge center |
Center | Dead center of container |
MiddleRight | Right edge center |
BottomLeft | Bottom-left corner |
BottomCenter | Center of bottom edge |
BottomRight | Bottom-right corner |
Custom Positioning
Using X and Y Coordinates
For precise positioning, use the position property with X and Y coordinates:
@Component({
template: `
<div id="dialog-container" style="height: 600px;">
<ejs-dialog
[position]="{ X: 100, Y: 50 }"
content="Custom positioned at (100px, 50px)"
>
</ejs-dialog>
</div>
`
})
export class CustomPositionComponent {}Percentage-based Positioning
@Component({
template: `
<ejs-dialog
[position]="{ X: '50%', Y: '50%' }"
content="Centered using percentages"
>
</ejs-dialog>
`
})
export class PercentagePositionComponent {}Dynamic Positioning
@Component({
template: `
<div id="dialog-container" style="height: 600px;">
<div>
<label>X Position: <input [(ngModel)]="posX" type="number" /></label>
<label>Y Position: <input [(ngModel)]="posY" type="number" /></label>
<button (click)="updatePosition()">Update Position</button>
</div>
<ejs-dialog
[position]="currentPosition"
content="Dynamically positioned dialog"
>
</ejs-dialog>
</div>
`
})
export class DynamicPositionComponent {
posX = 100;
posY = 100;
currentPosition = { X: 100, Y: 100 };
updatePosition(): void {
this.currentPosition = { X: this.posX, Y: this.posY };
}
}Positioning with Offset
@Component({
template: `
<ejs-dialog
[position]="{ X: window.innerWidth / 2 - 150, Y: window.innerHeight / 2 - 100 }"
width="300px"
content="Manually centered"
>
</ejs-dialog>
`
})
export class OffsetPositionComponent {}Width and Height Configuration
Fixed Dimensions
@Component({
template: `
<ejs-dialog
width="400px"
height="300px"
content="Fixed size dialog"
>
</ejs-dialog>
`
})
export class FixedSizeComponent {}Percentage-based Dimensions
@Component({
template: `
<ejs-dialog
width="80%"
height="60%"
content="Responsive percentage sizing"
>
</ejs-dialog>
`
})
export class PercentageSizeComponent {}Auto Width/Height
For content-based sizing:
@Component({
template: `
<ejs-dialog
width="auto"
content="This dialog width adjusts to content"
>
</ejs-dialog>
`
})
export class AutoSizeComponent {}Dynamic Sizing
import { Component, ViewChild } from '@angular/core';
import { DialogModule, DialogComponent } from '@syncfusion/ej2-angular-popups';
@Component({
selector: 'app-dynamic-size',
standalone: true,
imports: [DialogModule],
template: `
<div id="dialog-container" style="height: 600px;">
<button (click)="makeSmall()">Small</button>
<button (click)="makeMedium()">Medium</button>
<button (click)="makeLarge()">Large</button>
<ejs-dialog
#dialog
width="400px"
height="300px"
content="Resizable dialog"
>
</ejs-dialog>
</div>
`
})
export class DynamicSizeComponent {
@ViewChild('dialog') dialog!: DialogComponent;
makeSmall(): void {
this.dialog.width = '300px';
this.dialog.height = '200px';
}
makeMedium(): void {
this.dialog.width = '400px';
this.dialog.height = '300px';
}
makeLarge(): void {
this.dialog.width = '600px';
this.dialog.height = '400px';
}
}Min/Max Constraints
Minimum Size
@Component({
template: `
<ejs-dialog
width="500px"
height="300px"
[minHeight]="250"
[resizeHandles]="['All']"
content="Try resizing - minimum 250px height enforced"
>
</ejs-dialog>
`
})
export class MinHeightComponent {}---
Height Calculation and Target Container Requirements
Important: The Dialog'smax-heightis automatically calculated based on the height of its target element. If the dialog'sheightexceeds the target element's height, the height will not be set correctly.
How the Calculation Works
| Scenario | Target | Requirement |
|---|---|---|
No target set | document.body (default) | Set html, body { height: 100%; } in CSS |
Custom target="#container" | The specified element | Container must have explicit height or min-height |
Percentage height="80%" | Target element | Target must have a concrete pixel height for % to resolve |
Rule: Always Give the Target an Explicit Height
// ✅ CORRECT — target has explicit height
@Component({
template: `
<div id="dialog-container" style="height: 600px; position: relative; min-height: 400px;">
<ejs-dialog
target="#dialog-container"
height="400px"
content="Height renders correctly because target has explicit height"
>
</ejs-dialog>
</div>
`
})
export class CorrectHeightComponent {}// ❌ INCORRECT — target has no height, dialog height won't be applied
@Component({
template: `
<div id="dialog-container">
<ejs-dialog
target="#dialog-container"
height="400px"
content="Height may NOT render correctly"
>
</ejs-dialog>
</div>
`
})
export class IncorrectHeightComponent {}Using document.body as Target (Default Behavior)
When no target is configured, the dialog uses document.body. To ensure proper height calculation:
/* styles.css — add globally */
html, body {
height: 100%;
margin: 0;
}// No target property = document.body is the target
// Body must have height: 100% for dialog height to compute correctly
@Component({
selector: 'app-root',
standalone: true,
imports: [DialogModule],
template: `
<ejs-dialog
height="500px"
content="Dialog using document.body as target"
>
</ejs-dialog>
`
// styles.css must include: html, body { height: 100%; }
})
export class BodyTargetDialogComponent {}Percentage Height with a Target
When using percentage-based height, the target must have a concrete size:
@Component({
template: `
<!-- ✅ 80% of 600px = 480px — resolves correctly -->
<div id="dialog-container" style="height: 600px; position: relative;">
<ejs-dialog
target="#dialog-container"
height="80%"
content="80% height works because parent has explicit height"
>
</ejs-dialog>
</div>
`
})
export class PercentageHeightComponent {}Summary of Requirements
| Requirement | Why |
|---|---|
Target must have position: relative (or absolute/fixed) | Dialog is positioned relative to target |
Target must have explicit height or min-height | Dialog max-height is computed from target height |
html, body { height: 100%; } when no custom target | Ensures body has measurable height for calculation |
Avoid height: auto on target when using % dialog height | Percentage heights cannot resolve against an auto-height container |
---
Responsive Sizing
Container Relative Sizing
@Component({
template: `
<div id="dialog-container"
style="width: 100%; height: 100vh; display: flex; align-items: center; justify-content: center;">
<ejs-dialog
width="90%"
height="80%"
content="Responsive to container"
>
</ejs-dialog>
</div>
`
})
export class ResponsiveContainerComponent {}Media Query Based Positioning
@Component({
template: `
<ejs-dialog
[width]="getDialogWidth()"
[height]="getDialogHeight()"
[position]="getDialogPosition()"
content="Responsive dialog"
>
</ejs-dialog>
`
})
export class ResponsiveMediaComponent {
@HostListener('window:resize', ['$event'])
onResize(): void {
// Dialog will recalculate on resize
}
getDialogWidth(): string {
const width = window.innerWidth;
return width < 768 ? '90%' : '50%';
}
getDialogHeight(): string {
const height = window.innerHeight;
return height < 600 ? '80%' : '60%';
}
getDialogPosition(): string {
return window.innerWidth < 768 ? 'Center' : 'TopCenter';
}
}Full-screen Mode
Mobile Full-screen Dialog
@Component({
template: `
<div id="dialog-container" style="height: 500px;">
<button class="e-control e-btn" (click)="openFullscreen()">
Open Full-screen Dialog
</button>
<ejs-dialog
#fullscreenDialog
[width]="isMobile() ? '100%' : '600px'"
[height]="isMobile() ? '100%' : 'auto'"
[position]="isMobile() ? { X: 0, Y: 0 } : 'Center'"
[showCloseIcon]="true"
content="Full-screen on mobile, normal on desktop"
>
</ejs-dialog>
</div>
`
})
export class FullscreenComponent {
@ViewChild('fullscreenDialog') dialog!: DialogComponent;
isMobile(): boolean {
return window.innerWidth < 768;
}
openFullscreen(): void {
this.dialog.show();
}
}Toggle Full-screen
@Component({
template: `
<ejs-dialog
#dialog
[width]="isFullscreen ? '100%' : '500px'"
[height]="isFullscreen ? '100%' : '400px'"
>
<ng-template #header>
<div class="header-with-toggle">
<span>Dialog Title</span>
<button
class="e-control e-btn e-icon-btn"
(click)="toggleFullscreen()"
>
{{ isFullscreen ? 'Exit Fullscreen' : 'Fullscreen' }}
</button>
</div>
</ng-template>
</ejs-dialog>
`,
styles: [`
.header-with-toggle {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
`]
})
export class ToggleFullscreenComponent {
@ViewChild('dialog') dialog!: DialogComponent;
isFullscreen = false;
toggleFullscreen(): void {
this.isFullscreen = !this.isFullscreen;
this.dialog.refresh();
}
}Examples
Example 1: Sticky Positioned Dialog
@Component({
template: `
<div id="dialog-container" style="height: 800px; overflow-y: auto;">
<button (click)="openSticky()">Open Sticky Dialog</button>
<ejs-dialog
#stickyDialog
position="TopRight"
width="300px"
[showCloseIcon]="true"
content="This dialog stays in view while scrolling"
>
</ejs-dialog>
<!-- Long scrollable content -->
<div style="height: 2000px; background: linear-gradient(to bottom, #f0f0f0, #fff);">
<p *ngFor="let i of [1,2,3,4,5,6,7,8,9,10]">
Lorem ipsum dolor sit amet... ({{ i * 100 }} words)
</p>
</div>
</div>
`
})
export class StickyDialogComponent {
@ViewChild('stickyDialog') dialog!: DialogComponent;
openSticky(): void {
this.dialog.show();
}
}Example 2: Cascading Dialogs
@Component({
template: `
<div id="dialog-container" style="height: 600px;">
<button (click)="openDialog1()">Open First Dialog</button>
<ejs-dialog
#dialog1
position="Center"
[position]="{ X: 50, Y: 50 }"
width="400px"
height="300px"
>
<ng-template #header><span>Dialog 1</span></ng-template>
<ng-template #content>
<p>This is the first dialog</p>
<button (click)="openDialog2()">Open Second Dialog</button>
</ng-template>
</ejs-dialog>
<ejs-dialog
#dialog2
[position]="{ X: 150, Y: 150 }"
width="400px"
height="300px"
>
<ng-template #header><span>Dialog 2</span></ng-template>
<ng-template #content>
<p>This is the second dialog, offset from the first</p>
</ng-template>
</ejs-dialog>
</div>
`
})
export class CascadingDialogsComponent {
@ViewChild('dialog1') dialog1!: DialogComponent;
@ViewChild('dialog2') dialog2!: DialogComponent;
openDialog1(): void { this.dialog1.show(); }
openDialog2(): void { this.dialog2.show(); }
}