
Syncfusion Angular Splitter
- 170 installs
- Updated August 4, 2026
- syncfusion/angular-ui-components-skills
Use syncfusion-angular-splitter for development tasks
About
syncfusion-angular-splitter: A skill for development. This provides functionality for development workflows.
- syncfusion-angular-splitter
Syncfusion Angular Splitter by the numbers
- 170 all-time installs (skills.sh)
- +11 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #2,287 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-splitterAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 170 |
|---|---|
| Last updated | August 4, 2026 |
| Repository | syncfusion/angular-ui-components-skills ↗ |
What it does
Use syncfusion-angular-splitter for development tasks
Files
Implementing Syncfusion Angular Splitter
The Splitter component divides a container into resizable panes separated by draggable separator bars. This enables flexible, user-controllable multi-pane layouts for dashboards, editors, and complex UI structures.
When to Use This Skill
- Dashboard layouts: Create multi-column dashboards with resizable panels
- Editor interfaces: Build text editors, code editors, or IDEs with side panels
- Navigation + content: Implement sidebar navigation with main content area
- Data exploration: Design interfaces with filters, previews, and detailed views
- Nested layouts: Create complex hierarchical pane structures
- Dynamic interfaces: Add/remove panes programmatically based on user actions
- Responsive splitting: Support both horizontal and vertical orientations
- Constrained resizing: Enforce min/max pane sizes for layout stability
Documentation and Navigation Guide
Getting Started
📄 Read: references/getting-started.md
- Package installation and setup
- Standalone component vs NgModule imports
- Basic Splitter component setup
- CSS theme imports
- First working example
API Reference (Complete)
📄 Read: references/api-reference.md
- All component properties (orientation, height, width, etc.)
- All pane properties (size, min, max, collapsible, etc.)
- All public methods (addPane, removePane, expand, collapse)
- All 8 events with argument details
- Complete working examples
Pane Orientation & Layout
📄 Read: references/split-panes.md
- Horizontal layout (default, side-by-side panes)
- Vertical layout (stacked panes with horizontal separator)
- Multiple panes (3+ panes in single splitter)
- Nested splitters (splitter within pane content)
- Template-based pane content
Pane Sizing & Configuration
📄 Read: references/pane-sizing.md
- Fixed pixel sizing (200px, 300px)
- Responsive percentage sizing (30%, 50%)
- Auto-sizing (flex layout, automatic distribution)
- Mixed sizing strategies in single splitter
- Dynamic pane size adjustments
Expand & Collapse Functionality
📄 Read: references/expand-collapse.md
- Collapsible panes (user-clickable expand/collapse icons)
- Collapsed state on initialization
- Programmatic
expand()method - Programmatic
collapse()method - Dynamic pane visibility control
Resizing & Interaction
📄 Read: references/resizing.md
- Resize behavior and dragging separator
- Fixed panes (non-resizable, static size)
- Resizable pane configuration
- Min/max size constraints (pane validation)
- Preventing invalid resize operations
Layout Patterns & Recipes
📄 Read: references/layout-patterns.md
- Two-pane sidebar layouts
- Three-pane editor layouts (left sidebar, main content, right panel)
- Nested splitters and complex hierarchies
- Common UI patterns with complete code examples
- Layout composition strategies
Styling & Customization
📄 Read: references/styling-customization.md
- Theme application (Material3, Bootstrap, etc.)
- CSS class customization
- Separator styling and sizing
- Pane content styling
Globalization & Localization
📄 Read: references/globalization.md
- Right-to-left (RTL) language support (Arabic, Hebrew)
- Locale and culture configuration
- Text direction attributes
- Multi-language content
- Locale-aware formatting
Content Loading
📄 Read: references/content-loading.md
- HTML element content
- String content via
contentproperty - ng-template content (template-based)
- DOM selector content (external HTML)
- Dynamic content updates
Dynamic Pane Manipulation
📄 Read: references/dynamic-manipulation.md
- Adding panes with
addPane()method - Removing panes with
removePane()method - Pane configuration and properties
- Dynamic pane state management
- Methods and events reference
- Constraints during manipulation
Security Best Practices
📄 Read: references/security-best-practices.md
- HTML sanitization and XSS prevention
enableHtmlSanitizerproperty usage- Content validation patterns
- Safe content sources and ranking
- Common vulnerabilities to avoid
- Secure code examples
---
Quick Start
Basic Two-Pane Layout
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
standalone: true,
imports: [SplitterModule],
template: `
<ejs-splitter height="400px" width="100%">
<e-panes>
<e-pane size="300px">
<ng-template #content>
<div>Left Pane</div>
</ng-template>
</e-pane>
<e-pane size="300px">
<ng-template #content>
<div>Right Pane</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {}Vertical Layout with Collapsible Panes
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-vertical-splitter',
standalone: true,
imports: [SplitterModule],
template: `
<ejs-splitter orientation="Vertical" height="400px" width="100%">
<e-panes>
<e-pane size="150px" [collapsible]="true">
<ng-template #content>
<div>Header Panel</div>
</ng-template>
</e-pane>
<e-pane [collapsible]="true">
<ng-template #content>
<div>Content Area</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`
})
export class VerticalSplitterComponent {}Common Patterns
Sidebar + Content Layout
The classic two-pane layout with a fixed sidebar and flexible content area:
<ejs-splitter height="500px" width="100%">
<e-panes>
<!-- Fixed sidebar -->
<e-pane size="250px">
<ng-template #content>
<div class="sidebar">
<ul>
<li>Navigation Item 1</li>
<li>Navigation Item 2</li>
</ul>
</div>
</ng-template>
</e-pane>
<!-- Flexible content -->
<e-pane>
<ng-template #content>
<div class="content">Main Content Area</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>Responsive Percentage-Based Layout
Panes that resize based on container size:
<ejs-splitter height="400px" width="100%">
<e-panes>
<e-pane size="25%">
<ng-template #content>25% Panel</ng-template>
</e-pane>
<e-pane size="50%">
<ng-template #content>50% Panel</ng-template>
</e-pane>
<e-pane size="25%">
<ng-template #content>25% Panel</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>Collapsible Dashboard Panels
Panes with expand/collapse icons for compact UI:
<ejs-splitter height="500px" width="100%">
<e-panes>
<e-pane size="200px" [collapsible]="true">
<ng-template #content>
<div>Filters Panel (Collapsible)</div>
</ng-template>
</e-pane>
<e-pane [collapsible]="true">
<ng-template #content>
<div>Main Dashboard</div>
</ng-template>
</e-pane>
<e-pane size="300px" [collapsible]="true">
<ng-template #content>
<div>Details Panel (Collapsible)</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>Key Features
| Feature | Purpose | When to Use |
|---|---|---|
| Orientation | Horizontal or vertical pane layout | Choose based on UI design needs |
| Pane Sizing | Fixed pixels, percentages, or auto | Mix sizing strategies for responsive layouts |
| Collapsible | User-controlled expand/collapse | Save space in dashboards and editors |
| Fixed Panes | Non-resizable panes with static size | Create stable reference areas (sidebars) |
| Min/Max Constraints | Enforce pane size limits | Prevent layout breaking during resize |
| Nested Splitters | Splitter within splitter panes | Create complex hierarchical layouts |
| Dynamic Manipulation | Add/remove panes programmatically | Adapt UI to user actions or data changes |
| Content Flexibility | HTML, strings, templates, selectors | Load any type of content into panes |
| Themes & Styling | Multiple built-in themes | Apply consistent design across app |
Related Skills
- Data Grids - Display tabular data within splitter panes
- Charts & Visualization - Embed dashboards and analytics in split layouts
- Navigation Components - Build sidebars and navigation structures with splitter
---
Next Steps: Choose a reference file based on your specific use case, then refer to the code snippets and examples provided.
API Reference - Splitter Component
Complete reference for Syncfusion Angular Splitter component properties, methods, and events with working code examples.
Table of Contents
---
Component Properties
Properties available on the main <ejs-splitter> element for configuring the Splitter component.
orientation
Type: 'Horizontal' | 'Vertical' Default: 'Horizontal' Description: Specifies whether panes are arranged horizontally (left-to-right) or vertically (top-to-bottom).
// Horizontal layout (default)
<ejs-splitter orientation="Horizontal" height="400px">
<e-panes>
<e-pane size="200px"><ng-template #content>Left</ng-template></e-pane>
<e-pane><ng-template #content>Right</ng-template></e-pane>
</e-panes>
</ejs-splitter>
// Vertical layout
<ejs-splitter orientation="Vertical" height="400px">
<e-panes>
<e-pane size="150px"><ng-template #content>Top</ng-template></e-pane>
<e-pane><ng-template #content>Bottom</ng-template></e-pane>
</e-panes>
</ejs-splitter>height
Type: string | number Description: Sets the height of the Splitter component. Accept pixel values (e.g., '400px') or percentages (e.g., '100%').
// Fixed pixel height
<ejs-splitter height="500px" width="100%">
<e-panes>
<e-pane><ng-template #content>Content</ng-template></e-pane>
</e-panes>
</ejs-splitter>
// Percentage height with numeric value
<ejs-splitter [height]="600" width="100%">
<e-panes>
<e-pane><ng-template #content>Content</ng-template></e-pane>
</e-panes>
</ejs-splitter>width
Type: string | number Description: Sets the width of the Splitter component. Accept pixel values or percentages.
// Full width responsive
<ejs-splitter width="100%" height="400px">
<e-panes>
<e-pane><ng-template #content>Content</ng-template></e-pane>
</e-panes>
</ejs-splitter>
// Fixed pixel width
<ejs-splitter width="800px" height="400px">
<e-panes>
<e-pane><ng-template #content>Content</ng-template></e-pane>
</e-panes>
</ejs-splitter>paneSettings
Type: PanePropertiesModel[] Description: Array of pane configuration objects defining properties for each pane (alternative to inline pane elements).
import { Component } from '@angular/core';
import { PanePropertiesModel } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
template: `<ejs-splitter [paneSettings]="paneSettings" height="400px" width="100%"></ejs-splitter>`
})
export class SplitterComponent {
public paneSettings: PanePropertiesModel[] = [
{ size: '250px', content: 'Left Pane', collapsible: true },
{ size: '250px', content: 'Right Pane', collapsible: false }
];
}separatorSize
Type: number Default: null Description: Specifies the width (horizontal) or height (vertical) of the separator line in pixels.
// Custom separator size
<ejs-splitter height="400px" width="100%" [separatorSize]="8">
<e-panes>
<e-pane size="250px"><ng-template #content>Left</ng-template></e-pane>
<e-pane><ng-template #content>Right</ng-template></e-pane>
</e-panes>
</ejs-splitter>
// Thick separator for easier interaction
<ejs-splitter height="400px" width="100%" [separatorSize]="12">
<e-panes>
<e-pane size="200px"><ng-template #content>Pane 1</ng-template></e-pane>
<e-pane><ng-template #content>Pane 2</ng-template></e-pane>
</e-panes>
</ejs-splitter>enabled
Type: boolean Default: true Description: Enables or disables the entire Splitter component. When disabled, users cannot interact with panes or separators.
import { Component } from '@angular/core';
@Component({
selector: 'app-splitter',
template: `
<button (click)="toggleEnabled()">Toggle Splitter</button>
<ejs-splitter [enabled]="isEnabled" height="400px" width="100%">
<e-panes>
<e-pane><ng-template #content>Content</ng-template></e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
isEnabled = true;
toggleEnabled() {
this.isEnabled = !this.isEnabled;
}
}enableRtl
Type: boolean Default: false Description: Enables right-to-left (RTL) layout for languages like Arabic, Hebrew, and Persian.
// RTL support for Arabic
<ejs-splitter [enableRtl]="true" height="400px" width="100%">
<e-panes>
<e-pane size="250px"><ng-template #content>القائمة</ng-template></e-pane>
<e-pane><ng-template #content>المحتوى</ng-template></e-pane>
</e-panes>
</ejs-splitter>
// Dynamic RTL toggle
import { Component } from '@angular/core';
@Component({
selector: 'app-rtl-splitter',
template: `
<button (click)="toggleRTL()">Toggle RTL</button>
<ejs-splitter [enableRtl]="isRTL" height="400px" width="100%">
<e-panes>
<e-pane size="200px"><ng-template #content>Navigation</ng-template></e-pane>
<e-pane><ng-template #content>Content</ng-template></e-pane>
</e-panes>
</ejs-splitter>
`
})
export class RtlSplitterComponent {
isRTL = false;
toggleRTL() {
this.isRTL = !this.isRTL;
}
}enableReversePanes
Type: boolean Default: true Description: When enabled, reorders panes in the splitter (useful for responsive layouts).
<ejs-splitter [enableReversePanes]="false" height="400px" width="100%">
<e-panes>
<e-pane size="250px"><ng-template #content>Pane 1</ng-template></e-pane>
<e-pane size="250px"><ng-template #content>Pane 2</ng-template></e-pane>
<e-pane><ng-template #content>Pane 3</ng-template></e-pane>
</e-panes>
</ejs-splitter>enablePersistence
Type: boolean Default: false Description: Persists component state (pane sizes, collapsed state) in browser localStorage across page reloads.
// Persist splitter state
<ejs-splitter [enablePersistence]="true" height="400px" width="100%" id="splitter">
<e-panes>
<e-pane size="250px"><ng-template #content>Left</ng-template></e-pane>
<e-pane><ng-template #content>Right</ng-template></e-pane>
</e-panes>
</ejs-splitter>
// Component will restore pane sizes on page reloadenableHtmlSanitizer
Type: boolean Default: true Description: Enables HTML sanitization to prevent cross-site scripting (XSS) attacks in pane content. See Security Best Practices for details.
// Enable sanitization (default, recommended)
<ejs-splitter [enableHtmlSanitizer]="true" height="400px" width="100%">
<e-panes>
<e-pane [content]="'<strong>Safe Content</strong>'"></e-pane>
</e-panes>
</ejs-splitter>
// Disable sanitization (ONLY for trusted content)
<ejs-splitter [enableHtmlSanitizer]="false" height="400px" width="100%">
<e-panes>
<e-pane [content]="trustedHtmlContent"></e-pane>
</e-panes>
</ejs-splitter>locale
Type: string Default: 'en-US' Description: Specifies the locale for the component, affecting text direction and formatting for internationalization.
// Spanish locale
<ejs-splitter locale="es" height="400px" width="100%">
<e-panes>
<e-pane><ng-template #content>Contenido</ng-template></e-pane>
</e-panes>
</ejs-splitter>
// Arabic locale with RTL
<ejs-splitter locale="ar" [enableRtl]="true" height="400px" width="100%">
<e-panes>
<e-pane><ng-template #content>المحتوى</ng-template></e-pane>
</e-panes>
</ejs-splitter>cssClass
Type: string Description: Applies custom CSS class(es) to the root element of the Splitter for custom styling.
// Single custom class
<ejs-splitter cssClass="custom-splitter" height="400px" width="100%">
<e-panes>
<e-pane><ng-template #content>Content</ng-template></e-pane>
</e-panes>
</ejs-splitter>
// Multiple classes
<ejs-splitter cssClass="custom-splitter dark-theme premium" height="400px" width="100%">
<e-panes>
<e-pane><ng-template #content>Content</ng-template></e-pane>
</e-panes>
</ejs-splitter>
// CSS
<style>
.custom-splitter {
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.custom-splitter.dark-theme {
background-color: #1e1e1e;
color: #ffffff;
}
</style>---
Pane Properties
Properties available on each <e-pane> element for configuring individual panes.
size
Type: string Description: Sets the initial size of the pane in pixels ('200px'), percentages ('30%'), or auto-sizing.
// Fixed pixel size
<e-pane size="250px"><ng-template #content>Sidebar</ng-template></e-pane>
// Percentage of container
<e-pane size="30%"><ng-template #content>Left Panel</ng-template></e-pane>
// Auto-sizing (flexible)
<e-pane><ng-template #content>Main Content</ng-template></e-pane>
// Mixed sizing example
<ejs-splitter height="400px" width="100%">
<e-panes>
<e-pane size="200px"><ng-template #content>Fixed Sidebar</ng-template></e-pane>
<e-pane size="50%"><ng-template #content>Main (50%)</ng-template></e-pane>
<e-pane><ng-template #content>Flexible</ng-template></e-pane>
</e-panes>
</ejs-splitter>min
Type: string Description: Sets the minimum size a pane can be resized to, preventing it from becoming too small. Use pixels or percentages.
// Minimum 100 pixels
<e-pane size="250px" min="100px"><ng-template #content>Content</ng-template></e-pane>
// Minimum 15% of container
<e-pane size="30%" min="15%"><ng-template #content>Panel</ng-template></e-pane>
// Comprehensive example with constraints
<ejs-splitter height="400px" width="100%">
<e-panes>
<e-pane size="250px" min="150px" max="400px">
<ng-template #content>Constrained Pane</ng-template>
</e-pane>
<e-pane min="200px">
<ng-template #content>Main Content</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>max
Type: string Description: Sets the maximum size a pane can be resized to. Use pixels or percentages.
// Maximum 500 pixels
<e-pane size="300px" max="500px"><ng-template #content>Content</ng-template></e-pane>
// Maximum 60% of container
<e-pane size="40%" max="60%"><ng-template #content>Panel</ng-template></e-pane>
// Sidebar with constraints
<ejs-splitter height="400px" width="100%">
<e-panes>
<e-pane size="250px" min="100px" max="350px">
<ng-template #content>Constrained Sidebar</ng-template>
</e-pane>
<e-pane>
<ng-template #content>Main Content</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>resizable
Type: boolean Default: true Description: Enables or disables resizing for the specific pane. Fixed panes cannot be dragged.
// Non-resizable sidebar (fixed)
<ejs-splitter height="400px" width="100%">
<e-panes>
<e-pane size="250px" [resizable]="false">
<ng-template #content>Fixed Sidebar</ng-template>
</e-pane>
<e-pane [resizable]="true">
<ng-template #content>Resizable Content</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
// All panes except first are resizable
<ejs-splitter height="400px" width="100%">
<e-panes>
<e-pane size="200px" [resizable]="false"><ng-template #content>Panel 1</ng-template></e-pane>
<e-pane [resizable]="true"><ng-template #content>Panel 2</ng-template></e-pane>
<e-pane [resizable]="true"><ng-template #content>Panel 3</ng-template></e-pane>
</e-panes>
</ejs-splitter>collapsible
Type: boolean Default: false Description: Makes a pane collapsible by showing an expand/collapse icon in the separator. Users can click to hide/show the pane.
// Collapsible panes
<ejs-splitter height="400px" width="100%">
<e-panes>
<e-pane size="200px" [collapsible]="true">
<ng-template #content>Filters (Collapsible)</ng-template>
</e-pane>
<e-pane [collapsible]="true">
<ng-template #content>Dashboard</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
// Mixed collapsible and fixed panes
<ejs-splitter height="500px" width="100%">
<e-panes>
<e-pane size="250px" [collapsible]="true">
<ng-template #content>Left Sidebar (Collapsible)</ng-template>
</e-pane>
<e-pane [collapsible]="false">
<ng-template #content>Main Content (Not Collapsible)</ng-template>
</e-pane>
<e-pane size="300px" [collapsible]="true">
<ng-template #content>Right Panel (Collapsible)</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>collapsed
Type: boolean Default: false Description: When true, the pane starts in a collapsed (hidden) state on component initialization.
// Start with first pane collapsed
<ejs-splitter height="400px" width="100%">
<e-panes>
<e-pane size="200px" [collapsible]="true" [collapsed]="true">
<ng-template #content>Initially Hidden</ng-template>
</e-pane>
<e-pane [collapsible]="true" [collapsed]="false">
<ng-template #content>Initially Visible</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
// Component control
import { Component, ViewChild } from '@angular/core';
import { SplitterComponent } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
template: `
<button (click)="togglePane()">Toggle First Pane</button>
<ejs-splitter #splitter height="400px" width="100%">
<e-panes>
<e-pane size="200px" [collapsible]="true" [collapsed]="isCollapsed">
<ng-template #content>Dynamic Pane</ng-template>
</e-pane>
<e-pane>
<ng-template #content>Content</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterDemoComponent {
@ViewChild('splitter') splitterRef!: SplitterComponent;
isCollapsed = false;
togglePane() {
this.isCollapsed = !this.isCollapsed;
}
}content
Type: string | HTMLElement Description: Specifies pane content as HTML string, plain text, or DOM element (alternative to ng-template).
// String content
<e-pane content="<strong>HTML Content</strong>"></e-pane>
// Plain text
<e-pane content="Simple Text"></e-pane>
// Template content (recommended for complex layouts)
<e-pane>
<ng-template #content>
<div class="pane-content">
<h3>Pane Title</h3>
<p>Complex content with Angular bindings</p>
</div>
</ng-template>
</e-pane>
// Dynamic content from component
import { Component } from '@angular/core';
@Component({
selector: 'app-splitter',
template: `
<ejs-splitter height="400px" width="100%">
<e-panes>
<e-pane [content]="dynamicContent"></e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
dynamicContent = '<p>Dynamic HTML Content</p>';
}cssClass
Type: string Description: Applies custom CSS class(es) to individual pane elements for targeted styling.
// Custom pane styling
<ejs-splitter height="400px" width="100%">
<e-panes>
<e-pane size="250px" cssClass="sidebar-pane">
<ng-template #content>Sidebar</ng-template>
</e-pane>
<e-pane cssClass="main-pane highlighted">
<ng-template #content>Main Content</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
// CSS
<style>
.sidebar-pane {
background-color: #f5f5f5;
padding: 15px;
border-right: 1px solid #ddd;
}
.main-pane {
background-color: #ffffff;
padding: 20px;
}
.main-pane.highlighted {
border: 2px solid #007bff;
}
</style>---
Methods
Public instance methods for programmatic control of the Splitter component. Access via ViewChild reference.
addPane(paneProperties, index)
Returns: void Description: Dynamically adds a new pane at the specified index with given properties.
import { Component, ViewChild } from '@angular/core';
import { SplitterComponent } from '@syncfusion/ej2-angular-layouts';
import { PanePropertiesModel } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
template: `
<button (click)="addNewPane()">Add Pane</button>
<ejs-splitter #splitter height="400px" width="100%">
<e-panes>
<e-pane size="250px"><ng-template #content>Pane 1</ng-template></e-pane>
<e-pane><ng-template #content>Pane 2</ng-template></e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
@ViewChild('splitter') splitterRef!: SplitterComponent;
// Add pane at end
addNewPane() {
const newPane: PanePropertiesModel = {
size: '200px',
content: '<div>New Pane</div>',
collapsible: true
};
const index = this.splitterRef.paneSettings.length;
this.splitterRef.addPane(newPane, index);
}
// Add pane at specific index
addPaneAtIndex() {
const newPane: PanePropertiesModel = {
size: '150px',
content: '<div>Inserted Pane</div>',
min: '100px',
max: '300px'
};
this.splitterRef.addPane(newPane, 1); // Insert at index 1
}
// Add pane with complex content
addComplexPane() {
const newPane: PanePropertiesModel = {
size: '300px',
content: '<h3>Dynamic Content</h3><p>Added at runtime</p>',
collapsible: true,
cssClass: 'new-pane'
};
const index = this.splitterRef.paneSettings.length;
this.splitterRef.addPane(newPane, index);
}
}Real-world Example - Tabbed Interface:
import { Component, ViewChild } from '@angular/core';
import { SplitterComponent } from '@syncfusion/ej2-angular-layouts';
import { PanePropertiesModel } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-tabbed-splitter',
template: `
<div>
<input [(ngModel)]="newTabName" placeholder="Tab name" />
<button (click)="addTab()">Add Tab</button>
</div>
<ejs-splitter #splitter orientation="Horizontal" height="400px" width="100%"></ejs-splitter>
`
})
export class TabbedSplitterComponent {
@ViewChild('splitter') splitterRef!: SplitterComponent;
newTabName = '';
tabCount = 0;
addTab() {
if (this.newTabName.trim()) {
const tabPane: PanePropertiesModel = {
size: '200px',
content: `<div><strong>${this.newTabName}</strong><p>Content for tab ${++this.tabCount}</p></div>`,
collapsible: true
};
const index = this.splitterRef.paneSettings.length;
this.splitterRef.addPane(tabPane, index);
this.newTabName = '';
}
}
}removePane(index)
Returns: void Description: Removes the pane at the specified index from the Splitter.
import { Component, ViewChild } from '@angular/core';
import { SplitterComponent } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
template: `
<button (click)="removeLast()">Remove Last Pane</button>
<button (click)="removeFirst()">Remove First Pane</button>
<ejs-splitter #splitter height="400px" width="100%">
<e-panes>
<e-pane size="200px"><ng-template #content>Pane 1</ng-template></e-pane>
<e-pane size="200px"><ng-template #content>Pane 2</ng-template></e-pane>
<e-pane><ng-template #content>Pane 3</ng-template></e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
@ViewChild('splitter') splitterRef!: SplitterComponent;
removeLast() {
const paneCount = this.splitterRef.paneSettings.length;
if (paneCount > 0) {
this.splitterRef.removePane(paneCount - 1);
}
}
removeFirst() {
if (this.splitterRef.paneSettings.length > 0) {
this.splitterRef.removePane(0);
}
}
}Real-world Example - Closable Tabs:
import { Component, ViewChild } from '@angular/core';
import { SplitterComponent } from '@syncfusion/ej2-angular-layouts';
import { PanePropertiesModel } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-closable-tabs',
template: `
<button (click)="addTab('New Tab')">Add Tab</button>
<button (click)="closeLastTab()">Close Last Tab</button>
<ejs-splitter #splitter orientation="Horizontal" height="400px" width="100%"></ejs-splitter>
`
})
export class ClosableTabsComponent {
@ViewChild('splitter') splitterRef!: SplitterComponent;
tabCount = 0;
addTab(name: string): void {
const tabPane: PanePropertiesModel = {
size: '200px',
content: `
<div style="display: flex; justify-content: space-between;">
<span>${name} ${++this.tabCount}</span>
</div>
`,
collapsible: true
};
const index = this.splitterRef.paneSettings.length;
this.splitterRef.addPane(tabPane, index);
}
closeTab(index: number): void {
if (index >= 0 && index < this.splitterRef.paneSettings.length) {
this.splitterRef.removePane(index);
}
}
closeLastTab(): void {
const paneCount = this.splitterRef.paneSettings.length;
if (paneCount > 0) {
this.splitterRef.removePane(paneCount - 1);
}
}
}expand(index)
Returns: void Description: Expands (shows) a collapsed pane at the given index.
import { Component, ViewChild } from '@angular/core';
import { SplitterComponent } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
template: `
<button (click)="expandFirstPane()">Expand Pane 0</button>
<ejs-splitter #splitter height="400px" width="100%">
<e-panes>
<e-pane size="200px" [collapsible]="true" [collapsed]="true">
<ng-template #content>Pane 1 (Collapsed)</ng-template>
</e-pane>
<e-pane [collapsible]="true">
<ng-template #content>Pane 2</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
@ViewChild('splitter') splitterRef!: SplitterComponent;
expandFirstPane() {
this.splitterRef.expand(0);
}
}collapse(index)
Returns: void Description: Collapses (hides) an expanded pane at the given index.
import { Component, ViewChild } from '@angular/core';
import { SplitterComponent } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
template: `
<button (click)="collapseFirstPane()">Collapse Pane 0</button>
<ejs-splitter #splitter height="400px" width="100%">
<e-panes>
<e-pane size="200px" [collapsible]="true">
<ng-template #content>Pane 1</ng-template>
</e-pane>
<e-pane [collapsible]="true">
<ng-template #content>Pane 2</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
@ViewChild('splitter') splitterRef!: SplitterComponent;
collapseFirstPane() {
this.splitterRef.collapse(0);
}
}---
Events
The Splitter component emits events at various lifecycle and user interaction points. Subscribe using Angular's event binding syntax (eventName)="handler($event)".
Most Common Events
created
Trigger: After the Splitter component and all panes are initialized Argument Type: Object Description: Fired once when the component is fully created and ready for interaction.
import { Component } from '@angular/core';
@Component({
selector: 'app-splitter',
template: `
<ejs-splitter (created)="onCreated()" height="400px" width="100%">
<e-panes>
<e-pane><ng-template #content>Content</ng-template></e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
onCreated() {
console.log('Splitter created and ready');
// Initialize custom logic, fetch data, etc.
}
}resizing
Trigger: While user is dragging the separator (continuous updates) Argument Type: ResizingEventArgs Description: Fired continuously while resizing occurs. Use to monitor pane size changes in real-time.
ResizingEventArgs Properties:
element(HTMLElement): Root element of the resizing paneevent(Event): Native DOM event objectindex(number[]): Index of resizing panepane(HTMLElement[]): Pane elementspaneSize(number[]): Current pane sizes during resizeseparator(HTMLElement): Separator element being dragged
import { Component } from '@angular/core';
import { ResizingEventArgs } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
template: `
<div>Current sizes: {{ paneSize }}</div>
<ejs-splitter (resizing)="onResizing($event)" height="400px" width="100%">
<e-panes>
<e-pane size="250px"><ng-template #content>Left Pane</ng-template></e-pane>
<e-pane><ng-template #content>Right Pane</ng-template></e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
paneSize = '';
onResizing(event: ResizingEventArgs) {
console.log('Resizing in progress');
console.log('Pane sizes:', event.paneSize);
console.log('Pane index:', event.index);
this.paneSize = event.paneSize?.join(', ') || '';
}
}resizeStop
Trigger: When user completes resizing (releases mouse) Argument Type: ResizingEventArgs Description: Fired when resize operation completes. Use to persist final pane sizes or trigger post-resize updates.
import { Component } from '@angular/core';
import { ResizingEventArgs } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
template: `
<ejs-splitter (resizeStop)="onResizeStop($event)" height="400px" width="100%">
<e-panes>
<e-pane size="250px"><ng-template #content>Left</ng-template></e-pane>
<e-pane><ng-template #content>Right</ng-template></e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
onResizeStop(event: ResizingEventArgs) {
console.log('Resize completed');
console.log('Final pane size:', event.paneSize);
// Save final sizes to localStorage or server
localStorage.setItem('paneSize', JSON.stringify(event.paneSize));
}
}beforeExpand
Trigger: Before a pane is expanded (can be prevented) Argument Type: BeforeExpandEventArgs Description: Fired before expand action. Set cancel = true in event handler to prevent expansion.
BeforeExpandEventArgs Properties:
cancel(boolean): Set totrueto prevent expansionelement(HTMLElement): Root element after control createdevent(Event): Default event argumentsindex(number[]): Index of pane being expandedpane(HTMLElement[]): Pane elementsseparator(HTMLElement): Respective split-bar element
import { Component } from '@angular/core';
import { BeforeExpandEventArgs } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
template: `
<ejs-splitter (beforeExpand)="onBeforeExpand($event)" height="400px" width="100%">
<e-panes>
<e-pane size="200px" [collapsible]="true" [collapsed]="true">
<ng-template #content>Pane 1</ng-template>
</e-pane>
<e-pane [collapsible]="true">
<ng-template #content>Pane 2</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
onBeforeExpand(event: BeforeExpandEventArgs) {
console.log('Before expand - index:', event.index);
// Prevent expansion under certain conditions
if (event.index && event.index[0] === 0) {
// Allow only pane 0 to expand
event.cancel = false;
}
}
}expanded
Trigger: After a pane is successfully expanded Argument Type: ExpandedEventArgs Description: Fired after expand completes. Pane is now visible and fully rendered.
ExpandedEventArgs Properties:
element(HTMLElement): Root element after control createdevent(Event): Default event argumentsindex(number[]): Index of expanded panepane(HTMLElement[]): Pane elementsseparator(HTMLElement): Split-bar element
import { Component } from '@angular/core';
import { ExpandedEventArgs } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
template: `
<ejs-splitter (expanded)="onExpanded($event)" height="400px" width="100%">
<e-panes>
<e-pane size="200px" [collapsible]="true">
<ng-template #content>Expandable Pane</ng-template>
</e-pane>
<e-pane [collapsible]="true">
<ng-template #content>Content</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
onExpanded(event: ExpandedEventArgs) {
console.log('Pane expanded - index:', event.index);
console.log('Expanded element:', event.element);
// Trigger animations or load content
}
}beforeCollapse
Trigger: Before a pane is collapsed (can be prevented) Argument Type: BeforeExpandEventArgs Description: Fired before collapse action. Set cancel = true to prevent collapse.
import { Component } from '@angular/core';
import { BeforeExpandEventArgs } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
template: `
<ejs-splitter (beforeCollapse)="onBeforeCollapse($event)" height="400px" width="100%">
<e-panes>
<e-pane size="200px" [collapsible]="true">
<ng-template #content>Pane 1</ng-template>
</e-pane>
<e-pane [collapsible]="true">
<ng-template #content>Pane 2</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
onBeforeCollapse(event: BeforeExpandEventArgs) {
console.log('Before collapse - index:', event.index);
// Validate before collapsing
if (this.hasUnsavedChanges()) {
event.cancel = true; // Prevent collapse if unsaved changes
alert('Please save changes before collapsing');
}
}
hasUnsavedChanges(): boolean {
// Your validation logic
return false;
}
}collapsed
Trigger: After a pane is successfully collapsed Argument Type: ExpandedEventArgs Description: Fired after collapse completes. Pane is now hidden.
import { Component } from '@angular/core';
import { ExpandedEventArgs } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
template: `
<ejs-splitter (collapsed)="onCollapsed($event)" height="400px" width="100%">
<e-panes>
<e-pane size="200px" [collapsible]="true">
<ng-template #content>Collapsible Pane</ng-template>
</e-pane>
<e-pane [collapsible]="true">
<ng-template #content>Content</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
onCollapsed(event: ExpandedEventArgs) {
console.log('Pane collapsed - index:', event.index);
// Cleanup or save state
}
}All Events Reference
resizeStart
Trigger: When user starts dragging a separator Argument Type: ResizeEventArgs Description: Fired when resize begins (before resizing event).
ResizeEventArgs Properties:
cancel(boolean): Set totrueto prevent resizeelement(HTMLElement): Root element of resizing paneevent(Event): Contains native DOM eventindex(number[]): Index of resizing panepane(HTMLElement[]): Pane elementsseparator(HTMLElement): Separator element
import { Component } from '@angular/core';
import { ResizeEventArgs } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
template: `
<ejs-splitter (resizeStart)="onResizeStart($event)" height="400px" width="100%">
<e-panes>
<e-pane size="250px"><ng-template #content>Pane 1</ng-template></e-pane>
<e-pane><ng-template #content>Pane 2</ng-template></e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
onResizeStart(event: ResizeEventArgs) {
console.log('Resize started at pane index:', event.index);
// Prevent resize under conditions
if (this.shouldPreventResize()) {
event.cancel = true;
}
}
shouldPreventResize(): boolean {
return false; // Your logic
}
}beforeSanitizeHtml
Trigger: Before HTML content is sanitized for security Argument Type: BeforeSanitizeHtmlArgs Description: Fired when HTML is about to be sanitized. Allows custom sanitization logic. See Security Best Practices.
BeforeSanitizeHtmlArgs Properties:
cancel(boolean): Prevent default sanitizationhelper(Function): Callback returning sanitized HTML stringselectors(SanitizeSelectors): Block lists for tags/attributes
import { Component } from '@angular/core';
import { BeforeSanitizeHtmlArgs } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
template: `
<ejs-splitter (beforeSanitizeHtml)="onBeforeSanitize($event)" height="400px" width="100%">
<e-panes>
<e-pane [content]="htmlContent"></e-pane>
</e-panes>
</ejs-splitter>
`
})
export class SplitterComponent {
htmlContent = '<div><strong>Safe Content</strong></div>';
onBeforeSanitize(event: BeforeSanitizeHtmlArgs) {
console.log('HTML sanitization in progress');
console.log('Blocked selectors:', event.selectors);
// Custom sanitization if needed
if (event.helper) {
// Perform custom cleaning
const cleaned = event.helper();
console.log('Cleaned HTML:', cleaned);
}
}
}---
Complete Working Examples
Example 1: Dashboard with All Events
import { Component, ViewChild } from '@angular/core';
import { SplitterComponent, ResizingEventArgs, ExpandedEventArgs, BeforeExpandEventArgs } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-dashboard',
template: `
<div class="dashboard">
<div class="event-log">
<h4>Event Log</h4>
<div>{{ eventMessages }}</div>
</div>
<ejs-splitter
#splitter
height="500px"
width="100%"
(created)="onCreated()"
(resizing)="onResizing($event)"
(resizeStop)="onResizeStop($event)"
(beforeExpand)="onBeforeExpand($event)"
(expanded)="onExpanded($event)"
(beforeCollapse)="onBeforeCollapse($event)"
(collapsed)="onCollapsed($event)"
>
<e-panes>
<e-pane size="250px" [collapsible]="true">
<ng-template #content>
<div class="sidebar">Filters Panel</div>
</ng-template>
</e-pane>
<e-pane [collapsible]="true">
<ng-template #content>
<div class="content">Dashboard Content</div>
</ng-template>
</e-pane>
<e-pane size="300px" [collapsible]="true">
<ng-template #content>
<div class="details">Details Panel</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
</div>
`,
styles: [`
.event-log { margin-bottom: 10px; }
.sidebar, .content, .details { padding: 15px; }
`]
})
export class DashboardComponent {
@ViewChild('splitter') splitterRef!: SplitterComponent;
eventMessages = 'Waiting for events...';
onCreated() {
this.log('✓ Splitter created');
}
onResizing(event: ResizingEventArgs) {
this.log(`▶ Resizing... Sizes: ${event.paneSize?.join(', ')}`);
}
onResizeStop(event: ResizingEventArgs) {
this.log(`✓ Resize stopped at ${event.paneSize?.join(', ')}`);
}
onBeforeExpand(event: BeforeExpandEventArgs) {
this.log(`? Before expand pane ${event.index?.[0]}`);
}
onExpanded(event: ExpandedEventArgs) {
this.log(`✓ Pane ${event.index?.[0]} expanded`);
}
onBeforeCollapse(event: BeforeExpandEventArgs) {
this.log(`? Before collapse pane ${event.index?.[0]}`);
}
onCollapsed(event: ExpandedEventArgs) {
this.log(`✓ Pane ${event.index?.[0]} collapsed`);
}
log(message: string) {
this.eventMessages = message + '\n' + this.eventMessages;
}
}---
Reference: For more information on specific features, see:
- Dynamic Pane Manipulation for
addPane()andremovePane()patterns - Security Best Practices for HTML sanitization
- Content Loading for content property types
Content Loading Methods
Splitter supports multiple ways to populate pane content: HTML strings, templates, DOM selectors, and dynamic content.
String Content
Simple Text/HTML String
Use the content property for quick content:
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-string-content',
standalone: true,
imports: [SplitterModule],
template: `
<ejs-splitter height='250px' width='600px'>
<e-panes>
<e-pane size='200px' content='<div class="content"><h3>Left Pane</h3><p>String content</p></div>'>
</e-pane>
<e-pane size='200px' content='<div class="content"><h3>Right Pane</h3><p>HTML string</p></div>'>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.content {
padding: 15px;
}
`]
})
export class StringContentComponent {}HTML with Inline Styles
<e-pane size='200px' content='
<div style="background: #f5f5f5; padding: 20px; border-radius: 8px;">
<h3 style="color: #007bff;">Styled Content</h3>
<p>Content with inline styles</p>
</div>
'>
</e-pane>Advantages
✓ Quick and simple for static content ✓ No component lifecycle overhead ✓ Works for plain HTML ✓ Good for debugging
Disadvantages
✗ No Angular binding (not reactive) ✗ No event handlers ✗ Hard to maintain complex HTML ✗ XSS vulnerability if user input (use with caution)
---
Template Content
ng-template Content
Use <ng-template> with #content reference for Angular integration:
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-template-content',
standalone: true,
imports: [SplitterModule],
template: `
<ejs-splitter height='300px' width='600px'>
<e-panes>
<e-pane size='200px'>
<ng-template #content>
<div class='pane'>
<h3>Template Content</h3>
<p>Fully Angular-integrated</p>
</div>
</ng-template>
</e-pane>
<e-pane size='200px'>
<ng-template #content>
<div class='pane'>
<h3>Right Pane</h3>
<p>Also template</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.pane {
padding: 20px;
}
`]
})
export class TemplateContentComponent {}Data Binding in Template
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-binding-template',
standalone: true,
imports: [SplitterModule, CommonModule],
template: `
<ejs-splitter height='300px' width='600px'>
<e-panes>
<e-pane size='200px'>
<ng-template #content>
<div class='pane'>
<h3>{{ title }}</h3>
<ul>
<li *ngFor='let item of leftItems'>{{ item }}</li>
</ul>
</div>
</ng-template>
</e-pane>
<e-pane size='200px'>
<ng-template #content>
<div class='pane'>
<h3>{{ rightTitle }}</h3>
<p>Count: {{ counter }}</p>
<button (click)='increment()'>Increment</button>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.pane {
padding: 20px;
}
button {
padding: 8px 15px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #0056b3;
}
`]
})
export class BindingTemplateComponent {
title = 'Left Panel';
rightTitle = 'Right Panel';
counter = 0;
leftItems = ['Item 1', 'Item 2', 'Item 3'];
increment(): void {
this.counter++;
}
}Event Handling in Template
<ejs-splitter height='300px' width='600px'>
<e-panes>
<e-pane size='200px'>
<ng-template #content>
<div class='pane'>
<button (click)='onLeftClick()'>Click Me</button>
<p *ngIf='leftClicked'>Button was clicked!</p>
</div>
</ng-template>
</e-pane>
<e-pane size='200px'>
<ng-template #content>
<div class='pane'>
<input [(ngModel)]='inputValue' placeholder='Type here' />
<p>You typed: {{ inputValue }}</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>export class EventTemplateComponent {
leftClicked = false;
inputValue = '';
onLeftClick(): void {
this.leftClicked = true;
setTimeout(() => {
this.leftClicked = false;
}, 1000);
}
}Advantages
✓ Full Angular integration (binding, directives, pipes) ✓ Reactive data flow ✓ Event handlers and two-way binding ✓ Type-safe ✓ Easy to maintain
Disadvantages
✗ More setup code ✗ Requires CommonModule for ngIf, ngFor ✗ More memory per pane (component instances)
---
DOM Selector Content
Reference External HTML Elements
import { Component, ViewChild } from '@angular/core';
import { SplitterModule, SplitterComponent } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-selector-content',
standalone: true,
imports: [SplitterModule],
template: `
<!-- Hidden content containers -->
<div id='left-pane-content' style='display: none;'>
<div>
<h3>Left Content</h3>
<p>Hidden in DOM, referenced by selector</p>
</div>
</div>
<div id='middle-pane-content' style='display: none;'>
<div>
<h3>Middle Content</h3>
<p>Also hidden initially</p>
</div>
</div>
<div id='right-pane-content' style='display: none;'>
<div>
<h3>Right Content</h3>
<p>Loaded on demand</p>
</div>
</div>
<!-- Splitter using selectors -->
<ejs-splitter #splitter height='250px' width='100%' separatorSize='4'></ejs-splitter>
`
})
export class SelectorContentComponent {
@ViewChild('splitter') splitterObj?: SplitterComponent;
ngAfterViewInit() {
// Set pane settings with selectors after view init
this.splitterObj!.paneSettings = [
{ size: '25%', min: '60px', content: '#left-pane-content' },
{ size: '50%', min: '60px', content: '#middle-pane-content' },
{ size: '25%', min: '60px', content: '#right-pane-content' }
];
}
}Dynamic Content Containers
<div id='user-panel' style='display: none;'>
<div class='panel-content'>
<h3>User Profile</h3>
<img src='avatar.jpg' alt='User' />
<p>Name: John Doe</p>
</div>
</div>
<div id='settings-panel' style='display: none;'>
<div class='panel-content'>
<h3>Settings</h3>
<label>
<input type='checkbox' />
Enable notifications
</label>
</div>
</div>
<ejs-splitter #splitter height='400px' width='100%'></ejs-splitter>ngAfterViewInit() {
this.splitterObj!.paneSettings = [
{ size: '30%', content: '#user-panel' },
{ size: '70%', content: '#settings-panel' }
];
}Advantages
✓ Content separated from splitter markup ✓ Reusable content containers ✓ Good for complex HTML ✓ Cleaner template
Disadvantages
✗ Content must exist in DOM ✗ Harder to bind/update data ✗ Less discoverable (selectors in code)
---
Dynamic Content Updates
Update Content After Initialization
import { Component, ViewChild } from '@angular/core';
import { SplitterModule, SplitterComponent } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-dynamic-content',
standalone: true,
imports: [SplitterModule],
template: `
<div style='margin-bottom: 20px'>
<button class='e-btn' (click)='loadData()'>Load Data</button>
<button class='e-btn' (click)='clearData()'>Clear</button>
</div>
<ejs-splitter #splitter height='300px' width='100%'>
<e-panes>
<e-pane size='200px'>
<ng-template #content>
<div class='pane'>
<h3>Data Panel</h3>
<div id='data-container'>
Click "Load Data" to load content...
</div>
</div>
</ng-template>
</e-pane>
<e-pane size='200px'>
<ng-template #content>
<div class='pane'>
<h3>Status</h3>
<p id='status'>Ready</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.pane {
padding: 20px;
}
button {
padding: 8px 15px;
margin-right: 10px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #0056b3;
}
`]
})
export class DynamicContentComponent {
@ViewChild('splitter') splitterObj?: SplitterComponent;
loadData(): void {
const container = document.getElementById('data-container');
const status = document.getElementById('status');
if (container && status) {
container.innerHTML = `
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
`;
status.textContent = 'Data loaded at ' + new Date().toLocaleTimeString();
}
}
clearData(): void {
const container = document.getElementById('data-container');
const status = document.getElementById('status');
if (container && status) {
container.innerHTML = 'Cleared';
status.textContent = 'Cleared at ' + new Date().toLocaleTimeString();
}
}
}Real-Time Content Updates
import { Component, ViewChild, OnDestroy } from '@angular/core';
import { SplitterModule, SplitterComponent } from '@syncfusion/ej2-angular-layouts';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-realtime-content',
standalone: true,
imports: [SplitterModule, CommonModule],
template: `
<ejs-splitter height='300px' width='100%'>
<e-panes>
<e-pane size='200px'>
<ng-template #content>
<div class='pane'>
<h3>Live Updates</h3>
<p>Time: {{ currentTime }}</p>
<p>Count: {{ counter }}</p>
</div>
</ng-template>
</e-pane>
<e-pane size='200px'>
<ng-template #content>
<div class='pane'>
<h3>Info</h3>
<p>Updates every second</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.pane {
padding: 20px;
}
`]
})
export class RealtimeContentComponent implements OnDestroy {
currentTime = new Date().toLocaleTimeString();
counter = 0;
private intervalId?: number;
ngOnInit(): void {
this.intervalId = window.setInterval(() => {
this.currentTime = new Date().toLocaleTimeString();
this.counter++;
}, 1000);
}
ngOnDestroy(): void {
if (this.intervalId) {
clearInterval(this.intervalId);
}
}
}---
Content Loading Best Practices
✓ Use templates for complex, interactive content ✓ Use string content for simple, static content ✓ Use selectors for reusable content containers ✓ Always clean up resources in ngOnDestroy ✓ Consider performance with many panes (component instances) ✓ Test content updates for memory leaks ✓ Use change detection strategically (OnPush for performance)
Dynamic Pane Manipulation
Programmatically add, remove, and manage panes at runtime to create responsive, user-driven interfaces.
Adding Panes
Add Pane with addPane() Method
import { Component, ViewChild } from '@angular/core';
import { SplitterModule, SplitterComponent, PanePropertiesModel } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-add-pane',
standalone: true,
imports: [SplitterModule],
template: `
<div style='margin-bottom: 20px'>
<button class='e-btn' (click)='addPane()'>Add Pane</button>
<p>Panes: {{ getPaneCount() }}</p>
</div>
<ejs-splitter #splitter height='250px' width='600px'>
<e-panes>
<e-pane size='150px'>
<ng-template #content>
<div class='content'>Pane 1</div>
</ng-template>
</e-pane>
<e-pane size='150px'>
<ng-template #content>
<div class='content'>Pane 2</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.content {
padding: 15px;
text-align: center;
}
button {
padding: 8px 15px;
background: #28a745;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #218838;
}
`]
})
export class AddPaneComponent {
@ViewChild('splitter') splitterObj?: SplitterComponent;
// Define new pane properties
paneDetails: PanePropertiesModel = {
size: '190px',
content: 'New Pane',
min: '30px',
max: '250px'
};
addPane(): void {
if (this.splitterObj) {
// Add pane at index 1 (between first and second pane)
this.splitterObj.addPane(this.paneDetails, 1);
}
}
getPaneCount(): number {
return this.splitterObj ? this.splitterObj.paneSettings.length : 0;
}
}Add Pane with HTML Content
paneDetails: PanePropertiesModel = {
size: '150px',
content: '<div style="padding: 15px; text-align: center;"><h4>New Panel</h4><p>Dynamically added</p></div>',
min: '50px',
max: '300px'
};
addPane(): void {
this.splitterObj!.addPane(this.paneDetails, 0); // Add at beginning
}Add Pane with ng-template-like Content
// Content as HTML string
paneDetails: PanePropertiesModel = {
size: '200px',
content: `
<div style="padding: 20px;">
<h3>Dynamic Pane</h3>
<p>Added at runtime: ${new Date().toLocaleTimeString()}</p>
</div>
`,
min: '100px'
};Insert at Specific Position
addPane(): void {
// Add at index 0 (beginning)
this.splitterObj!.addPane(this.paneDetails, 0);
// Add at index 1 (middle)
this.splitterObj!.addPane(this.paneDetails, 1);
// Add at end (no index = append)
this.splitterObj!.addPane(this.paneDetails);
}Multiple Add Operations
import { Component, ViewChild } from '@angular/core';
import { SplitterModule, SplitterComponent, PanePropertiesModel } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-multi-add',
standalone: true,
imports: [SplitterModule],
template: `
<button class='e-btn' (click)='addThreePanes()'>Add 3 Panes</button>
<ejs-splitter #splitter height='300px' width='100%'>
<e-panes>
<e-pane size='150px'>
<ng-template #content>
<div class='content'>Initial Pane</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
button {
padding: 10px 20px;
margin-bottom: 10px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.content {
padding: 15px;
text-align: center;
}
`]
})
export class MultiAddComponent {
@ViewChild('splitter') splitterObj?: SplitterComponent;
addThreePanes(): void {
const panes: PanePropertiesModel[] = [
{ size: '100px', content: 'New Pane 1', min: '50px' },
{ size: '100px', content: 'New Pane 2', min: '50px' },
{ size: '100px', content: 'New Pane 3', min: '50px' }
];
panes.forEach((pane, index) => {
this.splitterObj!.addPane(pane, index + (this.splitterObj?.paneSettings.length || 0));
});
}
}---
Removing Panes
Remove Pane with removePane() Method
import { Component, ViewChild } from '@angular/core';
import { SplitterModule, SplitterComponent } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-remove-pane',
standalone: true,
imports: [SplitterModule],
template: `
<div style='margin-bottom: 20px'>
<button class='e-btn' (click)='removePane()'>Remove Pane</button>
<p>Panes: {{ getPaneCount() }}</p>
</div>
<ejs-splitter #splitter height='250px' width='600px'>
<e-panes>
<e-pane size='200px'>
<ng-template #content>
<div class='content'>Pane 1</div>
</ng-template>
</e-pane>
<e-pane size='200px'>
<ng-template #content>
<div class='content'>Pane 2</div>
</ng-template>
</e-pane>
<e-pane size='200px'>
<ng-template #content>
<div class='content'>Pane 3</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.content {
padding: 15px;
text-align: center;
}
button {
padding: 8px 15px;
background: #dc3545;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #c82333;
}
`]
})
export class RemovePaneComponent {
@ViewChild('splitter') splitterObj?: SplitterComponent;
removePane(): void {
if (this.splitterObj) {
const paneCount = this.splitterObj.paneSettings.length;
// Keep at least 1 pane
if (paneCount > 1) {
// Remove pane at index 1 (middle pane)
this.splitterObj.removePane(1);
} else {
alert('Cannot remove last pane');
}
}
}
getPaneCount(): number {
return this.splitterObj ? this.splitterObj.paneSettings.length : 0;
}
}Remove by Index
// Remove first pane (index 0)
this.splitterObj!.removePane(0);
// Remove middle pane (index 1)
this.splitterObj!.removePane(1);
// Remove last pane
const lastIndex = this.splitterObj!.paneSettings.length - 1;
this.splitterObj!.removePane(lastIndex);Conditional Removal
removeLastPane(): void {
const paneCount = this.splitterObj!.paneSettings.length;
if (paneCount > 2) {
this.splitterObj!.removePane(paneCount - 1);
}
}
removeAllButFirst(): void {
while (this.splitterObj!.paneSettings.length > 1) {
this.splitterObj!.removePane(1);
}
}---
Pane Constraints: Min & Max Sizes
Add Pane with Constraints
import { Component, ViewChild } from '@angular/core';
import { SplitterModule, SplitterComponent, PanePropertiesModel } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-constrained-pane',
standalone: true,
imports: [SplitterModule],
template: `
<button class='e-btn' (click)='addConstrainedPane()'>Add Constrained Pane</button>
<ejs-splitter #splitter height='250px' width='600px'>
<e-panes>
<e-pane size='150px'>
<ng-template #content>
<div class='content'>Base Pane</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.content {
padding: 15px;
text-align: center;
}
button {
padding: 10px 20px;
margin-bottom: 10px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
`]
})
export class ConstrainedPaneComponent {
@ViewChild('splitter') splitterObj?: SplitterComponent;
paneDetails: PanePropertiesModel = {
size: '150px',
content: 'Constrained Pane',
min: '60px', // Can't shrink below 60px
max: '300px' // Can't grow beyond 300px
};
addConstrainedPane(): void {
this.splitterObj!.addPane(this.paneDetails);
}
}Percentage-Based Constraints
paneDetails: PanePropertiesModel = {
size: '30%',
content: 'Responsive Pane',
min: '15%', // Minimum 15% of container
max: '50%' // Maximum 50% of container
};---
Real-World Examples
Tabbed Interface with Dynamic Tabs
import { Component, ViewChild } from '@angular/core';
import { SplitterModule, SplitterComponent, PanePropertiesModel } from '@syncfusion/ej2-angular-layouts';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-dynamic-tabs',
standalone: true,
imports: [SplitterModule, CommonModule],
template: `
<div class='controls'>
<input
[(ngModel)]='tabName'
placeholder='Tab name'
(keyup.enter)='addTab()' />
<button class='e-btn' (click)='addTab()'>Add Tab</button>
<button class='e-btn' (click)='removeLastTab()' [disabled]='tabs.length <= 1'>
Remove Last
</button>
<p>Total tabs: {{ tabs.length }}</p>
</div>
<ejs-splitter #splitter height='300px' width='100%'>
<e-panes>
<e-pane size='150px'>
<ng-template #content>
<div class='tab-list'>
<div *ngFor='let tab of tabs; let i = index' class='tab-item'>
<strong>{{ tab }}</strong>
</div>
</div>
</ng-template>
</e-pane>
<e-pane>
<ng-template #content>
<div class='tab-content'>
<p>Tab content goes here</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.controls {
padding: 15px;
background-color: #f5f5f5;
margin-bottom: 10px;
border-radius: 4px;
}
input {
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
margin-right: 10px;
}
button {
padding: 8px 15px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin-right: 5px;
}
button:hover {
background: #0056b3;
}
button:disabled {
background: #ccc;
cursor: not-allowed;
}
.tab-list {
padding: 15px;
background-color: #fafafa;
}
.tab-item {
padding: 10px;
border-bottom: 1px solid #eee;
cursor: pointer;
}
.tab-item:hover {
background-color: #e8e8e8;
}
.tab-content {
padding: 20px;
}
`]
})
export class DynamicTabsComponent {
@ViewChild('splitter') splitterObj?: SplitterComponent;
tabName = '';
tabs: string[] = ['Overview', 'Settings'];
addTab(): void {
if (this.tabName.trim()) {
this.tabs.push(this.tabName);
this.tabName = '';
}
}
removeLastTab(): void {
if (this.tabs.length > 1) {
this.tabs.pop();
}
}
}Editor with Add/Remove Panes
import { Component, ViewChild } from '@angular/core';
import { SplitterModule, SplitterComponent, PanePropertiesModel } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-editor-panes',
standalone: true,
imports: [SplitterModule],
template: `
<div class='toolbar'>
<button class='e-btn' (click)='splitPane()'>Split View</button>
<button class='e-btn' (click)='closePane()' [disabled]='getPaneCount() <= 1'>Close</button>
<span>Views: {{ getPaneCount() }}</span>
</div>
<ejs-splitter #splitter height='400px' width='100%'>
<e-panes>
<e-pane size='300px' min='150px'>
<ng-template #content>
<div class='editor-pane'>
<div class='editor-tab'>main.ts</div>
<div class='editor-content'>
<pre><code>import {{ bootstrapApplication }} from '@angular/platform-browser';
import {{ AppComponent }} from './app.component';</code></pre>
</div>
</div>
</ng-template>
</e-pane>
<e-pane size='300px' min='150px'>
<ng-template #content>
<div class='editor-pane'>
<div class='editor-tab'>app.component.ts</div>
<div class='editor-content'>
<pre><code>export class AppComponent {{
title = 'My App';
}}</code></pre>
</div>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.toolbar {
display: flex;
gap: 10px;
align-items: center;
padding: 15px;
background-color: #f5f5f5;
border-bottom: 1px solid #ddd;
}
button {
padding: 8px 15px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover:not(:disabled) {
background: #0056b3;
}
button:disabled {
background: #ccc;
cursor: not-allowed;
}
.editor-pane {
display: flex;
flex-direction: column;
height: 100%;
}
.editor-tab {
background-color: #f5f5f5;
padding: 10px 15px;
border-bottom: 1px solid #ddd;
font-weight: bold;
}
.editor-content {
flex: 1;
overflow: auto;
background-color: #1e1e1e;
color: #d4d4d4;
padding: 15px;
font-family: 'Courier New', monospace;
}
pre {
margin: 0;
}
`]
})
export class EditorPanesComponent {
@ViewChild('splitter') splitterObj?: SplitterComponent;
paneCounter = 2;
splitPane(): void {
this.paneCounter++;
const newPane: PanePropertiesModel = {
size: '300px',
min: '150px',
content: `
<div style="padding: 15px; background: #fafafa;">
<h4>Pane ${this.paneCounter}</h4>
<p>Dynamically added editor pane</p>
</div>
`
};
this.splitterObj!.addPane(newPane);
}
closePane(): void {
const count = this.getPaneCount();
if (count > 1) {
this.splitterObj!.removePane(count - 1);
}
}
getPaneCount(): number {
return this.splitterObj ? this.splitterObj.paneSettings.length : 0;
}
}---
Best Practices
✓ Always check pane count before removing (keep at least 1 pane) ✓ Set sensible min/max constraints to prevent broken layouts ✓ Use size='auto' for flexible panes when adding dynamically ✓ Test performance with many dynamically added panes ✓ Clean up references when removing panes ✓ Consider user experience (animations, feedback) ✓ Provide undo/redo for complex multi-pane operations
---
Methods & Events Reference
Methods
The Splitter component provides the following public methods for programmatic control:
addPane(paneProperties: PanePropertiesModel, index?: number): void
Adds a new pane to the Splitter at the specified index or at the end.
Parameters:
paneProperties(PanePropertiesModel): Configuration object for the new paneindex(optional, number): Position to insert the pane (0-based). If omitted, pane is appended
Example:
const newPane: PanePropertiesModel = {
size: '200px',
content: '<div>New Pane</div>',
min: '100px',
max: '400px',
collapsible: true
};
// Add at end
this.splitterRef.addPane(newPane);
// Insert at index 1
this.splitterRef.addPane(newPane, 1);removePane(index: number): void
Removes the pane at the specified index.
Parameters:
index(number): 0-based index of pane to remove
Example:
// Remove first pane
this.splitterRef.removePane(0);
// Remove last pane
const lastIndex = this.splitterRef.paneSettings.length - 1;
this.splitterRef.removePane(lastIndex);expand(index: number): void
Expands (shows) a collapsed pane at the specified index.
Parameters:
index(number): 0-based index of pane to expand
Example:
// Expand first pane
this.splitterRef.expand(0);collapse(index: number): void
Collapses (hides) an expanded pane at the specified index.
Parameters:
index(number): 0-based index of pane to collapse
Example:
// Collapse pane at index 1
this.splitterRef.collapse(1);---
Events
Subscribe to Splitter events using Angular's event binding (eventName)="handler($event)".
created
When it fires: After the Splitter component and all panes are initialized and rendered Argument: Generic Object
<ejs-splitter (created)="onCreated()">
<e-panes>
<e-pane><ng-template #content>Content</ng-template></e-pane>
</e-panes>
</ejs-splitter>
onCreated() {
console.log('Splitter component created and ready');
// Initialize custom logic, fetch data, setup listeners
}resizeStart
When it fires: When user begins dragging a separator (mouse down) Argument: ResizeEventArgs
ResizeEventArgs Properties:
cancel(boolean): Set totrueto prevent resizeelement(HTMLElement): Root element of resizing paneevent(Event): Native DOM mouse eventindex(number[]): Index of pane being resizedpane(HTMLElement[]): Pane DOM elementsseparator(HTMLElement): Separator element being dragged
import { ResizeEventArgs } from '@syncfusion/ej2-angular-layouts';
onResizeStart(args: ResizeEventArgs) {
console.log('Resize started for pane:', args.index);
// Prevent resize if certain conditions met
if (this.shouldLockResize()) {
args.cancel = true;
}
}resizing
When it fires: Continuously while user is dragging separator (high frequency) Argument: ResizingEventArgs
ResizingEventArgs Properties:
element(HTMLElement): Root element of resizing paneevent(Event): Native DOM eventindex(number[]): Index of resizing panepane(HTMLElement[]): Pane elements- `paneSize` (number[]): Current pane sizes during resize operation
separator(HTMLElement): Separator element
import { ResizingEventArgs } from '@syncfusion/ej2-angular-layouts';
onResizing(args: ResizingEventArgs) {
// Monitor pane sizes in real-time
console.log('Current sizes:', args.paneSize);
// Update UI or perform validations
this.updatePaneSizeDisplay(args.paneSize);
}
updatePaneSizeDisplay(sizes: number[]) {
this.displayedSizes = sizes.map(s => Math.round(s) + 'px').join(' | ');
}resizeStop
When it fires: When user completes resize (releases mouse) Argument: ResizingEventArgs
ResizingEventArgs Properties: Same as resizing event
import { ResizingEventArgs } from '@syncfusion/ej2-angular-layouts';
onResizeStop(args: ResizingEventArgs) {
console.log('Resize completed');
console.log('Final pane sizes:', args.paneSize);
// Persist size to localStorage/server
localStorage.setItem('splitterSizes', JSON.stringify(args.paneSize));
}beforeExpand
When it fires: Just before a pane begins expanding (can be cancelled) Argument: BeforeExpandEventArgs
BeforeExpandEventArgs Properties:
- `cancel` (boolean): Set to
trueto prevent expansion element(HTMLElement): Root elementevent(Event): Default event argumentsindex(number[]): Index of pane being expandedpane(HTMLElement[]): Pane elementsseparator(HTMLElement): Split-bar element
import { BeforeExpandEventArgs } from '@syncfusion/ej2-angular-layouts';
onBeforeExpand(args: BeforeExpandEventArgs) {
console.log('Before expanding pane:', args.index);
// Validate before allowing expand
if (this.hasUnsavedChanges()) {
args.cancel = true;
alert('Please save changes first');
}
}expanded
When it fires: After a pane successfully expands (is now visible) Argument: ExpandedEventArgs
ExpandedEventArgs Properties:
element(HTMLElement): Root elementevent(Event): Default event argumentsindex(number[]): Index of expanded panepane(HTMLElement[]): Pane elementsseparator(HTMLElement): Split-bar element
import { ExpandedEventArgs } from '@syncfusion/ej2-angular-layouts';
onExpanded(args: ExpandedEventArgs) {
console.log('Pane expanded:', args.index);
// Trigger animations or load deferred content
this.loadPaneContent(args.index[0]);
}beforeCollapse
When it fires: Just before a pane begins collapsing (can be cancelled) Argument: BeforeExpandEventArgs
BeforeExpandEventArgs Properties:
- `cancel` (boolean): Set to
trueto prevent collapse element(HTMLElement): Root elementevent(Event): Default event argumentsindex(number[]): Index of pane being collapsedpane(HTMLElement[]): Pane elementsseparator(HTMLElement): Split-bar element
import { BeforeExpandEventArgs } from '@syncfusion/ej2-angular-layouts';
onBeforeCollapse(args: BeforeExpandEventArgs) {
console.log('Before collapsing pane:', args.index);
// Prevent collapse under conditions
if (this.isOnlyVisiblePane(args.index[0])) {
args.cancel = true;
alert('Cannot collapse - this is the only visible pane');
}
}collapsed
When it fires: After a pane successfully collapses (is now hidden) Argument: ExpandedEventArgs
ExpandedEventArgs Properties:
element(HTMLElement): Root elementevent(Event): Default event argumentsindex(number[]): Index of collapsed panepane(HTMLElement[]): Pane elementsseparator(HTMLElement): Split-bar element
import { ExpandedEventArgs } from '@syncfusion/ej2-angular-layouts';
onCollapsed(args: ExpandedEventArgs) {
console.log('Pane collapsed:', args.index);
// Cleanup or save state
this.unloadPaneContent(args.index[0]);
this.savePaneState();
}beforeSanitizeHtml
When it fires: Before HTML content in panes is sanitized for security Argument: BeforeSanitizeHtmlArgs
BeforeSanitizeHtmlArgs Properties:
cancel(boolean): Set totrueto prevent default sanitizationhelper(Function): Callback for custom sanitization returning HTML stringselectors(SanitizeSelectors): Object with tag/attribute blocklists
import { BeforeSanitizeHtmlArgs } from '@syncfusion/ej2-angular-layouts';
onBeforeSanitizeHtml(args: BeforeSanitizeHtmlArgs) {
console.log('HTML sanitization in progress');
console.log('Blocked selectors:', args.selectors);
// Custom sanitization if needed
if (args.helper) {
const sanitized = args.helper();
console.log('Sanitized HTML:', sanitized);
}
}See Security Best Practices for detailed sanitization examples.
---
Complete Event Handling Example
import { Component, ViewChild } from '@angular/core';
import { SplitterComponent, ResizingEventArgs, ExpandedEventArgs, BeforeExpandEventArgs, ResizeEventArgs } from '@syncfusion/ej2-angular-layouts';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter-events',
standalone: true,
imports: [SplitterModule],
template: `
<div class="event-monitor">
<h4>Event Monitor</h4>
<div class="event-log">{{ eventLog }}</div>
</div>
<ejs-splitter
#splitter
height="500px"
width="100%"
(created)="onCreated()"
(resizeStart)="onResizeStart($event)"
(resizing)="onResizing($event)"
(resizeStop)="onResizeStop($event)"
(beforeExpand)="onBeforeExpand($event)"
(expanded)="onExpanded($event)"
(beforeCollapse)="onBeforeCollapse($event)"
(collapsed)="onCollapsed($event)"
>
<e-panes>
<e-pane size="250px" [collapsible]="true">
<ng-template #content>
<div class="pane-content">
<h3>Left Panel</h3>
<p>Drag separator to resize</p>
</div>
</ng-template>
</e-pane>
<e-pane [collapsible]="true">
<ng-template #content>
<div class="pane-content">
<h3>Main Content</h3>
<p>Watch events in monitor above</p>
</div>
</ng-template>
</e-pane>
<e-pane size="300px" [collapsible]="true">
<ng-template #content>
<div class="pane-content">
<h3>Right Panel</h3>
<p>All events logged above</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.event-monitor {
margin-bottom: 10px;
padding: 10px;
background-color: #f5f5f5;
border-radius: 4px;
}
.event-log {
height: 80px;
overflow-y: auto;
background-color: white;
border: 1px solid #ddd;
padding: 8px;
font-family: monospace;
font-size: 11px;
line-height: 1.4;
}
.pane-content {
padding: 20px;
}
`]
})
export class SplitterEventsComponent {
@ViewChild('splitter') splitterRef!: SplitterComponent;
eventLog = 'Waiting for events...';
private addLog(message: string) {
const timestamp = new Date().toLocaleTimeString();
this.eventLog = `[${timestamp}] ${message}\n` + this.eventLog;
}
onCreated() {
this.addLog('✓ Splitter created');
}
onResizeStart(args: ResizeEventArgs) {
this.addLog(`▶ Resize started - Pane: ${args.index?.[0]}`);
}
onResizing(args: ResizingEventArgs) {
this.addLog(`◇ Resizing - Sizes: ${args.paneSize?.map(s => Math.round(s)).join(', ')}px`);
}
onResizeStop(args: ResizingEventArgs) {
this.addLog(`✓ Resize stopped - Final: ${args.paneSize?.map(s => Math.round(s)).join(', ')}px`);
}
onBeforeExpand(args: BeforeExpandEventArgs) {
this.addLog(`? Before expand - Pane: ${args.index?.[0]}`);
}
onExpanded(args: ExpandedEventArgs) {
this.addLog(`✓ Expanded - Pane: ${args.index?.[0]}`);
}
onBeforeCollapse(args: BeforeExpandEventArgs) {
this.addLog(`? Before collapse - Pane: ${args.index?.[0]}`);
}
onCollapsed(args: ExpandedEventArgs) {
this.addLog(`✓ Collapsed - Pane: ${args.index?.[0]}`);
}
}---
For comprehensive API reference including all properties, see: API Reference
Expand and Collapse Panes
Enable users to show/hide panes with expand/collapse icons or control pane visibility programmatically.
Collapsible Panes
Enable Collapse Icons
Set [collapsible]='true' on panes to display expand/collapse icons in the separator:
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-collapsible',
standalone: true,
imports: [SplitterModule],
template: `
<ejs-splitter height='250px' width='580px'>
<e-panes>
<e-pane size='200px' [collapsible]='true'>
<ng-template #content>
<div class='template'>
<h3>PARIS</h3>
<p>Paris, the city of lights and love...</p>
</div>
</ng-template>
</e-pane>
<e-pane size='200px' [collapsible]='true'>
<ng-template #content>
<div class='template'>
<h3>CAMEMBERT</h3>
<p>The village where the famous French cheese originated...</p>
</div>
</ng-template>
</e-pane>
<e-pane size='200px' [collapsible]='true'>
<ng-template #content>
<div class='template'>
<h3>GRENOBLE</h3>
<p>Capital city of the French Alps...</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.template {
padding: 15px;
}
`]
})
export class CollapsiblePanesComponent {}User Interaction: Click the expand/collapse icon next to the separator to toggle pane visibility.
Collapse Icons Placement
- Left/Top panes: Icon appears on the right edge (collapses left/up)
- Right/Bottom panes: Icon appears on the left edge (collapses right/down)
Multiple Collapsible Panes
All panes can be independently collapsible:
<ejs-splitter height='300px' width='100%'>
<e-panes>
<e-pane size='200px' [collapsible]='true'>
<ng-template #content>Left Panel (Collapsible)</ng-template>
</e-pane>
<e-pane [collapsible]='true'>
<ng-template #content>Middle Panel (Collapsible)</ng-template>
</e-pane>
<e-pane size='200px' [collapsible]='true'>
<ng-template #content>Right Panel (Collapsible)</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>Partial Collapsible Setup
Only specific panes can be collapsible:
<e-panes>
<e-pane size='200px' [collapsible]='true'>
<ng-template #content>Collapsible</ng-template>
</e-pane>
<e-pane size='200px' [collapsible]='false'>
<ng-template #content>Fixed (Not Collapsible)</ng-template>
</e-pane>
</e-panes>---
Collapsed State
Start with Collapsed Pane
Set collapsed property to start with a hidden pane:
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-collapsed-state',
standalone: true,
imports: [SplitterModule],
template: `
<ejs-splitter height='250px' width='600px'>
<e-panes>
<e-pane size='200px' [collapsible]='true' [collapsed]='true'>
<ng-template #content>
<div>Hidden Panel (Start Collapsed)</div>
</ng-template>
</e-pane>
<e-pane size='200px'>
<ng-template #content>
<div>Visible Panel</div>
</ng-template>
</e-pane>
<e-pane size='200px'>
<ng-template #content>
<div>Visible Panel</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`
})
export class CollapsedStateComponent {}Result: Splitter loads with the first pane hidden (taking no space). Click expand icon to reveal it.
---
Programmatic Expand/Collapse
Expand Pane
Use the expand() method to show a collapsed pane:
import { Component, ViewChild } from '@angular/core';
import { SplitterModule, SplitterComponent } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-expand-control',
standalone: true,
imports: [SplitterModule],
template: `
<div>
<button class='e-btn' (click)='expandPane()'>Expand Panel 1</button>
</div>
<ejs-splitter #splitter height='250px' width='600px'>
<e-panes>
<e-pane size='200px' [collapsible]='true' [collapsed]='true'>
<ng-template #content>
<div>Panel 1</div>
</ng-template>
</e-pane>
<e-pane size='200px'>
<ng-template #content>
<div>Panel 2</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`
})
export class ExpandControlComponent {
@ViewChild('splitter') splitterObj?: SplitterComponent;
expandPane(): void {
// Expand pane at index 0
this.splitterObj!.expand(0);
}
}Parameters:
index: Pane index to expand (0 = first pane, 1 = second pane, etc.)
Collapse Pane
Use the collapse() method to hide a visible pane:
import { Component, ViewChild } from '@angular/core';
import { SplitterModule, SplitterComponent } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-collapse-control',
standalone: true,
imports: [SplitterModule],
template: `
<div>
<button class='e-btn' (click)='collapsePane()'>Collapse Panel 1</button>
</div>
<ejs-splitter #splitter height='250px' width='600px'>
<e-panes>
<e-pane size='200px' [collapsible]='true'>
<ng-template #content>
<div>Panel 1</div>
</ng-template>
</e-pane>
<e-pane size='200px'>
<ng-template #content>
<div>Panel 2</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`
})
export class CollapseControlComponent {
@ViewChild('splitter') splitterObj?: SplitterComponent;
collapsePane(): void {
// Collapse pane at index 0
this.splitterObj!.collapse(0);
}
}Expand Multiple Panes
expandAllPanes(): void {
this.splitterObj!.expand(0);
this.splitterObj!.expand(1);
this.splitterObj!.expand(2);
}Collapse Multiple Panes
collapseAllPanes(): void {
this.splitterObj!.collapse(0);
this.splitterObj!.collapse(1);
}---
Real-World Examples
Dashboard with Collapsible Filters
import { Component, ViewChild } from '@angular/core';
import { SplitterModule, SplitterComponent } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-dashboard',
standalone: true,
imports: [SplitterModule],
template: `
<div>
<button class='e-btn' (click)='toggleFilters()'>Toggle Filters</button>
</div>
<ejs-splitter height='400px' width='100%'>
<e-panes>
<!-- Filters panel -->
<e-pane size='250px' [collapsible]='true'>
<ng-template #content>
<div class='filters'>
<h3>Filters</h3>
<p>Filter controls here</p>
</div>
</ng-template>
</e-pane>
<!-- Main dashboard -->
<e-pane>
<ng-template #content>
<div class='dashboard'>
<h3>Dashboard</h3>
<p>Charts and data here</p>
</div>
</ng-template>
</e-pane>
<!-- Details panel -->
<e-pane size='300px' [collapsible]='true'>
<ng-template #content>
<div class='details'>
<h3>Details</h3>
<p>Selected item details</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.filters, .dashboard, .details {
padding: 15px;
}
`]
})
export class DashboardComponent {
@ViewChild('splitter') splitterObj?: SplitterComponent;
private isFilterCollapsed = false;
toggleFilters(): void {
if (this.isFilterCollapsed) {
this.splitterObj!.expand(0);
this.isFilterCollapsed = false;
} else {
this.splitterObj!.collapse(0);
this.isFilterCollapsed = true;
}
}
}Mobile-Responsive Navigation
import { Component, ViewChild, OnInit } from '@angular/core';
import { SplitterModule, SplitterComponent } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-mobile-nav',
standalone: true,
imports: [SplitterModule],
template: `
<ejs-splitter #splitter height='100vh' width='100%'>
<e-panes>
<e-pane size='250px' [collapsible]='true' [collapsed]='isMobile'>
<ng-template #content>
<div>Navigation Menu</div>
</ng-template>
</e-pane>
<e-pane>
<ng-template #content>
<div>Main Content</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`
})
export class MobileNavComponent implements OnInit {
@ViewChild('splitter') splitterObj?: SplitterComponent;
isMobile = false;
ngOnInit(): void {
this.isMobile = window.innerWidth < 768;
window.addEventListener('resize', this.onResize.bind(this));
}
onResize(): void {
this.isMobile = window.innerWidth < 768;
if (this.isMobile) {
this.splitterObj!.collapse(0);
} else {
this.splitterObj!.expand(0);
}
}
}---
Key Points
✓ Only collapsible='true' panes can be collapsed ✓ Collapsed panes take no space in the layout ✓ Icons indicate which direction pane will collapse ✓ Users can collapse/expand manually or via buttons ✓ Programmatic methods give you full control over pane visibility
Getting Started with Angular Splitter
Learn how to install, import, and create your first Splitter component.
Installation
Install the Layouts Package
The Splitter component is part of the @syncfusion/ej2-angular-layouts package. Install it using npm:
npm install @syncfusion/ej2-angular-layouts --saveAngular Version Compatibility
Syncfusion Angular packages support:
- Ivy (Angular 12+): Default distribution for modern Angular
- ngcc (Angular < 12): Legacy compatibility package
For Angular < 12, install the ngcc version:
npm install @syncfusion/ej2-angular-layouts@ngcc --saveModule Import
Standalone Component (Recommended - Angular 14+)
Import SplitterModule directly in your component:
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-splitter',
standalone: true,
imports: [SplitterModule],
template: `
<ejs-splitter height="250px" width="600px">
<e-panes>
<e-pane></e-pane>
<e-pane></e-pane>
</e-panes>
</ejs-splitter>
`
})
export class AppComponent {}NgModule Import (Traditional)
For NgModule-based applications, import SplitterModule in your app module:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-root',
template: `
<ejs-splitter height="250px" width="600px">
<e-panes>
<e-pane></e-pane>
<e-pane></e-pane>
</e-panes>
</ejs-splitter>
`
})
export class AppComponent {}
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, SplitterModule],
bootstrap: [AppComponent]
})
export class AppModule {}CSS Theme Setup
Add Theme Imports
Include Syncfusion CSS files in src/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-layouts/styles/material3.css';Available Themes
Replace material3 with any of these options:
bootstrap5- Bootstrap 5 themebootstrap- Bootstrap 4 themefabric- Microsoft Fabric themetailwind- Tailwind CSS themematerial- Material Designhighcontrast- High contrast accessibility theme
Basic Component Setup
Minimal Splitter Example
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-basic-splitter',
standalone: true,
imports: [SplitterModule],
template: `
<div id='container'>
<ejs-splitter height='250px' width='600px'>
<e-panes>
<e-pane size='200px'>
<ng-template #content>
<div class='content'>Left Pane</div>
</ng-template>
</e-pane>
<e-pane size='200px'>
<ng-template #content>
<div class='content'>Right Pane</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
</div>
`,
styles: [`
.content {
padding: 20px;
text-align: center;
}
`]
})
export class BasicSplitterComponent {}Component Structure
XML-like Syntax
Splitter uses Syncfusion's element syntax:
<ejs-splitter> <!-- Root component -->
<e-panes> <!-- Panes container -->
<e-pane> <!-- Individual pane -->
<ng-template #content> <!-- Pane content -->
Content goes here
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>Key Elements
- `<ejs-splitter>`: Main component container
height: Splitter container heightwidth: Splitter container widthorientation: "Horizontal" (default) or "Vertical"
- `<e-panes>`: Container for all panes (required)
- `<e-pane>`: Individual resizable pane
size: Pane size (pixels like "200px" or percentage like "30%")collapsible: Enable collapse/expand icons (boolean)content: String content (alternative to ng-template)
Running the Application
Development Server
ng serveNavigate to http://localhost:4200 in your browser.
Production Build
ng buildComplete First Example
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
import { bootstrapApplication } from '@angular/platform-browser';
@Component({
selector: 'app-root',
standalone: true,
imports: [SplitterModule],
template: `
<div style='margin: 20px'>
<h2>My First Splitter</h2>
<ejs-splitter height='300px' width='100%'>
<e-panes>
<e-pane size='200px'>
<ng-template #content>
<div style='padding: 15px'>
<h3>Sidebar</h3>
<p>Navigation menu goes here</p>
</div>
</ng-template>
</e-pane>
<e-pane>
<ng-template #content>
<div style='padding: 15px'>
<h3>Main Content</h3>
<p>Your content area</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
</div>
`
})
export class AppComponent {}
bootstrapApplication(AppComponent).catch(err => console.error(err));Verification Checklist
Before proceeding to advanced features, verify:
- ✓ Package installed successfully
- ✓ SplitterModule imported in component
- ✓ CSS theme file imported
- ✓ Splitter renders in browser
- ✓ Panes are visible and draggable
- ✓ No console errors
Next Steps
- Layouts: Create horizontal and vertical splits with split-panes.md
- Sizing: Configure pane sizes with pane-sizing.md
- Interactivity: Add collapsible panes with expand-collapse.md
Globalization and Localization
Enable Splitter to support international audiences with right-to-left (RTL) layout, localized text, and multi-language support.
Right-to-Left (RTL) Support
Enable RTL with enableRtl Property
Use the enableRtl property to support right-to-left languages like Arabic, Hebrew, and Persian:
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-rtl-splitter',
standalone: true,
imports: [SplitterModule],
template: `
<ejs-splitter
height='200px'
width='600px'
[enableRtl]='true'>
<e-panes>
<e-pane size='200px' content='<div class="content">Left pane</div>'>
</e-pane>
<e-pane size='200px' content='<div class="content">Middle pane</div>'>
</e-pane>
<e-pane size='200px' content='<div class="content">Right pane</div>'>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.content {
padding: 15px;
text-align: center;
}
`]
})
export class RTLSplitterComponent {}Result: Splitter layout mirrors for RTL languages. Panes arrange right-to-left, separators respond accordingly.
RTL with Arabic Content
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-arabic-splitter',
standalone: true,
imports: [SplitterModule],
template: `
<ejs-splitter
height='300px'
width='100%'
[enableRtl]='true'>
<e-panes>
<!-- Right sidebar (visually on right due to RTL) -->
<e-pane size='250px'>
<ng-template #content>
<div class='sidebar' dir='rtl'>
<h3>القائمة</h3>
<ul>
<li>الرئيسية</li>
<li>حول</li>
<li>خدمات</li>
<li>اتصل بنا</li>
</ul>
</div>
</ng-template>
</e-pane>
<!-- Main content area -->
<e-pane>
<ng-template #content>
<div class='content' dir='rtl'>
<h1>مرحبا بك</h1>
<p>هذا محتوى بسيط لتطبيق متعدد اللغات</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.sidebar, .content {
padding: 20px;
text-align: right;
direction: rtl;
}
.sidebar {
background-color: #f5f5f5;
border-right: 1px solid #ddd;
}
.sidebar h3 {
margin-top: 0;
}
.sidebar ul {
list-style: none;
padding: 0;
}
.sidebar li {
padding: 10px 0;
border-bottom: 1px solid #eee;
}
`]
})
export class ArabicSplitterComponent {}RTL with HTML Attribute
Set RTL at the document level:
<!-- In index.html -->
<html dir="rtl" lang="ar">
<head>
<meta charset="utf-8">
<title>تطبيق RTL</title>
</head>
<body>
<app-root></app-root>
</body>
</html>// In app.component.ts
@Component({
selector: 'app-root',
template: '<router-outlet></router-outlet>'
})
export class AppComponent implements OnInit {
ngOnInit() {
// Apply RTL globally
document.body.setAttribute('dir', 'rtl');
}
}RTL from User Settings
import { Component, ViewChild } from '@angular/core';
import { SplitterModule, SplitterComponent } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-dynamic-rtl',
standalone: true,
imports: [SplitterModule],
template: `
<div style='margin-bottom: 20px'>
<label>
<input
type='checkbox'
[checked]='isRTL'
(change)='toggleRTL()' />
Enable RTL
</label>
<p>Current: {{ isRTL ? 'RTL' : 'LTR' }}</p>
</div>
<ejs-splitter
#splitter
height='300px'
width='100%'
[enableRtl]='isRTL'>
<e-panes>
<e-pane size='250px'>
<ng-template #content>
<div [dir]='isRTL ? "rtl" : "ltr"'>
Left/Right Sidebar
</div>
</ng-template>
</e-pane>
<e-pane>
<ng-template #content>
<div [dir]='isRTL ? "rtl" : "ltr"'>
Main Content
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
label {
display: block;
margin-bottom: 10px;
cursor: pointer;
}
input {
margin-right: 10px;
}
`]
})
export class DynamicRTLComponent {
@ViewChild('splitter') splitterObj?: SplitterComponent;
isRTL = false;
toggleRTL(): void {
this.isRTL = !this.isRTL;
}
}---
Locale and Culture Support
Set Global Locale
import { Component, OnInit } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
import { setCulture } from '@syncfusion/ej2-base';
@Component({
selector: 'app-locale-splitter',
standalone: true,
imports: [SplitterModule],
template: `
<div style='margin-bottom: 20px'>
<button (click)='setCultureEn()'>English</button>
<button (click)='setCultureEs()'>Español</button>
<button (click)='setCultureAr()'>العربية</button>
<button (click)='setCultureJa()'>日本語</button>
<p>Current Locale: {{ currentLocale }}</p>
</div>
<ejs-splitter
height='300px'
width='100%'
[enableRtl]='isRTL'>
<e-panes>
<e-pane size='250px'>
<ng-template #content>
<div>{{ localeName }}</div>
</ng-template>
</e-pane>
<e-pane>
<ng-template #content>
<div>{{ localeContent }}</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
button {
padding: 8px 15px;
margin-right: 10px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #0056b3;
}
p {
margin-top: 10px;
font-weight: bold;
}
`]
})
export class LocaleSplitterComponent implements OnInit {
currentLocale = 'en';
isRTL = false;
localeName = 'Language';
localeContent = 'Select a language to change locale';
ngOnInit(): void {
this.setCultureEn();
}
setCultureEn(): void {
setCulture('en');
this.currentLocale = 'en';
this.isRTL = false;
this.localeName = 'Language';
this.localeContent = 'English locale is set';
}
setCultureEs(): void {
setCulture('es');
this.currentLocale = 'es';
this.isRTL = false;
this.localeName = 'Idioma';
this.localeContent = 'La configuración regional de español está establecida';
}
setCultureAr(): void {
setCulture('ar');
this.currentLocale = 'ar';
this.isRTL = true;
this.localeName = 'اللغة';
this.localeContent = 'تم تعيين الإعدادات الإقليمية باللغة العربية';
}
setCultureJa(): void {
setCulture('ja');
this.currentLocale = 'ja';
this.isRTL = false;
this.localeName = '言語';
this.localeContent = '日本語のロケール設定が有効になっています';
}
}Supported Locales
Syncfusion supports numerous locales:
| Locale Code | Language | RTL |
|---|---|---|
| en | English | ✗ |
| es | Spanish | ✗ |
| fr | French | ✗ |
| de | German | ✗ |
| pt | Portuguese | ✗ |
| ja | Japanese | ✗ |
| zh | Chinese (Simplified) | ✗ |
| ko | Korean | ✗ |
| ar | Arabic | ✓ |
| he | Hebrew | ✓ |
| fa | Persian/Farsi | ✓ |
| ur | Urdu | ✓ |
| hi | Hindi | ✗ |
| th | Thai | ✗ |
| tr | Turkish | ✗ |
---
Text Direction Attributes
HTML dir Attribute
Apply text direction to pane content:
<ejs-splitter height='300px' width='100%'>
<e-panes>
<e-pane size='250px'>
<ng-template #content>
<!-- LTR content -->
<div dir='ltr'>
<h3>English Text</h3>
<p>This content flows left to right</p>
</div>
</ng-template>
</e-pane>
<e-pane>
<ng-template #content>
<!-- RTL content -->
<div dir='rtl'>
<h3>نص عربي</h3>
<p>هذا المحتوى يتدفق من اليمين إلى اليسار</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>Mixed Direction Content
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-mixed-direction',
standalone: true,
imports: [SplitterModule, CommonModule],
template: `
<ejs-splitter height='300px' width='100%'>
<e-panes>
<e-pane size='250px'>
<ng-template #content>
<div class='panel' dir='ltr'>
<h3>English Content</h3>
<p>Left to right text</p>
<p>Numbers: 1234567890</p>
</div>
</ng-template>
</e-pane>
<e-pane>
<ng-template #content>
<div class='panel' dir='rtl'>
<h3>محتوى عربي</h3>
<p>نص من اليمين إلى اليسار</p>
<p>الأرقام: ١٢٣٤٥٦٧٨٩٠</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.panel {
padding: 20px;
text-align: left;
}
[dir='rtl'] {
text-align: right;
}
`]
})
export class MixedDirectionComponent {}---
Number and Date Formatting
Locale-Aware Formatting
Different locales format numbers and dates differently:
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-locale-formatting',
standalone: true,
imports: [SplitterModule, CommonModule],
template: `
<ejs-splitter height='300px' width='100%'>
<e-panes>
<e-pane size='250px'>
<ng-template #content>
<div class='panel'>
<h3>Number Formatting</h3>
<p>English: {{ englishNumber | number:'1.2-2' }}</p>
<p>German: {{ germanNumber }}</p>
<p>French: {{ frenchNumber }}</p>
</div>
</ng-template>
</e-pane>
<e-pane>
<ng-template #content>
<div class='panel'>
<h3>Date Formatting</h3>
<p>English: {{ currentDate | date:'short' }}</p>
<p>German: {{ currentDate | date:'dd.MM.yyyy' }}</p>
<p>Arabic: {{ currentDate | date:'short' }}</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.panel {
padding: 20px;
}
p {
margin: 10px 0;
font-size: 14px;
}
`]
})
export class LocaleFormattingComponent {
englishNumber = 1234.56;
germanNumber = '1.234,56'; // German uses comma for decimals
frenchNumber = '1 234,56'; // French uses space for thousands
currentDate = new Date();
}---
Best Practices for Globalization
✓ Always set enableRtl when supporting RTL languages ✓ Use dir attribute on content containers for proper text direction ✓ Test with real locales - not all RTL is the same ✓ Consider number formats - some locales use different separators ✓ Test date formats - DD/MM/YYYY vs MM/DD/YYYY ✓ Use CSS that respects direction - avoid left/right margins in favor of logical properties ✓ Handle mixed content - apps often mix LTR and RTL ✓ Test on devices - RTL behavior can vary across browsers
---
Common Pitfalls
❌ Only setting enableRtl - also set dir='rtl' on HTML elements ✓ Combine enableRtl with dir attributes for complete RTL support
❌ Forgetting to import setCulture - won't change locale ✓ Import and call setCulture() for locale changes
❌ Hard-coding text in components - not translatable ✓ Use translation libraries (ngx-translate, i18n) for user-facing text
❌ Assuming all RTL is the same - each language has nuances ✓ Test with native speakers for each language
Layout Patterns and Recipes
Table of Contents
---
Two-Pane Sidebar Layout
Classic sidebar + content pattern, ideal for navigation and dashboards.
Basic Sidebar Layout
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-sidebar-layout',
standalone: true,
imports: [SplitterModule],
template: `
<ejs-splitter height='100vh' width='100%'>
<e-panes>
<!-- Sidebar Navigation -->
<e-pane size='250px'>
<ng-template #content>
<div class='sidebar'>
<h2>Navigation</h2>
<ul class='nav-menu'>
<li>Dashboard</li>
<li>Analytics</li>
<li>Reports</li>
<li>Settings</li>
</ul>
</div>
</ng-template>
</e-pane>
<!-- Main Content Area -->
<e-pane>
<ng-template #content>
<div class='content'>
<h1>Dashboard</h1>
<p>Main content area with dynamic content</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.sidebar {
background-color: #f5f5f5;
padding: 20px;
height: 100%;
overflow: auto;
border-right: 1px solid #ddd;
}
.nav-menu {
list-style: none;
padding: 0;
}
.nav-menu li {
padding: 10px 15px;
cursor: pointer;
border-radius: 4px;
}
.nav-menu li:hover {
background-color: #e0e0e0;
}
.content {
padding: 30px;
}
`]
})
export class SidebarLayoutComponent {}Collapsible Sidebar
<ejs-splitter height='100vh' width='100%'>
<e-panes>
<!-- Collapsible sidebar -->
<e-pane size='250px' [collapsible]='true'>
<ng-template #content>
<div class='sidebar'>
<h2>Menu</h2>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
</ng-template>
</e-pane>
<!-- Content -->
<e-pane>
<ng-template #content>
<div class='content'>Main Area</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>Resizable Sidebar with Constraints
<e-panes>
<!-- Sidebar: min 150px, max 400px, default 250px -->
<e-pane size='250px' min='150px' max='400px'>
<ng-template #content>
<div class='sidebar'>Navigation</div>
</ng-template>
</e-pane>
<!-- Content: flexible -->
<e-pane>
<ng-template #content>
<div class='content'>Main Content</div>
</ng-template>
</e-pane>
</e-panes>---
Three-Pane Editor Layout
IDE/Editor-style layout with left explorer, center editor, and right inspector.
Complete Editor Layout
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-editor-layout',
standalone: true,
imports: [SplitterModule],
template: `
<ejs-splitter height='100vh' width='100%'>
<e-panes>
<!-- Left: File Explorer (200px) -->
<e-pane size='200px' min='150px' max='350px'>
<ng-template #content>
<div class='explorer'>
<h3>Explorer</h3>
<ul class='file-tree'>
<li>📁 src/
<ul>
<li>📄 app.component.ts</li>
<li>📄 app.component.html</li>
</ul>
</li>
<li>📁 node_modules/</li>
<li>📄 package.json</li>
</ul>
</div>
</ng-template>
</e-pane>
<!-- Center: Code Editor (flexible) -->
<e-pane>
<ng-template #content>
<div class='editor'>
<div class='editor-tabs'>
<span class='tab active'>app.component.ts</span>
<span class='tab'>app.component.html</span>
</div>
<div class='editor-content'>
<pre><code>export class AppComponent {{
title = 'My App';
}}</code></pre>
</div>
</div>
</ng-template>
</e-pane>
<!-- Right: Properties/Inspector (250px) -->
<e-pane size='250px' min='150px' max='350px'>
<ng-template #content>
<div class='inspector'>
<h3>Properties</h3>
<div class='property-group'>
<label>Title:</label>
<input type='text' value='My App' />
</div>
<div class='property-group'>
<label>Version:</label>
<input type='text' value='1.0.0' />
</div>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.explorer, .editor, .inspector {
height: 100%;
overflow: auto;
border-right: 1px solid #ddd;
}
.explorer {
background-color: #f5f5f5;
padding: 15px;
}
.file-tree {
list-style: none;
padding: 0;
font-family: monospace;
}
.file-tree li {
padding: 5px 0;
}
.editor-tabs {
display: flex;
border-bottom: 1px solid #ddd;
padding: 10px;
}
.tab {
padding: 8px 15px;
cursor: pointer;
border-bottom: 2px solid transparent;
}
.tab.active {
border-bottom-color: #007bff;
color: #007bff;
}
.editor-content {
padding: 20px;
font-family: 'Courier New', monospace;
background-color: #f8f8f8;
}
.inspector {
background-color: #fafafa;
padding: 15px;
}
.property-group {
margin-bottom: 15px;
}
.property-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.property-group input {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
`]
})
export class EditorLayoutComponent {}---
Nested Complex Layouts
IDE with Nested Vertical Split
Bottom panel contains logs and debug info:
import { Component } from '@angular/core';
import { SplitterModule } from '@syncfusion/ej2-angular-layouts';
@Component({
selector: 'app-nested-ide',
standalone: true,
imports: [SplitterModule],
template: `
<!-- Main horizontal split: sidebar | editor area -->
<ejs-splitter height='100vh' width='100%'>
<e-panes>
<!-- Left: Sidebar -->
<e-pane size='200px'>
<ng-template #content>
<div class='sidebar'>
<h3>Project</h3>
<p>File tree here</p>
</div>
</ng-template>
</e-pane>
<!-- Right: Editor area with nested vertical split -->
<e-pane>
<ng-template #content>
<!-- Nested vertical split: editor | output -->
<ejs-splitter orientation='Vertical' height='100%'>
<e-panes>
<!-- Top: Code editor -->
<e-pane size='70%'>
<ng-template #content>
<div class='editor'>
<h3>Editor</h3>
<pre><code>// Code here</code></pre>
</div>
</ng-template>
</e-pane>
<!-- Bottom: Output/Logs (resizable) -->
<e-pane size='30%' min='100px'>
<ng-template #content>
<div class='output'>
<h3>Output</h3>
<p>Build logs and output...</p>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.sidebar, .editor, .output {
padding: 15px;
height: 100%;
overflow: auto;
}
.sidebar {
background-color: #f5f5f5;
border-right: 1px solid #ddd;
}
.editor {
background-color: #fafafa;
border-bottom: 1px solid #ddd;
}
.output {
background-color: #1e1e1e;
color: #d4d4d4;
font-family: monospace;
}
`]
})
export class NestedIDEComponent {}---
Responsive Dashboard
Dashboard with Collapsible Panels
import { Component, ViewChild, OnInit } from '@angular/core';
import { SplitterModule, SplitterComponent } from '@syncfusion/ej2-angular-layouts';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-dashboard',
standalone: true,
imports: [SplitterModule, CommonModule],
template: `
<div class='toolbar'>
<h1>Analytics Dashboard</h1>
<div class='actions'>
<button class='e-btn' (click)='toggleFilters()'>
{{ showFilters ? 'Hide' : 'Show' }} Filters
</button>
<button class='e-btn' (click)='toggleDetails()'>
{{ showDetails ? 'Hide' : 'Show' }} Details
</button>
</div>
</div>
<ejs-splitter #dashboard height='calc(100vh - 80px)' width='100%'>
<e-panes>
<!-- Left: Filters Panel (collapsible) -->
<e-pane
size='250px'
[collapsible]='true'
[collapsed]='!showFilters'>
<ng-template #content>
<div class='filters-panel'>
<h3>Filters</h3>
<div class='filter-item'>
<label>Date Range:</label>
<input type='date' />
</div>
<div class='filter-item'>
<label>Category:</label>
<select>
<option>All</option>
<option>Category A</option>
<option>Category B</option>
</select>
</div>
<button class='e-btn'>Apply</button>
</div>
</ng-template>
</e-pane>
<!-- Center: Dashboard Content (flexible) -->
<e-pane>
<ng-template #content>
<div class='dashboard-content'>
<div class='metric-card'>
<h4>Total Revenue</h4>
<p class='metric-value'>$125,430</p>
</div>
<div class='metric-card'>
<h4>Users</h4>
<p class='metric-value'>12,547</p>
</div>
<div class='metric-card'>
<h4>Conversion</h4>
<p class='metric-value'>3.42%</p>
</div>
</div>
</ng-template>
</e-pane>
<!-- Right: Details Panel (collapsible) -->
<e-pane
size='300px'
[collapsible]='true'
[collapsed]='!showDetails'>
<ng-template #content>
<div class='details-panel'>
<h3>Recent Activity</h3>
<ul class='activity-list'>
<li>Order #1234 - Completed</li>
<li>User registration - 23 new users</li>
<li>System update - 2.1 deployed</li>
</ul>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
`,
styles: [`
.toolbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
background-color: #f5f5f5;
border-bottom: 1px solid #ddd;
}
.actions {
display: flex;
gap: 10px;
}
.filters-panel, .details-panel {
padding: 20px;
height: 100%;
overflow: auto;
}
.filters-panel {
background-color: #fafafa;
border-right: 1px solid #ddd;
}
.filter-item {
margin-bottom: 15px;
}
.filter-item label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.filter-item input,
.filter-item select {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
.dashboard-content {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
padding: 20px;
}
.metric-card {
background: white;
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
text-align: center;
}
.metric-value {
font-size: 28px;
font-weight: bold;
color: #007bff;
margin: 10px 0 0 0;
}
.details-panel {
background-color: #fafafa;
border-left: 1px solid #ddd;
}
.activity-list {
list-style: none;
padding: 0;
}
.activity-list li {
padding: 10px;
border-bottom: 1px solid #eee;
font-size: 14px;
}
`]
})
export class ResponsiveDashboardComponent implements OnInit {
@ViewChild('dashboard') splitterObj?: SplitterComponent;
showFilters = true;
showDetails = true;
ngOnInit(): void {
// Collapse panels on mobile
if (window.innerWidth < 1200) {
this.showFilters = false;
this.showDetails = false;
}
}
toggleFilters(): void {
this.showFilters = !this.showFilters;
if (this.showFilters) {
this.splitterObj!.expand(0);
} else {
this.splitterObj!.collapse(0);
}
}
toggleDetails(): void {
this.showDetails = !this.showDetails;
if (this.showDetails) {
this.splitterObj!.expand(2);
} else {
this.splitterObj!.collapse(2);
}
}
}---
Pattern Selection Guide
| Pattern | Use Case | Complexity |
|---|---|---|
| Two-Pane Sidebar | Navigation + content | Simple |
| Three-Pane Editor | IDE-like interfaces | Medium |
| Nested Complex | Advanced dashboards | Advanced |
| Responsive Dashboard | Mobile-friendly UI | Medium |
Choose based on your application needs and user interaction requirements.