RR.Blazor's modal system provides enterprise-grade modal dialogs that render directly to DOM portals for optimal performance and z-index management. The system eliminates the need for component-based modal hosts by leveraging JavaScript portal management.
The modal system uses a portal-based architecture:
- ModalProvider Component (
RModalProvider.razor) - Manages portal system and renders modals - JavaScript Portal System (
portal.js) - Creates DOM portals at document.body level - Modal Manager (
modal.js) - Handles modal lifecycle, animations, and events - ModalService (
ModalService.cs) - Blazor service interface - Modal Components (
RModal,RConfirmationModal) - Blazor modal components
- Simple ModalProvider setup - Single component manages all modals
- Better z-index management - Portal system handles stacking automatically
- Improved performance - Direct DOM manipulation without Blazor reconciliation
- Clean separation of concerns - JavaScript handles DOM, Blazor handles data
// Program.cs
builder.Services.AddRRBlazor();<!-- App.razor or MainLayout.razor -->
<ModalProvider />
@Body@inject IModalService ModalService
// Simple confirmation
var confirmed = await ModalService.ConfirmAsync("Are you sure?", "Confirm Action");
// Destructive confirmation
var confirmed = await ModalService.ConfirmAsync(
"This action cannot be undone!",
"Delete Item",
true // isDestructive
);
// Custom confirmation
var options = new ConfirmationOptions
{
Title = "Custom Confirmation",
Message = "This is a custom confirmation dialog.",
ConfirmText = "Yes, Proceed",
CancelText = "No, Cancel",
Variant = ModalVariant.Warning
};
var confirmed = await ModalService.ConfirmAsync(options);For enterprise scenarios requiring validation:
var result = await ModalService.ShowAsync<bool>(
typeof(RConfirmationModal),
new Dictionary<string, object>
{
["Title"] = "Delete Employee",
["Message"] = $"Permanently delete <strong>{employee.Name}</strong>?",
["Icon"] = "delete_forever",
["Variant"] = ConfirmationVariant.Destructive,
["ShowInputField"] = true,
["InputLabel"] = "Type employee's last name to confirm",
["InputPlaceholder"] = employee.LastName,
["InputRequired"] = true,
["OnInputValidate"] = new Func<string, Task<bool>>(input =>
Task.FromResult(string.Equals(input, employee.LastName, StringComparison.OrdinalIgnoreCase))),
["ShowDetails"] = true,
["DetailsDictionary"] = new Dictionary<string, string>
{
["Employee ID"] = employee.Id,
["Department"] = employee.Department,
["Status"] = employee.IsActive ? "Active" : "Inactive"
}
}
);// Show custom component in modal
var result = await ModalService.ShowAsync<MyData>(
typeof(MyCustomModal),
new Dictionary<string, object>
{
["InitialData"] = myData,
["Title"] = "Edit Data"
},
new ModalOptions
{
Size = SizeType.Large,
CloseOnBackdrop = false
}
);var options = new ModalOptions
{
Title = "Modal Title",
Subtitle = "Optional subtitle",
Icon = "info",
Size = SizeType.Medium,
Variant = ModalVariant.Default,
CloseOnBackdrop = true,
CloseOnEscape = true,
ShowCloseButton = true,
ShowHeader = true,
ShowFooter = true,
Class = "custom-modal-class"
};Info- Default informational styleSuccess- Success/positive action styleWarning- Warning/caution styleDanger- Dangerous action styleDestructive- Destructive/irreversible action style
- Title and Message - Customizable header and content
- Icon Support - Material Icons with variant-based defaults
- Button Customization - Custom text and styling
- Variant Styling - Pre-defined color schemes
- Input Validation - Require user input for confirmation
- Checkbox Confirmation - Additional confirmation checkbox
- Details Display - Show structured information
- Warning Messages - Highlight destructive actions
- Custom Templates - Override any section with custom content
var parameters = new Dictionary<string, object>
{
["ShowInputField"] = true,
["InputLabel"] = "Type 'DELETE' to confirm",
["InputRequired"] = true,
["OnInputValidate"] = new Func<string, Task<bool>>(input =>
Task.FromResult(input == "DELETE"))
};var parameters = new Dictionary<string, object>
{
["ShowDetails"] = true,
["DetailsTitle"] = "Employee Information",
["DetailsDictionary"] = new Dictionary<string, string>
{
["Name"] = employee.FullName,
["Department"] = employee.Department,
["Hire Date"] = employee.HireDate.ToString("yyyy-MM-dd")
}
};The modal system automatically creates DOM portals:
// Automatic portal creation
const portal = window.RRBlazor.Portal.create({
id: 'modal-12345',
className: 'modal-portal'
});
// Modal creation
window.RRBlazor.Modal.create(modalElement, {
useBackdrop: true,
closeOnEscape: true,
trapFocus: true
});The modal system uses a comprehensive event system:
PORTAL_CREATED- Portal created successfullyPORTAL_DESTROYED- Portal destroyedUI_COMPONENT_OPENED- Modal openedUI_COMPONENT_CLOSED- Modal closed
- Modern Browsers - Chrome 88+, Firefox 85+, Safari 14+, Edge 88+
- Mobile Support - iOS Safari 14+, Chrome Mobile 88+
- Accessibility - WCAG 2.1 AA compliant
If migrating from older versions that used RModalHost:
<!-- MainLayout.razor -->
<RModalHost />
@Body<!-- MainLayout.razor -->
<ModalProvider />
@BodyThe ModalProvider component manages the portal system and creates the necessary DOM structure automatically when the first modal is shown.
- Portal Creation - On-demand portal creation reduces initial DOM size
- Memory Management - Automatic cleanup when modals are destroyed
- Z-Index Management - Efficient stacking without CSS conflicts
- Animation Performance - Hardware-accelerated CSS animations
- Use confirmation modals for destructive actions
- Provide clear, actionable button text
- Use input validation for critical confirmations
- Show relevant details for context
- Handle modal results appropriately
- Don't nest modals deeply
Modal doesn't appear:
- Check browser console for JavaScript errors
- Ensure RR.Blazor JavaScript files are loaded
- Verify ModalService is properly injected
Modal doesn't close:
- Check if custom validation is preventing closure
- Ensure button click handlers are properly bound
- Verify JavaScript event system is functioning
Z-index issues:
- The portal system automatically manages z-index
- Avoid manual z-index CSS overrides
- Check for CSS conflicts with other libraries
Enable debug logging:
window.RRBlazor.Debug = true;This will log detailed information about portal creation, modal lifecycle, and event handling.