
Syncfusion Angular Sidebar
- 160 installs
- Updated August 4, 2026
- syncfusion/angular-ui-components-skills
Helps with ai & agent building tasks.
About
syncfusion-angular-sidebar is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- syncfusion-angular-sidebar
- AI & Agent Building
- AI-coding skill
Syncfusion Angular Sidebar by the numbers
- 160 all-time installs (skills.sh)
- +11 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #3,254 of 16,546 AI & Agent Building 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-sidebarAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 160 |
|---|---|
| Last updated | August 4, 2026 |
| Repository | syncfusion/angular-ui-components-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
Implementing Syncfusion Angular Sidebar Component
The Sidebar is an expandable and collapsible navigation component that acts as a side container for primary or secondary content alongside main content. It supports flexible show/hide behavior, multiple positioning modes (left, right, top, bottom), various expand types (Push, Slide, Over, Auto), docking for compact states, touch gestures, animations, responsive behavior, and rich content including TreeView and ListView.
When to Use This Skill
- Implementing collapsible navigation menus or sidebars
- Creating responsive navigation that adapts to screen size
- Building expandable panels with icon-only docked states
- Adding gesture-based sidebar toggle on touch devices
- Positioning sidebars in various directions (left, right, top, bottom)
- Implementing backdrop overlays to focus on sidebar content
- Creating multi-level navigation with TreeView or ListView
- Managing sidebar visibility with auto-close behavior
- Building toggle buttons with show(), hide(), toggle() methods
- Applying animations and RTL support to sidebars
Documentation and Navigation Guide
Getting Started
📄 Read: references/getting-started.md
- Angular CLI setup and project initialization (Recommended)
- Installing Syncfusion packages (Ivy and ngcc versions)
- Importing modules and CSS styles
- Creating basic sidebar component
- ViewChild setup and initialization
SystemJS Setup (Alternative)
📄 Read: references/systemjs-setup.md
- SystemJS configuration and installation
- systemjs.config.js setup with Syncfusion mappings
- UMD bundle configuration
- Creating Sidebar with SystemJS
- Development server and running the application
- SystemJS vs Angular CLI comparison
Sidebar Positioning and Behavior
📄 Read: references/sidebar-positioning.md
- Sidebar types: Push, Slide, Over, Auto
- Positioning: Left, Right, Top, Bottom
- Fixed positioning for static sidebars
- Docking with enableDock and dockSize properties
- Multiple sidebars on same page
- dataBind() for dynamic property updates
Sidebar Interactions and Control
📄 Read: references/sidebar-interactions.md
- Control methods: show(), hide(), toggle()
- Auto-close with mediaQuery for responsive behavior
- closeOnDocumentClick for external click handling
- Backdrop overlay with showBackdrop
- Touch gesture support with enableGestures
- Open and close event handling
Sidebar Content and Components
📄 Read: references/sidebar-content.md
- ListView integration for list-based content
- TreeView integration for hierarchical menus
- Custom HTML content and menu items
- Target element configuration
- Content structure and layout patterns
Animations and Styling
📄 Read: references/animations-and-styles.md
- Animation control with animate property
- Animation types and variations
- CSS theming with Material3 and other themes
- RTL (right-to-left) support with enableRtl
- Responsive design patterns
- CRG (Custom Resource Generator) usage
Advanced Features and Patterns
📄 Read: references/advanced-features.md
- Persistence with enablePersistence
- RTL implementation details
- Accessibility features
- Hiding sidebars with routing
- Performance optimization
- Edge cases and troubleshooting
Quick Start Example
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar #sidebar id="default-sidebar">
<div class="title">Sidebar Content</div>
</ejs-sidebar>
<div>
<div class="title">Main Content</div>
<button (click)="toggleSidebar()">Toggle Sidebar</button>
</div>`,
styles: [`
.title { padding: 20px; font-weight: bold; }
`]
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
toggleSidebar() {
this.sidebar?.toggle();
}
}Target Property Behavior
The sidebar's target property controls which element is affected when the sidebar expands/collapses. There are two distinct modes:
Implicit Targeting (Recommended - Default Behavior)
No `target` property is specified. The sidebar automatically targets the next sibling `<div>` element:
<ejs-sidebar id="sidebar" type="Push"></ejs-sidebar>
<div> <!-- Automatically becomes target - no wrapper needed -->
<div class="content">Main Content</div>
</div>✅ Advantages:
- Simple and clean code
- No wrapper element needed
- Perfect for straightforward layouts
- Use this for most applications
---
Explicit Targeting (Advanced - When You Need Control)
Use the `[target]="'#selector'"` property to explicitly specify which element to affect:
<ejs-sidebar [target]="'#content-area'" type="Push"></ejs-sidebar>
<div id="content-area"> <!-- Explicit target -->
<div> <!-- ⚠️ REQUIRED: Inner wrapper -->
<div class="content">Main Content</div>
</div>
</div>⚠️ IMPORTANT: When using explicit target, you MUST include an inner wrapper `<div>` inside the target container for CSS transforms to work correctly.
Use explicit targeting when:
- You want to exclude certain elements (header, footer) from sidebar effects
- You have complex layouts with multiple sections
- You need fine-grained control over transformation
---
When to Use Each Mode
| Mode | When to Use | Complexity | Wrapper Needed |
|---|---|---|---|
| Implicit (No target) | Default for most layouts | Simple | ❌ No |
| Explicit (With target) | Complex layouts, selective targeting | Advanced | ✅ Yes (inner) |
See detailed examples in [references/sidebar-positioning.md](references/sidebar-positioning.md#target-property---when-and-how-to-use)
---
API Properties Reference
The Sidebar component exposes the following properties to control its behavior and appearance:
animate
Type: boolean | Default: true
Enable or disable animation transitions when expanding or collapsing the sidebar.
// Example: Disable animations for instant toggle
<ejs-sidebar [animate]="false"></ejs-sidebar>
// Example: Enable animations (default)
<ejs-sidebar [animate]="true"></ejs-sidebar>---
closeOnDocumentClick
Type: boolean | Default: false
Specifies whether the sidebar closes when clicking outside of it on the main content area.
// Example: Auto-close sidebar on document click
<ejs-sidebar [closeOnDocumentClick]="true"></ejs-sidebar>
// Example: In component
this.closeOnClick = true;---
dockSize
Type: string | number | Default: 'auto'
Specifies the width of the sidebar when in dock state (collapsed but still visible with icons).
// Example: Set dock size to 72 pixels
<ejs-sidebar [dockSize]="'72px'" [enableDock]="true"></ejs-sidebar>
// Example: Set as number
<ejs-sidebar [dockSize]="72" [enableDock]="true"></ejs-sidebar>
// Example: In component
public dockSize: string = '72px';---
enableDock
Type: boolean | Default: false
Enables the docking state where sidebar shows icons only and expands on hover or click.
// Example: Enable docking for icon-only sidebar
<ejs-sidebar [enableDock]="true" [dockSize]="'72px'">
<div class="sidebar-item" title="Home">
<i class="e-icons e-home"></i>
</div>
<div class="sidebar-item" title="Settings">
<i class="e-icons e-settings"></i>
</div>
</ejs-sidebar>
// Example: In component
public enableDock = true;
public dockSize = '72px';---
enableGestures
Type: boolean | Default: true
Enables touch gestures (swipe) to open/close the sidebar on touch devices.
// Example: Enable gesture support (default)
<ejs-sidebar [enableGestures]="true"></ejs-sidebar>
// Example: Disable gestures for specific use cases
<ejs-sidebar [enableGestures]="false"></ejs-sidebar>---
enablePersistence
Type: boolean | Default: false
Enable persisting the sidebar state (open/closed, position, type) between page reloads using localStorage.
// Example: Enable persistence to remember sidebar state
<ejs-sidebar [enablePersistence]="true"></ejs-sidebar>
// Persisted states:
// 1. Position (Left/Right)
// 2. Type (Push/Slide/Over/Auto)
// 3. Open/Closed state---
enableRtl
Type: boolean | Default: false
Specifies right-to-left layout for the sidebar, useful for RTL languages like Arabic and Hebrew.
// Example: Enable RTL layout
<ejs-sidebar [enableRtl]="true"></ejs-sidebar>
// Example: Dynamically set based on language
public isRtl = document.documentElement.lang === 'ar';
<ejs-sidebar [enableRtl]="isRtl"></ejs-sidebar>---
isOpen
Type: boolean | Default: false
Gets or sets whether the sidebar is in open (expanded) or closed (collapsed) state.
// Example: Initially open sidebar
<ejs-sidebar [isOpen]="true"></ejs-sidebar>
// Example: Initially closed (default)
<ejs-sidebar [isOpen]="false"></ejs-sidebar>
// Example: Toggle state from component
@ViewChild('sidebar') sidebar?: SidebarComponent;
toggleOpen() {
this.sidebar!.isOpen = !this.sidebar!.isOpen;
}
// Note: When sidebar type is 'Auto', this property is ignored on mobile devices---
mediaQuery
Type: string | MediaQueryList | Default: null
Specifies a media query string that automatically opens the sidebar when the query matches.
// Example: Open sidebar on screens wider than 600px
<ejs-sidebar [mediaQuery]="'(min-width: 600px)'"></ejs-sidebar>
// Example: Using MediaQueryList object
public mediaQuery = window.matchMedia('(min-width: 768px)');
<ejs-sidebar [mediaQuery]="mediaQuery"></ejs-sidebar>
// Example: Common breakpoints
// Mobile: '(max-width: 600px)'
// Tablet: '(min-width: 601px) and (max-width: 1024px)'
// Desktop: '(min-width: 1025px)'---
position
Type: SidebarPosition | Default: 'Left'
Specifies the position of the sidebar: 'Left' or 'Right'.
// Example: Position sidebar on the left (default)
<ejs-sidebar [position]="'Left'"></ejs-sidebar>
// Example: Position sidebar on the right
<ejs-sidebar [position]="'Right'"></ejs-sidebar>
// Example: Set position dynamically
public sidebarPosition: SidebarPosition = 'Left';
<ejs-sidebar [position]="sidebarPosition"></ejs-sidebar>Available values:
'Left'- Sidebar appears on the left side'Right'- Sidebar appears on the right side
---
showBackdrop
Type: boolean | Default: false
Specifies whether to display an overlay backdrop on the main content when sidebar is open.
// Example: Show backdrop overlay
<ejs-sidebar [showBackdrop]="true"></ejs-sidebar>
// Example: Backdrop with auto-close on click
<ejs-sidebar [showBackdrop]="true" [closeOnDocumentClick]="true"></ejs-sidebar>
// Example: Combine with other properties
<ejs-sidebar
[showBackdrop]="true"
[closeOnDocumentClick]="true"
[type]="'Over'">
</ejs-sidebar>---
target
Type: HTMLElement | string | Default: null
Specifies which element the sidebar will affect (push/slide/transform). See Target Property Behavior section above.
⚠️ Important: When using explicit target with transform types (Push/Slide), include an inner wrapper <div> inside the target container.
// ✅ Example: Explicit targeting with ID selector (CORRECT - with wrapper)
<ejs-sidebar [target]="'#content-area'" [type]="'Push'"></ejs-sidebar>
<div id="content-area">
<div> <!-- Required wrapper for transforms -->
<div>Content here</div>
</div>
</div>
// ✅ Example: Explicit targeting with CSS class (CORRECT - with wrapper)
<ejs-sidebar [target]="'.main-content'" [type]="'Push'"></ejs-sidebar>
<div class="main-content">
<div> <!-- Required wrapper for transforms -->
<div>Content here</div>
</div>
</div>
// ✅ Example: Pass HTMLElement directly
@ViewChild('targetDiv') targetElement?: ElementRef;
<ejs-sidebar [target]="targetElement?.nativeElement" [type]="'Push'"></ejs-sidebar>
<div #targetDiv>
<div> <!-- Required wrapper for transforms -->
<div>Content here</div>
</div>
</div>---
type
Type: SidebarType | Default: 'Auto'
Specifies how the sidebar expands: 'Push', 'Slide', 'Over', or 'Auto'.
// Example: Push type - sidebar pushes content aside
<ejs-sidebar [type]="'Push'"></ejs-sidebar>
// Example: Slide type - sidebar slides over and translates content
<ejs-sidebar [type]="'Slide'"></ejs-sidebar>
// Example: Over type - sidebar floats over content
<ejs-sidebar [type]="'Over'"></ejs-sidebar>
// Example: Auto type - Over on mobile, Push on desktop
<ejs-sidebar [type]="'Auto'"></ejs-sidebar>Available values:
'Push'- Sidebar pushes main content to the side'Slide'- Sidebar slides and translates main content'Over'- Sidebar floats over main content'Auto'- Responsive (Over on mobile, Push on desktop)
---
width
Type: string | number | Default: '280px'
Specifies the width of the sidebar in its expanded state. Can be set in pixels, percentages, or em units.
// Example: Set width in pixels
<ejs-sidebar [width]="'300px'"></ejs-sidebar>
// Example: Set width as number (treated as pixels)
<ejs-sidebar [width]="300"></ejs-sidebar>
// Example: Set width in percentage
<ejs-sidebar [width]="'50%'"></ejs-sidebar>
// Example: Set width in em units
<ejs-sidebar [width]="'20em'"></ejs-sidebar>
// Example: Responsive width
public sidebarWidth = window.innerWidth < 768 ? '100%' : '300px';
<ejs-sidebar [width]="sidebarWidth"></ejs-sidebar>---
zIndex
Type: string | number | Default: 1000
Specifies the z-index of the sidebar. Only applicable when sidebar type is 'Over' or 'Auto' on mobile.
// Example: Set z-index for layering
<ejs-sidebar [zIndex]="1000"></ejs-sidebar>
// Example: High z-index to appear above other modals
<ejs-sidebar [zIndex]="9999" [type]="'Over'"></ejs-sidebar>---
API Methods Reference
The Sidebar component provides the following methods for programmatic control:
show(e?: Event)
Description: Shows the sidebar if it's currently closed.
Parameters:
e(optional) - The event triggering the show action (MouseEvent | Event)
Returns: void
Example:
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
selector: 'app-root',
template: `
<ejs-sidebar #sidebar></ejs-sidebar>
<button (click)="openSidebar()">Open Sidebar</button>
`
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
// Method 1: Show without event
openSidebar() {
this.sidebar?.show();
}
// Method 2: Show with event
openSidebarWithEvent(event: MouseEvent) {
this.sidebar?.show(event);
}
}---
hide(e?: Event)
Description: Hides the sidebar if it's currently open.
Parameters:
e(optional) - The event triggering the hide action (MouseEvent | Event)
Returns: void
Example:
@Component({
selector: 'app-root',
template: `
<ejs-sidebar #sidebar></ejs-sidebar>
<button (click)="closeSidebar()">Close Sidebar</button>
`
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
// Method 1: Hide without event
closeSidebar() {
this.sidebar?.hide();
}
// Method 2: Hide with click event
closeSidebarOnClick(event: MouseEvent) {
this.sidebar?.hide(event);
}
}---
toggle()
Description: Toggles the sidebar between open and closed states.
Returns: void
Example:
@Component({
selector: 'app-root',
template: `
<ejs-sidebar #sidebar id="sidebar" [isOpen]="false">
<button (click)="toggleMenu()">Close</button>
</ejs-sidebar>
<button (click)="toggleMenu()">☰ Menu</button>
`
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
toggleMenu() {
this.sidebar?.toggle();
}
}---
destroy()
Description: Removes the sidebar control from the DOM and detaches all event handlers and attributes.
Returns: void
Example:
@Component({
selector: 'app-root',
template: `
<ejs-sidebar #sidebar></ejs-sidebar>
<button (click)="destroySidebar()">Destroy Sidebar</button>
`
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
// Destroy and remove the sidebar
destroySidebar() {
this.sidebar?.destroy();
}
}---
dataBind()
Description: Applies pending property changes to the sidebar component. Use this method after dynamically changing sidebar properties to ensure changes are rendered immediately.
Returns: void
Example:
@Component({
selector: 'app-root',
template: `
<ejs-sidebar
#sidebar
[width]="sidebarWidth"
[type]="sidebarType">
</ejs-sidebar>
<button (click)="changeSidebarProperties()">Change Properties</button>
`
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
sidebarWidth = '280px';
sidebarType = 'Push';
// Change sidebar properties dynamically
changeSidebarProperties() {
// Modify properties
this.sidebarWidth = '350px';
this.sidebarType = 'Slide';
// Apply changes to the component
(this.sidebar as SidebarComponent).dataBind();
}
// Another example: Toggle width on docked state
updateDockSize() {
(this.sidebar as SidebarComponent).dockSize = '100px';
(this.sidebar as SidebarComponent).dataBind();
}
}---
API Events Reference
The Sidebar component emits the following events during its lifecycle and interactions:
open
Description: Triggers when the sidebar is opened.
Event Arguments: `EventArgs`
EventArgs Properties:
cancel(boolean) - Set to true to prevent the open actionelement(HTMLElement) - The sidebar DOM elementevent(MouseEvent | Event) - The original browser eventisInteracted(boolean) - Whether the user interacted to trigger the openmodel(SidebarModel) - The sidebar model instance
Example:
@Component({
selector: 'app-root',
template: `
<ejs-sidebar
#sidebar
(open)="onOpen($event)">
</ejs-sidebar>
`
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onOpen(event: any) {
console.log('Sidebar opened');
console.log('Event:', event.event);
console.log('Element:', event.element);
console.log('Is Interacted:', event.isInteracted);
// Prevent opening if needed
// event.cancel = true;
}
}---
close
Description: Triggers when the sidebar is closed.
Event Arguments: `EventArgs`
EventArgs Properties:
cancel(boolean) - Set to true to prevent the close actionelement(HTMLElement) - The sidebar DOM elementevent(MouseEvent | Event) - The original browser eventisInteracted(boolean) - Whether the user interacted to trigger the closemodel(SidebarModel) - The sidebar model instance
Example:
@Component({
selector: 'app-root',
template: `
<ejs-sidebar
#sidebar
(close)="onClose($event)">
</ejs-sidebar>
`
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onClose(event: any) {
console.log('Sidebar closed');
console.log('Is Interacted:', event.isInteracted);
// Prevent closing if needed
// event.cancel = true;
}
}---
change
Description: Triggers when the sidebar state changes between open and closed.
Event Arguments: `ChangeEventArgs`
ChangeEventArgs Properties:
element(HTMLElement) - The sidebar DOM elementname(string) - Event name: 'change'
Example:
@Component({
selector: 'app-root',
template: `
<ejs-sidebar
#sidebar
(change)="onChange($event)">
</ejs-sidebar>
`
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onChange(event: any) {
console.log('Sidebar state changed');
console.log('Event name:', event.name);
console.log('Element:', event.element);
}
}---
created
Description: Triggers when the sidebar component is created and initialized.
Event Arguments: Object
Example:
@Component({
selector: 'app-root',
template: `
<ejs-sidebar
#sidebar
(created)="onCreated($event)"
style="visibility: hidden">
</ejs-sidebar>
`
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(event: any) {
console.log('Sidebar created and initialized');
// Make sidebar visible after creation
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
}---
destroyed
Description: Triggers when the sidebar component is destroyed.
Event Arguments: Object
Example:
@Component({
selector: 'app-root',
template: `
<ejs-sidebar
#sidebar
(destroyed)="onDestroyed($event)">
</ejs-sidebar>
`
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onDestroyed(event: any) {
console.log('Sidebar destroyed');
// Cleanup any additional resources
}
}---
Common Patterns
Pattern 1: Toggle Button Sidebar
Open/close sidebar with button clicks using the toggle() method. Perfect for mobile navigation and responsive layouts.
// In component.ts
toggleSidebar() {
this.sidebar?.toggle();
}
// In template
<button (click)="toggleSidebar()">Toggle</button>Pattern 2: Responsive Auto-Close
Automatically collapse sidebar on small screens using mediaQuery property.
public mediaQuery = window.matchMedia('(max-width: 600px)');
// In template
<ejs-sidebar [mediaQuery]="mediaQuery" [isOpen]="true">Pattern 3: Docked Navigation with Icons
Create a compact icon-only docked state that expands on click.
public enableDock = true;
public dockSize = '72px';
// In template
<ejs-sidebar [enableDock]="enableDock" [dockSize]="dockSize">Pattern 4: Backdrop for Focus
Use backdrop to overlay main content and focus on sidebar.
// In template
<ejs-sidebar [showBackdrop]="true" [closeOnDocumentClick]="true">Key Properties
| Property | Type | Default | Purpose |
|---|---|---|---|
type | Push \ | Slide \ | Over \ |
position | Left \ | Right | Left |
width | string \ | number | 280px |
dockSize | string \ | number | auto |
enableDock | boolean | false | Enable compact docked state |
isOpen | boolean | false | Initial open/closed state |
animate | boolean | true | Enable expand/collapse animations |
showBackdrop | boolean | false | Display overlay on main content |
closeOnDocumentClick | boolean | false | Close when clicking outside |
enableGestures | boolean | true | Enable touch swipe gestures |
mediaQuery | string \ | MediaQueryList | null |
enableRtl | boolean | false | Right-to-left layout support |
enablePersistence | boolean | false | Persist state between page reloads |
Common Use Cases
1. App Navigation Menu - Top-level navigation with toggle button 2. Mobile Menu - Responsive sidebar that auto-closes on small screens 3. Settings Panel - Docked icon-based panel expanding to show options 4. Hierarchical Navigation - TreeView-based nested menu structure 5. Content Sidebar - Always-visible sidebar alongside main content 6. Mail Application - Folder tree with email list (ListView + TreeView) 7. Dashboard Layout - Collapsible widget panel 8. RTL Application - Right-to-left sidebar for Arabic/Hebrew interfaces
See Also
- Syncfusion Angular Sidebar Documentation
- Sidebar API Reference
- Component Events and Properties
Advanced Sidebar Features and Patterns
Table of Contents
- State Persistence
- Hiding Sidebars with Routing
- Accessibility Features
- Performance Optimization
- Advanced Event Handling
- Troubleshooting
State Persistence
Persist sidebar open/closed state between page reloads using enablePersistence property:
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="default-sidebar" #sidebar
type="Push"
[enablePersistence]="true"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Sidebar content</div>
<button (click)="closeSidebar()">Close</button>
</ejs-sidebar>
<div>
<div class="title">Main content</div>
<p>Sidebar state persists across page reloads</p>
<button (click)="toggleSidebar()">Toggle</button>
</div>`
})
export class PersistenceComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
closeSidebar() {
this.sidebar?.hide();
}
}How It Works
enablePersistencesaves the sidebar state to browser's localStorage- State is automatically restored when page reloads
- Storage key:
ej2_sidebar_id_default-sidebar(based on element ID) - Works with all properties: type, position, isOpen, etc.
Manual State Management
For custom storage (e.g., server-side persistence):
@Component({
selector: 'app-custom-persistence',
template: `<ejs-sidebar #sidebar
[isOpen]="sidebarOpen"
(change)="onStateChange($event)">
</ejs-sidebar>`
})
export class CustomPersistenceComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
sidebarOpen = false;
ngOnInit() {
// Load state from server
this.loadSidebarState();
}
onStateChange(args: any) {
// State changed - get current open state from sidebar
const currentState = this.sidebar?.isOpen;
this.saveSidebarState(currentState);
}
loadSidebarState() {
// Fetch from API
// this.sidebarOpen = response.isOpen;
}
saveSidebarState(isOpen: boolean | undefined) {
// Save to API
// this.userService.updateSidebarState(isOpen);
}
}Hiding Sidebars with Routing
Hide sidebar conditionally based on current route using Angular Router:
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
selector: 'app-root',
template: `<ejs-sidebar id="sidebar" #sidebar
(created)="onCreated()">
<nav-menu (itemSelected)="onMenuItemSelect()"></nav-menu>
</ejs-sidebar>
<div class="main-content">
<router-outlet></router-outlet>
</div>`
})
export class AppComponent implements AfterViewInit {
@ViewChild('sidebar') sidebar?: SidebarComponent;
constructor(private router: Router) {
// Listen to route changes
this.router.events.forEach((event) => {
if (event instanceof NavigationEnd) {
this.handleRouteChange(event.url);
}
});
}
onCreated() {
if (this.sidebar) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
}
handleRouteChange(url: string) {
// Hide sidebar on specific routes (e.g., login, checkout)
const hideSidebarRoutes = ['/login', '/register', '/checkout'];
const shouldHide = hideSidebarRoutes.some(route => url.includes(route));
if (shouldHide) {
this.sidebar?.hide();
// Optionally disable toggle button
} else {
// Show sidebar (but don't force open)
}
}
onMenuItemSelect() {
// Auto-close sidebar on mobile after selection
if (window.innerWidth < 768) {
this.sidebar?.hide();
}
}
ngAfterViewInit() {
// Initial check on page load
const url = this.router.routerState.root.component.toString();
this.handleRouteChange(url);
}
}Route-Specific Sidebar Configuration
// Different sidebar configs per route
const routeSidebarConfig = {
'/dashboard': { type: 'Push', position: 'Left', isOpen: true },
'/profile': { type: 'Over', position: 'Right', isOpen: false },
'/settings': { type: 'Push', position: 'Left', isOpen: false }
};
onRouteChange(route: string) {
const config = routeSidebarConfig[route];
if (config && this.sidebar) {
(this.sidebar as SidebarComponent).type = config.type;
(this.sidebar as SidebarComponent).position = config.position;
(this.sidebar as SidebarComponent).isOpen = config.isOpen;
(this.sidebar as SidebarComponent).dataBind();
}
}Accessibility Features
ARIA Attributes
The Sidebar automatically includes ARIA attributes for screen reader support:
@Component({
selector: 'app-accessible-sidebar',
template: `<ejs-sidebar #sidebar
role="navigation"
aria-label="Main navigation"
[attr.aria-expanded]="sidebarOpen">
<nav>
<ul role="menubar">
<li role="presentation">
<a href="#" role="menuitem">Home</a>
</li>
<li role="presentation">
<a href="#" role="menuitem">About</a>
</li>
</ul>
</nav>
</ejs-sidebar>
<main role="main">Content</main>`
})
export class AccessibleSidebarComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
get sidebarOpen(): boolean {
return this.sidebar?.isOpen ?? false;
}
}Keyboard Navigation
Enable keyboard support for sidebar toggle:
@Component({
template: `<ejs-sidebar #sidebar>
</ejs-sidebar>
<div (keydown)="handleKeydown($event)">
Content area
</div>`
})
export class KeyboardNavComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
handleKeydown(event: KeyboardEvent) {
// Alt + M to toggle sidebar (common shortcut)
if (event.altKey && event.code === 'KeyM') {
event.preventDefault();
this.sidebar?.toggle();
}
// Escape to close sidebar
if (event.code === 'Escape') {
this.sidebar?.hide();
}
}
}Focus Management
@Component({
template: `<ejs-sidebar #sidebar
(open)="onOpen()">
<div #firstFocusable tabindex="0">First item</div>
</ejs-sidebar>`
})
export class FocusManagementComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
@ViewChild('firstFocusable') firstFocusable?: any;
onOpen() {
// Move focus to sidebar when opened
setTimeout(() => {
this.firstFocusable?.nativeElement?.focus();
});
}
}Performance Optimization
Lazy Load Sidebar Content
Load sidebar content only when sidebar opens to improve initial page load:
@Component({
selector: 'app-lazy-sidebar',
template: `<ejs-sidebar #sidebar
(open)="onSidebarOpen()">
<div *ngIf="contentLoaded">
<lazy-nav-menu></lazy-nav-menu>
</div>
</ejs-sidebar>`
})
export class LazySidebarComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
contentLoaded = false;
onSidebarOpen() {
if (!this.contentLoaded) {
// Load sidebar content only on first open
this.contentLoaded = true;
// Or load from service: this.loadContent();
}
}
}OnPush Change Detection
Optimize performance with OnPush change detection:
@Component({
selector: 'app-optimized-sidebar',
template: `<ejs-sidebar #sidebar>...</ejs-sidebar>`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class OptimizedSidebarComponent {
constructor(private cdr: ChangeDetectorRef) {}
updateSidebar() {
// Manual change detection
this.cdr.detectChanges();
}
}Virtual Scrolling for Large Lists
For sidebars with many items, use virtual scrolling:
@Component({
imports: [SidebarModule, ScrollingModule],
template: `<ejs-sidebar #sidebar>
<cdk-virtual-scroll-viewport [itemSize]="50" class="nav-list">
<div *cdkVirtualFor="let item of navItems" class="nav-item">
{{ item.text }}
</div>
</cdk-virtual-scroll-viewport>
</ejs-sidebar>`
})
export class VirtualScrollComponent {
navItems = Array.from({ length: 1000 }, (_, i) => ({
id: i,
text: `Item ${i}`
}));
}Advanced Event Handling
State Change Events
@Component({
selector: 'app-events',
template: `<ejs-sidebar #sidebar
(open)="onOpen($event)"
(close)="onClose($event)"
(change)="onChange($event)"
(created)="onCreated($event)">
</ejs-sidebar>`
})
export class EventsComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onOpen(args: any) {
console.log('Sidebar opened', args);
// Emit analytics event
this.trackEvent('sidebar_opened');
}
onClose(args: any) {
console.log('Sidebar closed', args);
this.trackEvent('sidebar_closed');
}
onChange(args: any) {
console.log('State changed');
console.log('Event name:', args.name);
console.log('Element:', args.element);
// Get current state from sidebar component
const isOpen = this.sidebar?.isOpen;
this.trackEvent(isOpen ? 'sidebar_opened' : 'sidebar_closed');
}
onCreated(args: any) {
console.log('Sidebar initialized');
}
private trackEvent(eventName: string) {
// Send to analytics service
}
}Custom Event Emitters
@Component({
selector: 'app-sidebar-container',
template: `<app-sidebar (stateChange)="onStateChange($event)"></app-sidebar>`
})
export class SidebarContainerComponent {
onStateChange(isOpen: boolean) {
console.log('Sidebar state:', isOpen);
}
}
@Component({
selector: 'app-sidebar',
template: `<ejs-sidebar #sidebar
(change)="emitStateChange($event)">
</ejs-sidebar>`
})
export class SidebarComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
@Output() stateChange = new EventEmitter<boolean>();
emitStateChange(args: any) {
// Get current state from sidebar component
const isOpen = this.sidebar?.isOpen ?? false;
this.stateChange.emit(isOpen);
}
}Troubleshooting
Sidebar Not Showing
Problem: Sidebar element is invisible or hidden initially.
Solution: Set style="visibility: hidden" and show in (created) event:
template: `<ejs-sidebar style="visibility: hidden"
(created)="onCreated($event)">
</ejs-sidebar>`
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}Content Not Scrolling
Problem: Sidebar content is cut off and cannot scroll.
Solution: Add CSS for scrollable content:
:host ::ng-deep .e-sidebar {
overflow-y: auto;
max-height: 100vh;
}Backdrop Not Working
Problem: Backdrop overlay not appearing with showBackdrop.
Solution: Ensure target wrapper is set correctly with inner wrapper div:
template: `<ejs-sidebar [target]="'#wrapper'" [showBackdrop]="true">
</ejs-sidebar>
<div id="wrapper">
<div>
<!-- Only this element gets backdrop overlay -->
</div>
</div>`Animation Lag
Problem: Sidebar animation is slow or janky.
Solution: Use GPU acceleration with CSS:
:host ::ng-deep .e-sidebar {
will-change: transform;
transform: translateZ(0);
backface-visibility: hidden;
}Media Query Not Responsive
Problem: Sidebar doesn't auto-close on screen resize.
Solution: Use debounced resize handler:
private resizeSubject = new Subject<Event>();
ngOnInit() {
this.resizeSubject.pipe(
debounceTime(300),
takeUntil(this.destroy$)
).subscribe(() => {
this.handleResize();
});
window.addEventListener('resize', (e) => {
this.resizeSubject.next(e);
});
}
handleResize() {
const isMobile = window.innerWidth < 768;
if (isMobile && this.sidebar?.isOpen) {
this.sidebar?.hide();
}
}Route Change Sidebar Not Hiding
Problem: Sidebar stays open when navigating routes.
Solution: Subscribe to router events properly:
constructor(private router: Router) {
this.router.events.pipe(
filter(event => event instanceof NavigationEnd),
takeUntil(this.destroy$)
).subscribe((event: NavigationEnd) => {
this.sidebar?.hide();
});
}Memory Leaks
Problem: Event listeners not cleaned up.
Solution: Unsubscribe and destroy subscriptions:
private destroy$ = new Subject<void>();
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
// In subscriptions:
.pipe(takeUntil(this.destroy$))
.subscribe(...);Best Practices Checklist
- ✅ Always set initial
style="visibility: hidden"and show increatedevent - ✅ Use
@ViewChildto access sidebar methods (show, hide, toggle) - ✅ Set
[target]property for proper content pushing/shifting - ✅ Use
type="Auto"for responsive behavior by default - ✅ Enable
enableGesturesfor mobile touch support - ✅ Use
closeOnDocumentClickfor dropdown-style sidebars - ✅ Add media queries for responsive design changes
- ✅ Unsubscribe from observables in ngOnDestroy
- ✅ Use proper ARIA attributes for accessibility
- ✅ Test on various devices and screen sizes
Sidebar Animations and Styling
Table of Contents
Animation Control
Enable or disable expand/collapse animations using the animate property (enabled by default):
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="default-sidebar" #sidebar
[animate]="animateEnabled"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Sidebar content</div>
<button (click)="closeSidebar()">Close</button>
</ejs-sidebar>
<div>
<div class="title">Main content</div>
<div class="controls">
<label>
<input type="checkbox"
[(ngModel)]="animateEnabled"
(change)="updateAnimation()">
Enable Animation
</label>
</div>
<button (click)="toggleSidebar()">Toggle Sidebar</button>
</div>`
})
export class AnimationControlComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
animateEnabled = true;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
updateAnimation() {
if (this.sidebar) {
(this.sidebar as SidebarComponent).animate = this.animateEnabled;
(this.sidebar as SidebarComponent).dataBind();
}
}
toggleSidebar() {
this.sidebar?.toggle();
}
closeSidebar() {
this.sidebar?.hide();
}
}Animation Duration
Control animation speed with CSS transitions:
:host ::ng-deep {
.e-sidebar {
transition: all 0.3s ease-in-out !important;
}
}Animation Types
Syncfusion provides built-in animation variations through CSS classes and positioning types:
Push Type Animation
Smooth slide-and-resize animation:
@Component({
template: `<ejs-sidebar #sidebar
type="Push"
[animate]="true"
[width]="'280px'">
</ejs-sidebar>`
})
export class PushAnimationComponent { }Slide Type Animation
Content shifts with sidebar expansion:
@Component({
template: `<ejs-sidebar #sidebar
type="Slide"
[animate]="true"
[width]="'280px'">
</ejs-sidebar>`
})
export class SlideAnimationComponent { }Over Type Animation
Sidebar animates over main content:
@Component({
template: `<ejs-sidebar #sidebar
type="Over"
[animate]="true"
[width]="'280px'>
</ejs-sidebar>`
})
export class OverAnimationComponent { }CSS Theming
Available Themes
Import theme CSS in src/styles.css:
/* Material 3 (Default, Modern) */
@import '@syncfusion/ej2-base/styles/material3.css';
@import '@syncfusion/ej2-angular-navigations/styles/material3.css';
/* Bootstrap 5 */
@import '@syncfusion/ej2-base/styles/bootstrap5.css';
@import '@syncfusion/ej2-angular-navigations/styles/bootstrap5.css';
/* Fluent Design */
@import '@syncfusion/ej2-base/styles/fluent.css';
@import '@syncfusion/ej2-angular-navigations/styles/fluent.css';
/* Tailwind */
@import '@syncfusion/ej2-base/styles/tailwind.css';
@import '@syncfusion/ej2-angular-navigations/styles/tailwind.css';
/* High Contrast (Accessibility) */
@import '@syncfusion/ej2-base/styles/highcontrast.css';
@import '@syncfusion/ej2-angular-navigations/styles/highcontrast.css';Theme Switching at Runtime
Switch themes dynamically:
@Component({
selector: 'app-root',
template: `<select (change)="changeTheme($event)">
<option value="material3">Material 3</option>
<option value="bootstrap5">Bootstrap 5</option>
<option value="fluent">Fluent</option>
<option value="tailwind">Tailwind</option>
</select>
<ejs-sidebar #sidebar></ejs-sidebar>`
})
export class ThemeSwitchComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
currentTheme = 'material3';
changeTheme(event: any) {
const theme = event.target.value;
this.currentTheme = theme;
// Remove all theme classes
document.body.classList.remove('e-material3', 'e-bootstrap5', 'e-fluent', 'e-tailwind');
// Add new theme class
document.body.classList.add(`e-${theme}`);
// Rebind component
this.sidebar?.dataBind();
}
}RTL Support
Enable right-to-left layout for Arabic, Hebrew, and other RTL languages using enableRtl:
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="default-sidebar" #sidebar
[enableRtl]="true"
position="Right"
[animate]="true"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">محتوى الشريط الجانبي</div>
<button (click)="closeSidebar()">إغلاق</button>
</ejs-sidebar>
<div [dir]="'rtl'">
<div class="title">المحتوى الرئيسي</div>
<button (click)="toggleSidebar()">قائمة</button>
</div>`
})
export class RTLSidebarComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
// Set HTML dir attribute for RTL
document.documentElement.dir = 'rtl';
}
toggleSidebar() {
this.sidebar?.toggle();
}
closeSidebar() {
this.sidebar?.hide();
}
}RTL CSS
Apply RTL styles:
:host-context([dir="rtl"]) {
.e-sidebar {
transform: translateX(-100%);
}
.sidebar-nav {
text-align: right;
}
.sidebar-nav .icon {
margin-left: 10px;
margin-right: 0;
}
}Responsive Design
Media Query Responsive
Use media queries to automatically switch sidebar behavior:
@Component({
selector: 'app-responsive-sidebar',
template: `<ejs-sidebar #sidebar
[type]="sidebarType"
[mediaQuery]="mediaQuery"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="nav-items">
<ul>
<li>Home</li>
<li>About</li>
<li>Services</li>
</ul>
</div>
</ejs-sidebar>
<div class="main-container">
<header class="app-header">
<button (click)="toggleSidebar()">☰</button>
</header>
<main class="content">
Responsive content area
</main>
</div>`,
styles: [`
:host {
--sidebar-width: 280px;
}
/* Mobile */
@media (max-width: 768px) {
:host {
--sidebar-width: 240px;
}
}
/* Small devices */
@media (max-width: 480px) {
:host {
--sidebar-width: 200px;
}
}
`]
})
export class ResponsiveSidebarComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
sidebarType = 'Auto';
mediaQuery = window.matchMedia('(max-width: 768px)');
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
}Responsive Breakpoints
/* Desktop: Sidebar always visible */
@media (min-width: 1200px) {
.e-sidebar {
position: relative;
width: 280px;
}
}
/* Tablet: Sidebar collapsible */
@media (min-width: 768px) and (max-width: 1199px) {
.e-sidebar {
width: 240px;
}
}
/* Mobile: Sidebar overlay */
@media (max-width: 767px) {
.e-sidebar {
width: 200px;
position: fixed;
}
}Custom Styling
Custom CSS Classes
Apply custom styles to sidebar:
@Component({
selector: 'app-custom-style',
template: `<ejs-sidebar #sidebar
cssClass="custom-sidebar"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="sidebar-content">
Custom styled sidebar
</div>
</ejs-sidebar>`,
styles: [`
:host ::ng-deep {
.custom-sidebar {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.custom-sidebar .sidebar-content {
padding: 20px;
}
.custom-sidebar a {
color: #e0e0e0;
text-decoration: none;
}
.custom-sidebar a:hover {
color: white;
background: rgba(255,255,255,0.1);
}
}
`]
})
export class CustomStyleComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
}Color Customization
:host ::ng-deep {
.e-sidebar {
/* Background */
background-color: #f8f9fa;
/* Text Color */
color: #333;
/* Border */
border-right: 1px solid #e0e0e0;
}
.e-sidebar .nav-item {
color: #555;
padding: 12px 20px;
border-bottom: 1px solid #f0f0f0;
}
.e-sidebar .nav-item:hover {
background: #e8f4f8;
color: #667eea;
}
.e-sidebar .nav-item.active {
background: #667eea;
color: white;
}
}Docked State Styling
:host ::ng-deep {
/* Docked (collapsed) state */
.e-dock.e-close {
width: 72px !important;
}
.e-dock.e-close .e-text {
display: none;
}
.e-dock.e-close .icon {
display: block;
text-align: center;
}
/* Open state */
.e-dock.e-open {
width: 220px !important;
}
.e-dock.e-open .e-text {
display: inline;
}
}Complete Example: Styled Application Shell
@Component({
selector: 'app-shell',
template: `<ejs-sidebar #sidebar
cssClass="app-sidebar"
type="Push"
[animate]="true"
[enableRtl]="isRTL"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="sidebar-header">
<img src="assets/logo.svg" alt="App Logo">
<h2>MyApp</h2>
</div>
<nav class="sidebar-nav">
<a href="#" class="nav-item active">
<span class="icon home"></span>
<span class="text">Home</span>
</a>
<a href="#" class="nav-item">
<span class="icon users"></span>
<span class="text">Users</span>
</a>
<a href="#" class="nav-item">
<span class="icon settings"></span>
<span class="text">Settings</span>
</a>
</nav>
</ejs-sidebar>
<div class="app-container">
<header class="app-header">
<button (click)="toggleSidebar()" class="menu-btn">☰</button>
<h1>Dashboard</h1>
<button (click)="toggleRTL()" class="rtl-btn">RTL</button>
</header>
<main class="app-content">
<!-- Page content -->
</main>
</div>`,
styles: [`
:host {
display: flex;
height: 100vh;
}
:host ::ng-deep {
.app-sidebar {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
box-shadow: 2px 0 8px rgba(0,0,0,0.1);
}
.sidebar-header {
padding: 20px;
text-align: center;
border-bottom: 2px solid rgba(255,255,255,0.2);
}
.sidebar-header img {
width: 50px;
margin-bottom: 10px;
}
.sidebar-nav {
list-style: none;
padding: 20px 0;
}
.nav-item {
display: flex;
align-items: center;
padding: 15px 20px;
text-decoration: none;
color: rgba(255,255,255,0.8);
transition: all 0.3s;
}
.nav-item:hover,
.nav-item.active {
background: rgba(255,255,255,0.1);
color: white;
padding-left: 25px;
}
.nav-item .icon {
width: 20px;
margin-right: 15px;
}
.app-container {
flex: 1;
display: flex;
flex-direction: column;
}
.app-header {
background: white;
padding: 15px 20px;
border-bottom: 1px solid #e0e0e0;
display: flex;
align-items: center;
gap: 15px;
}
.app-content {
flex: 1;
overflow-y: auto;
padding: 20px;
}
}
`]
})
export class AppShellComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
isRTL = false;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
toggleRTL() {
this.isRTL = !this.isRTL;
document.documentElement.dir = this.isRTL ? 'rtl' : 'ltr';
}
}Getting Started with Syncfusion Angular Sidebar
Table of Contents
- Setup Angular Environment
- Installing Syncfusion Packages
- Adding Styles
- Adding Sidebar Component
- Basic Examples
- Running the Application
Setup Angular Environment
Install Angular CLI
Install Angular CLI globally to create and manage Angular projects:
npm install -g @angular/cliFor a specific version:
npm install -g @angular/cli@21.0.0Create New Angular Project
Generate a new Angular application using the CLI:
ng new syncfusion-angular-appThe CLI will prompt you to choose:
- Stylesheet format (CSS, SCSS, Less)
- Server-side rendering (SSR)
- AI tools integration
Navigate to the project directory:
cd syncfusion-angular-appNote: Angular 20+ uses simplified structure withapp.ts,app.html,app.css(no.componentsuffixes). Angular 19 and below useapp.component.ts,app.component.html,app.component.css.
Installing Syncfusion Packages
Ivy Library Distribution (Recommended)
For Angular 12+, use the modern Ivy distribution package:
npm install @syncfusion/ej2-angular-navigations --saveThis includes all Sidebar dependencies:
- @syncfusion/ej2-base
- @syncfusion/ej2-data
- @syncfusion/ej2-angular-base
- @syncfusion/ej2-navigations
- And supporting packages (buttons, inputs, lists, popups)
Angular Compatibility Compiled Package (ngcc)
For Angular versions below 12, use the ngcc (Angular Compatibility Compiler) package:
npm install @syncfusion/ej2-angular-navigations@ngcc --saveOr specify in package.json:
"@syncfusion/ej2-angular-navigations": "20.2.38-ngcc"Adding Styles
Import Sidebar and dependency styles in src/styles.css:
@import '../node_modules/@syncfusion/ej2-base/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-angular-navigations/styles/material3.css';Alternative import path (based on your CSS file location):
@import 'node_modules/@syncfusion/ej2-base/styles/material3.css';
@import 'node_modules/@syncfusion/ej2-angular-navigations/styles/material3.css';Theme Options: The example uses Material3 theme. Other available themes:
bootstrap5.cssfluent.csshighcontrast.csstailwind.css
For combined component styles, use the CRG (Custom Resource Generator).
Adding Sidebar Component
In app.component.ts
Import the Sidebar module and create the component using standalone architecture:
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="default-sidebar" #sidebar>
<div class="title">Sidebar content</div>
</ejs-sidebar>
<div>
<div class="title">Main content</div>
<div class="sub-title">Content goes here.</div>
</div>`
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
}Main Entry Point (main.ts)
Bootstrap the standalone application:
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Basic Examples
Example 1: Simple Sidebar with Toggle
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="default-sidebar" #sidebar
[width]="'280px'" (created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Sidebar content</div>
</ejs-sidebar>
<div>
<div class="title">Main content</div>
<button (click)="toggleClick()">Toggle Sidebar</button>
</div>`
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
// Show sidebar after creation
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleClick() {
this.sidebar?.toggle();
}
}Example 2: Sidebar with Backdrop
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="default-sidebar" #sidebar
[width]="'280px'"
[showBackdrop]="true"
[closeOnDocumentClick]="true"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Sidebar content</div>
<button (click)="closeSidebar()">Close</button>
</ejs-sidebar>
<div>
<div class="title">Main content</div>
<button (click)="openSidebar()">Open</button>
</div>`
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
openSidebar() {
this.sidebar?.show();
}
closeSidebar() {
this.sidebar?.hide();
}
}Running the Application
Development Server
Start the development server with auto-reload:
ng serve --openThe --open flag automatically opens the application in your browser at http://localhost:4200.
Production Build
Build for production:
ng build --configuration productionCompiled files will be in the dist/ directory.
Key Points
- ViewChild Setup: Use
@ViewChild('sidebar') sidebar?: SidebarComponent;to reference the sidebar for method calls - Visibility Hidden: Set
style="visibility: hidden"initially to prevent flashing before component initializes - onCreated Event: Use
(created)="onCreated($event)"to show the sidebar after initialization is complete - Standalone Components: Modern Angular uses standalone mode (imports array instead of NgModule)
- Zone.js: Import 'zone.js' for Angular zone handling
See Also
- Sidebar Types and Positioning: Reference the positioning guide for Push, Slide, Over, Auto types
- Content Integration: Use ListView or TreeView for rich sidebar content
- Responsive Behavior: Use mediaQuery for auto-close on different screen sizes
Sidebar Content and Components
Table of Contents
- Sidebar Content Overview
- ListView Integration
- TreeView Integration
- Custom HTML Content
- Target Element Configuration
Sidebar Content Overview
ℹ️ Targeting Mode: Unless otherwise noted, examples in this section use implicit targeting (sidebar automatically targets the next sibling div). Some advanced examples show explicit targeting with the [target] property.The Sidebar is a flexible container that supports any HTML content or Angular components. Common content patterns include:
- Simple text and links
- ListView for list-based navigation
- TreeView for hierarchical menus
- Custom HTML with icons
- Component instances
ListView Integration
Use ListView component inside Sidebar for structured list navigation:
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { ListViewModule } from '@syncfusion/ej2-angular-lists';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
imports: [SidebarModule, ListViewModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="sidebar" #sidebar
[width]="'260px'"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="sidebar-header">
<span>Navigation</span>
</div>
<ejs-listview #listView
[dataSource]="listData"
(select)="onSelect($event)">
</ejs-listview>
</ejs-sidebar>
<div>
<div class="toolbar">
<button (click)="toggleSidebar()">☰ Menu</button>
</div>
<div class="content">
<h2>{{ selectedItem }}</h2>
<p>Selected item content</p>
</div>
</div>`,
styles: [`
.sidebar-header {
padding: 20px;
border-bottom: 1px solid #e0e0e0;
font-weight: bold;
}
`]
})
export class ListViewSidebarComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
listData = [
{ id: '1', text: 'Home', icon: 'e-icons e-home' },
{ id: '2', text: 'Profile', icon: 'e-icons e-user' },
{ id: '3', text: 'Settings', icon: 'e-icons e-settings' },
{ id: '4', text: 'About', icon: 'e-icons e-info' }
];
selectedItem = 'Select an item';
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
onSelect(args: any) {
this.selectedItem = args.text;
this.sidebar?.hide(); // Auto-close after selection
}
toggleSidebar() {
this.sidebar?.toggle();
}
}ListView with Icons
Display icons alongside list items:
template: `<ejs-listview #listView
[dataSource]="listData"
[headerTitle]="'Menu'"
[showIcon]="true"
(select)="onSelect($event)"
template="<span class='{{icon}}'></span><span class='text'>{{text}}</span>">
</ejs-listview>`,TreeView Integration
Use TreeView for hierarchical navigation structure:
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { TreeViewModule } from '@syncfusion/ej2-angular-navigations';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
imports: [SidebarModule, TreeViewModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="sidebar" #sidebar
[width]="'280px'"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="sidebar-header">
<span>Explore</span>
</div>
<ejs-treeview #treeView
[fields]="treeFields"
[dataSource]="treeData"
(nodeSelected)="onNodeSelect($event)">
</ejs-treeview>
</ejs-sidebar>
<div>
<div class="toolbar">
<button (click)="toggleSidebar()">☰ Menu</button>
</div>
<div class="content">
<h2>{{ selectedNode }}</h2>
</div>
</div>`,
styles: [`
.sidebar-header {
padding: 15px;
border-bottom: 1px solid #e0e0e0;
font-weight: bold;
}
`]
})
export class TreeViewSidebarComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
treeFields: any = { dataSource: this.treeData, id: 'id', text: 'text', child: 'child' };
treeData = [
{
id: '1', text: 'Documents',
child: [
{ id: '1-1', text: 'Reports' },
{ id: '1-2', text: 'Proposals' }
]
},
{
id: '2', text: 'Media',
child: [
{ id: '2-1', text: 'Images' },
{ id: '2-2', text: 'Videos' }
]
},
{
id: '3', text: 'Downloads'
}
];
selectedNode = 'Select an item';
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
onNodeSelect(args: any) {
this.selectedNode = args.node.innerText;
}
toggleSidebar() {
this.sidebar?.toggle();
}
}Custom HTML Content
Create custom sidebar content with HTML structure:
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="sidebar" #sidebar
[width]="'280px'"
(created)="onCreated($event)"
style="visibility: hidden">
<!-- Sidebar Header -->
<div class="sidebar-header">
<img src="assets/profile.jpg" alt="Profile" class="profile-pic">
<h3>John Doe</h3>
<p>john@example.com</p>
</div>
<!-- Navigation Menu -->
<nav class="sidebar-nav">
<div class="nav-section">
<h4>Main</h4>
<ul>
<li><a href="#"><span class="icon home-icon"></span>Home</a></li>
<li><a href="#"><span class="icon search-icon"></span>Search</a></li>
<li><a href="#"><span class="icon heart-icon"></span>Favorites</a></li>
</ul>
</div>
<div class="nav-section">
<h4>Library</h4>
<ul>
<li><a href="#"><span class="icon folder-icon"></span>Your Uploads</a></li>
<li><a href="#"><span class="icon history-icon"></span>History</a></li>
<li><a href="#"><span class="icon watch-icon"></span>Watch Later</a></li>
</ul>
</div>
</nav>
<!-- Sidebar Footer -->
<div class="sidebar-footer">
<button (click)="logout()">Logout</button>
</div>
</ejs-sidebar>
<div class="main-content">
<div class="toolbar">
<button (click)="toggleSidebar()">☰</button>
<h1>Dashboard</h1>
</div>
</div>`,
styles: [`
.sidebar-header {
padding: 20px;
text-align: center;
border-bottom: 1px solid #e0e0e0;
}
.profile-pic {
width: 60px;
height: 60px;
border-radius: 50%;
margin-bottom: 10px;
}
.sidebar-nav {
padding: 15px 0;
}
.nav-section {
padding: 10px 0;
}
.nav-section h4 {
padding-left: 15px;
font-size: 12px;
color: #999;
text-transform: uppercase;
margin: 5px 0;
}
.nav-section ul {
list-style: none;
padding: 0;
}
.nav-section li {
padding: 0;
}
.nav-section a {
display: flex;
align-items: center;
padding: 10px 15px;
text-decoration: none;
color: #333;
transition: background 0.3s;
}
.nav-section a:hover {
background: #f5f5f5;
}
.icon {
display: inline-block;
width: 20px;
margin-right: 10px;
}
.sidebar-footer {
position: absolute;
bottom: 20px;
width: 100%;
padding: 0 15px;
box-sizing: border-box;
}
.sidebar-footer button {
width: 100%;
padding: 10px;
background: #ddd;
border: none;
border-radius: 4px;
cursor: pointer;
}
`]
})
export class CustomContentComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
logout() {
console.log('Logging out...');
this.sidebar?.hide();
}
}Target Element Configuration
The target property specifies which element to affect when sidebar opens/closes. Important: Inside the target container, you must have a wrapper div for the actual content:
@Component({
imports: [SidebarModule],
standalone: true,
template: `<ejs-sidebar id="sidebar" #sidebar
[target]="'#wrapper'"
type="Push"
(created)="onCreated($event)"
style="visibility: hidden">
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</ejs-sidebar>
<!-- Target container with inner wrapper -->
<div id="wrapper">
<div>
<div class="toolbar">
<button (click)="toggleSidebar()">☰ Menu</button>
</div>
<div class="content">
<h1>Main Content</h1>
<p>Content that moves with sidebar</p>
</div>
</div>
</div>`
})
export class TargetElementComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
}Best Practices for Target
1. Target container (id="wrapper") - Defines the area to be affected 2. Inner wrapper div - Contains actual content that moves/resizes 3. Prevents unwanted shifts - Header/footer outside target unaffected 4. Proper structure:
<ejs-sidebar [target]="'#wrapper'"></ejs-sidebar>
<div id="wrapper"> <!-- Target container -->
<div> <!-- Inner wrapper (REQUIRED) -->
<div class="content">Content</div>
</div>
</div>Complete Example: Email Application
Combine ListView with sidebar for email-like navigation. Note the target wrapper structure:
@Component({
imports: [SidebarModule, ListViewModule],
standalone: true,
selector: 'app-mail',
template: `<ejs-sidebar id="sidebar" #sidebar
[width]="'280px'"
type="Push"
[target]="'#wrapper'"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="mail-header">
<h3>Gmail</h3>
</div>
<ejs-listview [dataSource]="folders"
(select)="onFolderSelect($event)">
</ejs-listview>
</ejs-sidebar>
<!-- Target container with inner wrapper -->
<div id="wrapper">
<div>
<div class="mail-toolbar">
<button (click)="toggleSidebar()">☰</button>
<input type="text" placeholder="Search emails">
</div>
<div class="mail-list">
<div class="email-item" *ngFor="let email of emails">
<strong>{{ email.from }}</strong>
<p>{{ email.subject }}</p>
</div>
</div>
</div>
</div>`
})
export class MailApplicationComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
folders = [
{ text: 'Inbox', icon: 'e-icon-inbox' },
{ text: 'Starred', icon: 'e-icon-star' },
{ text: 'Sent', icon: 'e-icon-sent' },
{ text: 'Drafts', icon: 'e-icon-draft' },
{ text: 'Spam', icon: 'e-icon-spam' }
];
emails = [
{ from: 'John Smith', subject: 'Meeting Tomorrow' },
{ from: 'Jane Doe', subject: 'Project Update' }
];
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
onFolderSelect(args: any) {
console.log('Selected folder:', args.text);
// Load emails for selected folder
}
}Sidebar Interactions and Control Methods
Table of Contents
- Control Methods
- Show Method
- Hide Method
- Toggle Method
- Auto-Close with Media Queries
- Close on Document Click
- Backdrop Overlay
- Touch Gestures
- Events
Control Methods
ℹ️ Targeting Mode: The examples in this section use implicit targeting (sidebar automatically targets the next sibling div). This is the recommended approach for most use cases. No wrapper needed.
The Sidebar provides three main methods to control visibility. Access these methods via a @ViewChild reference to the Sidebar instance:
@ViewChild('sidebar') sidebar?: SidebarComponent;All control methods update the isOpen property internally.
Show Method
Opens the sidebar and sets isOpen to true. Useful for displaying sidebar on user actions:
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="default-sidebar" #sidebar
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Sidebar content</div>
<button (click)="closeSidebar()">Close Sidebar</button>
</ejs-sidebar>
<div>
<div class="title">Main content</div>
<button (click)="openSidebar()">Open Sidebar</button>
</div>`
})
export class ShowMethodComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
openSidebar() {
this.sidebar?.show();
}
closeSidebar() {
this.sidebar?.hide();
}
}Hide Method
Closes the sidebar and sets isOpen to false. Ideal for hiding sidebar when navigating or completing actions:
// Hide on back button click
goBack() {
this.sidebar?.hide();
this.router.navigate(['/previous-page']);
}
// Hide after navigation
navigateToPage(page: string) {
this.sidebar?.hide(); // Close sidebar
this.router.navigate([page]);
}
// Hide when selecting item
selectMenuItem(item: any) {
this.sidebar?.hide(); // Auto-close after selection
// Navigate based on item
}Toggle Method
Toggles sidebar between open and closed states. Perfect for toggle buttons:
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="default-sidebar" #sidebar
(created)="onCreated($event)"
(open)="onOpen($event)"
(close)="onClose($event)"
style="visibility: hidden">
<div class="title">Sidebar content</div>
<div class="sub-title">Click the button to close the Sidebar.</div>
<button (click)="closeSidebar()">Close Sidebar</button>
</ejs-sidebar>
<div>
<div class="title">Main content</div>
<div class="sub-title">
Click the button to open/close the Sidebar.
</div>
<button (click)="toggleSidebar()">Toggle Sidebar</button>
</div>`
})
export class ToggleMethodComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
closeSidebar() {
this.sidebar?.hide();
}
onOpen(args: any) {
console.log('Sidebar opened');
}
onClose(args: any) {
console.log('Sidebar closed');
}
}Auto-Close with Media Queries
Automatically open or close sidebar based on screen resolution using the mediaQuery property. This accepts CSS media query strings or MediaQueryList objects:
General Auto-Close Configuration
Keep sidebar open on screens wider than 600px, closed on smaller screens:
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="default-sidebar" #sidebar
[width]="'280px'"
[mediaQuery]="mediaQuery"
[closeOnDocumentClick]="true">
<div class="title">Sidebar content</div>
</ejs-sidebar>
<div>
<div class="title">Main content</div>
<p>Sidebar auto-opens on screens wider than 600px</p>
</div>`
})
export class AutoCloseComponent {
public mediaQuery: object = window.matchMedia('(min-width: 600px)');
}Sidebar Open Only on Small Screens
Keep sidebar expanded only below 400px (e.g., for very small devices):
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="default-sidebar" #sidebar
[width]="'280px'"
[mediaQuery]="mediaQuery"
[isOpen]="true"
[closeOnDocumentClick]="true">
<div class="title">Sidebar content</div>
</ejs-sidebar>
<div>
<div class="title">Main content</div>
<p>Sidebar only expanded below 400px width</p>
</div>`
})
export class SmallScreenComponent {
public mediaQuery: object = window.matchMedia('(max-width: 400px)');
}Common Media Query Patterns
// Desktop-only (expanded on large screens)
mediaQuery = window.matchMedia('(min-width: 1200px)');
// Tablet and above
mediaQuery = window.matchMedia('(min-width: 768px)');
// Mobile only
mediaQuery = window.matchMedia('(max-width: 767px)');
// Landscape only
mediaQuery = window.matchMedia('(orientation: landscape)');
// Landscape and tablet
mediaQuery = window.matchMedia('(min-width: 768px) and (orientation: landscape)');Close on Document Click
Close sidebar when clicking outside of it using closeOnDocumentClick property. Useful for dropdown-style sidebars:
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="default-sidebar" #sidebar
[isOpen]="true"
[closeOnDocumentClick]="true"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Sidebar content</div>
</ejs-sidebar>
<div>
<div class="title">Main content</div>
<p>Click outside the sidebar to close it</p>
<button (click)="toggleSidebar()">Toggle</button>
</div>`
})
export class CloseOnClickComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
}Backdrop Overlay
Display a semi-transparent overlay on main content to focus on sidebar. Enabled with showBackdrop property:
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons';
@Component({
imports: [SidebarModule, ButtonModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="default-sidebar" #sidebar
[width]="'280px'"
[showBackdrop]="true"
[closeOnDocumentClick]="true"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Sidebar content</div>
<div class="sub-title">
Click outside or on backdrop to close
</div>
<button ejs-button (click)="closeClick()">Close Sidebar</button>
</ejs-sidebar>
<div>
<div class="title">Main content</div>
<div class="sub-title">
Click the button to open/close the Sidebar with backdrop.
</div>
<button ejs-button (click)="toggleClick()">Toggle Sidebar</button>
</div>`
})
export class BackdropComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleClick() {
this.sidebar?.toggle();
}
closeClick() {
this.sidebar?.hide();
}
}Backdrop Best Practices
Use a wrapper container as the sidebar's target to achieve proper backdrop:
template: `<ejs-sidebar id="sidebar"
[target]="'#wrapper'"
[showBackdrop]="true">
</ejs-sidebar>
<div id="wrapper">
<!-- Main content with backdrop overlay -->
</div>`Touch Gestures
Enable swipe gestures to open/close sidebar on touch devices using enableGestures property (enabled by default):
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="default-sidebar" #sidebar
[enableGestures]="enableGestures"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Sidebar content</div>
<div class="sub-title">
Swipe from left edge to open on touch devices
</div>
<button (click)="closeClick()">Close Sidebar</button>
</ejs-sidebar>
<div>
<div class="title">Main content</div>
<div class="sub-title">
Swipe from left edge (or toggle button) to open Sidebar.
</div>
<button (click)="toggleClick()">Toggle Sidebar</button>
</div>`
})
export class GesturesComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
public enableGestures: boolean = false; // Disabled in example, enable to true for production
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleClick() {
this.sidebar?.toggle();
}
closeClick() {
this.sidebar?.hide();
}
}Note: By default, enableGestures is true. Set to false to disable gesture support.
Events
Handle sidebar state changes with open and close events:
@Component({
imports: [SidebarModule],
standalone: true,
template: `<ejs-sidebar id="sidebar" #sidebar
(open)="onOpen($event)"
(close)="onClose($event)"
(change)="onChange($event)">
</ejs-sidebar>`
})
export class EventsComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onOpen(args: any) {
console.log('Sidebar opened', args);
// Perform actions on open
}
onClose(args: any) {
console.log('Sidebar closed', args);
// Perform cleanup on close
}
onChange(args: any) {
console.log('Sidebar state changed');
console.log('Event name:', args.name);
console.log('Element:', args.element);
// React to state changes
}
}Complete Example: Navigation Drawer
Combine multiple interaction features:
@Component({
imports: [SidebarModule, ButtonModule],
standalone: true,
selector: 'app-navbar',
template: `<ejs-sidebar #sidebar
type="Push"
[showBackdrop]="true"
[closeOnDocumentClick]="true"
[enableGestures]="true"
[mediaQuery]="mediaQuery"
(created)="onCreated($event)"
style="visibility: hidden">
<ul class="nav-items">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</ejs-sidebar>
<div class="navbar">
<button (click)="toggleMenu()">Menu</button>
</div>`
})
export class NavbarComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
mediaQuery = window.matchMedia('(max-width: 768px)');
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleMenu() {
this.sidebar?.toggle();
}
}Sidebar Positioning and Behavior Types
Table of Contents
- Sidebar Expand Types
- Push Type
- Slide Type
- Over Type
- Auto Type
- Sidebar Positioning
- Fixed Positioning
- Docking
- Multiple Sidebars
Understanding Target Behavior
Implicit vs Explicit Targeting
Implicit (Default - No target property):
- Sidebar automatically targets the next sibling `<div>` element immediately after it
- Simpler structure, no wrapper needed
- Perfect for straightforward layouts
Explicit (With target property):
- Sidebar targets a specific element by ID or class (e.g.,
[target]="'#wrapper'") - Requires inner wrapper `<div>` inside target for CSS transforms to work properly
- Provides precise control over which elements are affected
---
Sidebar Expand Types
The type property controls how the sidebar interacts with main content when expanding or collapsing. Choose based on your layout requirements.
| Type | Description | Use Case |
|---|---|---|
| Push | Sidebar pushes main content aside, shrinking it within screen width | Traditional navigation menus |
| Slide | Sidebar shifts main content position without resizing | Overlay-like behavior with shift |
| Over | Sidebar floats over main content without affecting layout | Floating panel, modal-like navigation |
| Auto | Over on mobile (≤600px), Push on desktop | Responsive default behavior |
Push Type - Implicit Targeting (Recommended)
Sidebar pushes main content to the side and shrinks it to fit the screen. No target property needed - sidebar automatically targets the next sibling <div>:
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
imports: [SidebarModule],
standalone: true,
selector: 'app-root',
template: `<ejs-sidebar id="sidebar" #sidebar
type="Push"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Sidebar</div>
<button (click)="closeSidebar()">Close</button>
</ejs-sidebar>
<!-- This div automatically becomes the target -->
<div>
<button (click)="toggleSidebar()">Toggle</button>
<div class="main-content">Main content resizes with sidebar</div>
</div>`
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
closeSidebar() {
this.sidebar?.hide();
}
}Push Type - Explicit Targeting (Advanced)
When you need precise control over which element the sidebar affects, use explicit target property with a wrapper:
@Component({
template: `<ejs-sidebar id="sidebar" #sidebar
type="Push"
[target]="'#content-wrapper'"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Sidebar</div>
</ejs-sidebar>
<!-- Explicit target container -->
<div id="content-wrapper">
<!-- REQUIRED: Inner wrapper for transforms -->
<div>
<button (click)="toggleSidebar()">Toggle</button>
<div class="main-content">Resizes with sidebar</div>
</div>
</div>`
})
export class ExplicitTargetComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
}Slide Type - Implicit Targeting
Sidebar shifts content without resizing. Content moves with sidebar but maintains full width. Sidebar automatically targets the next sibling `<div>`:
@Component({
template: `<ejs-sidebar id="sidebar" #sidebar
type="Slide"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Sidebar (Slide Type)</div>
</ejs-sidebar>
<!-- Automatically becomes the target -->
<div>
<button (click)="toggleSidebar()">Toggle</button>
<div>Content shifts position without resizing</div>
</div>`
})
export class SlideTypeComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
}Over Type - No Layout Changes
Sidebar floats over main content with no layout changes. No target property needed - sidebar appears on top without affecting layout:
@Component({
template: `<ejs-sidebar id="sidebar" #sidebar
type="Over"
[showBackdrop]="true"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Sidebar (Over Type)</div>
</ejs-sidebar>
<div>
<button (click)="toggleSidebar()">Toggle</button>
Content remains unchanged when sidebar opens
</div>`
})
export class OverTypeComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
}Note: Over type doesn't need explicit target because it doesn't affect content layout. The showBackdrop adds overlay to the automatically targeted sibling element.
Auto Type (Default)
Automatically uses Over type on mobile (≤600px) and Push on larger screens. This is the default and recommended for responsive apps:
@Component({
template: `<ejs-sidebar id="sidebar" #sidebar
type="Auto"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Sidebar (Auto Type)</div>
</ejs-sidebar>
<div>
<button (click)="toggleSidebar()">Toggle</button>
Responsive: Over on mobile, Push on desktop
</div>`
})
export class AutoTypeComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
}Sidebar Positioning
Position Left (Default)
Sidebar expands from the left side:
@Component({
template: `<ejs-sidebar #sidebar
position="Left"
type="Push">
</ejs-sidebar>`
})
export class LeftPositionComponent { }Position Right
Sidebar expands from the right side, ideal for RTL applications:
@Component({
template: `<ejs-sidebar #sidebar
position="Right"
type="Push"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Right Sidebar</div>
</ejs-sidebar>
<div>
<button (click)="toggleSidebar()">Toggle</button>
</div>`
})
export class RightPositionComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
}Top/Bottom Positioning
Position sidebar at top or bottom (less common but supported):
// Top sidebar (e.g., horizontal navigation)
<ejs-sidebar position="Top" type="Push" [width]="'100%'" [height]="'60px'">
</ejs-sidebar>
// Bottom sidebar (e.g., bottom navigation)
<ejs-sidebar position="Bottom" type="Push" [width]="'100%'" [height]="'60px'">
</ejs-sidebar>Fixed Positioning
By default, sidebars use fixed positioning and don't move when main content scrolls. This is ideal for persistent navigation:
@Component({
selector: 'app-root',
template: `<ejs-sidebar id="sidebar" #sidebar
type="Push"
[width]="'290px'"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="sidebar-header">Header</div>
<ul class="nav">
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
</ul>
</ejs-sidebar>
<div id="wrapper">
<div class="toolbar">
<span (click)="toggleSidebar()" class="menu-icon">☰</span>
</div>
<div class="content">
<!-- Scrollable content -->
<div style="height: 2000px">Long content area...</div>
</div>
</div>`,
styles: [`
:host ::ng-deep {
#sidebar { position: fixed; }
.content { overflow-y: auto; }
}
`]
})
export class FixedSidebarComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
}Docking
Docking creates a compact, always-visible portion of the sidebar (usually showing icons) that expands on interaction. Enabled with enableDock and dockSize properties:
@Component({
imports: [SidebarModule],
standalone: true,
template: `<ejs-sidebar #dockBar
id="dockSidebar"
[enableDock]="true"
[width]="'220px'"
[dockSize]="'72px'"
(created)="onCreated($event)">
<div class="dock">
<ul>
<li (click)="toggleClick()" title="Menu">
<span class="e-icons expand"></span>
<span class="e-text">Menu</span>
</li>
<li title="Home">
<span class="e-icons home"></span>
<span class="e-text">Home</span>
</li>
<li title="Profile">
<span class="e-icons profile"></span>
<span class="e-text">Profile</span>
</li>
<li title="Settings">
<span class="e-icons settings"></span>
<span class="e-text">Settings</span>
</li>
</ul>
</div>
</ejs-sidebar>
<div class="main-content">
<div class="title">Main content</div>
Click the expand icon to open/close the Sidebar
</div>`
})
export class DockingComponent {
@ViewChild('dockBar') dockBar?: SidebarComponent;
onCreated(args: any) {
(this.dockBar as SidebarComponent).element.style.visibility = '';
}
toggleClick() {
this.dockBar?.toggle();
}
}CSS for Docking
Hide text when docked (closed):
.e-dock.e-close span.e-text {
display: none;
}
.e-dock.e-open span.e-text {
display: inline-block;
}Multiple Sidebars
Create multiple sidebars (left and right) on the same page:
@Component({
imports: [SidebarModule],
standalone: true,
template: `<!-- Left Sidebar -->
<ejs-sidebar #leftSidebar
id="left-sidebar"
position="Left"
type="Push"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Left Sidebar</div>
</ejs-sidebar>
<!-- Right Sidebar -->
<ejs-sidebar #rightSidebar
id="right-sidebar"
position="Right"
type="Push"
(created)="onCreated($event)"
style="visibility: hidden">
<div class="title">Right Sidebar</div>
</ejs-sidebar>
<!-- Main Content -->
<div class="main-content">
<button (click)="toggleLeft()">Toggle Left</button>
<button (click)="toggleRight()">Toggle Right</button>
<div class="content">Main Content Area</div>
</div>`
})
export class MultipleSidebarsComponent {
@ViewChild('leftSidebar') leftSidebar?: SidebarComponent;
@ViewChild('rightSidebar') rightSidebar?: SidebarComponent;
onCreated(args: any) {
if (args.target?.id === 'left-sidebar') {
(this.leftSidebar as SidebarComponent).element.style.visibility = '';
}
if (args.target?.id === 'right-sidebar') {
(this.rightSidebar as SidebarComponent).element.style.visibility = '';
}
}
toggleLeft() {
this.leftSidebar?.toggle();
}
toggleRight() {
this.rightSidebar?.toggle();
}
}DataBind Method
Apply pending property changes immediately using dataBind():
// Change type dynamically
changeType(newType: string) {
if (this.sidebar) {
(this.sidebar as SidebarComponent).type = newType;
(this.sidebar as SidebarComponent).dataBind(); // Apply changes
}
}Target Property - When and How to Use
Default Behavior (No target property)
When you DON'T specify a target property, the sidebar automatically targets the next sibling `<div>` element:
// Implicit targeting - Simple and recommended
<ejs-sidebar id="sidebar" type="Push"></ejs-sidebar>
<div> <!-- Automatically becomes target -->
<div class="title">Main content</div>
<div class="sub-title">
Click the button to close the Sidebar.
</div>
</div>✅ Advantages:
- Simple structure, no wrapper needed
- Sidebar automatically targets next sibling
- Perfect for straightforward layouts
- Recommended for most use cases
---
Explicit Targeting (With target property)
When you need precise control over which element is affected, use the target property:
// Explicit targeting - Precise control
<ejs-sidebar [target]="'#content-area'" type="Push"></ejs-sidebar>
<div id="content-area"> <!-- Explicit target container -->
<div> <!-- REQUIRED: Inner wrapper -->
<div class="title">Main content</div>
<div class="sub-title">
Click the button to close the Sidebar.
</div>
</div>
</div>IMPORTANT: When using explicit target, you MUST include an inner wrapper <div> inside the target container:
// ❌ INCORRECT - No wrapper inside target
<ejs-sidebar [target]="'#wrapper'"></ejs-sidebar>
<div id="wrapper">
<div class="content">Content won't transform properly</div>
</div>
// ✅ CORRECT - Wrapper div inside target container
<ejs-sidebar [target]="'#wrapper'"></ejs-sidebar>
<div id="wrapper">
<div> <!-- Required inner wrapper -->
<div class="content">Content transforms correctly</div>
</div>
</div>---
Why Wrapper Needed with Explicit target
When you explicitly set a target, the sidebar applies CSS transforms to the direct child of the target container. The wrapper div is what actually moves/resizes.
Use explicit targeting when:
- You want to exclude certain elements (header, footer) from the sidebar effect
- You have complex layouts with multiple sections
- You need fine-grained control over which content responds to sidebar state
- You want different sidebars affecting different sections
Use implicit targeting (no target) when:
- Simple layout with one main content area
- You want sidebar to affect all content after it
- You prefer simpler, cleaner code
Edge Cases
Responsive Behavior: Use Auto type or mediaQuery to handle different screen sizes automatically.
Content Wrapping: Always wrap content in target with an inner div for proper push/slide behavior.
Overflow Management: For tall sidebars, add overflow-y: auto to CSS for scrollable content.
Multiple Targets: Use different target selectors for different sidebars if needed.
SystemJS Setup for Syncfusion Angular Sidebar
Table of Contents
- Overview
- Installation and Configuration
- SystemJS Configuration
- Adding Styles
- Creating a Sidebar Component
- Running the Application
- Comparison: SystemJS vs Angular CLI
Overview
SystemJS is an alternative module loader for Angular applications that provides dynamic module loading and development flexibility. While modern Angular projects typically use Webpack (via Angular CLI), SystemJS remains a valid option for specific use cases:
- Legacy projects using SystemJS
- Development environments preferring dynamic module loading
- Projects requiring UMD bundle support
- Alternative build tooling workflows
⚠️ Note: Angular CLI is the recommended and modern approach for new projects. Use SystemJS only if you have specific requirements or legacy constraints.
Installation and Configuration
Step 1: Clone Angular QuickStart Repository
The Angular QuickStart repository provides a pre-configured SystemJS setup:
git clone https://github.com/angular/quickstart.git quickstart
cd quickstart
npm installThis sets up the basic Angular environment with SystemJS already configured.
Step 2: Install Syncfusion Sidebar Package
Install the Syncfusion Angular Navigations package that includes the Sidebar component:
npm install @syncfusion/ej2-angular-navigations --saveThis command installs:
@syncfusion/ej2-angular-navigations- Sidebar and Navigation components@syncfusion/ej2-base- Base utilities and classes@syncfusion/ej2-data- Data management services@syncfusion/ej2-angular-base- Angular-specific wrappers- Other dependent packages
All packages are installed with UMD bundles compatible with SystemJS.
SystemJS Configuration
Configure systemjs.config.js
The systemjs.config.js file in your project root tells SystemJS how to load modules. Add mappings for Syncfusion packages:
/**
* System configuration for Angular samples
* Adjust as necessary for your application needs.
*/
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/',
"syncfusion:": "node_modules/@syncfusion/", // Syncfusion alias
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
'app': 'app',
// Angular bundles - UMD format
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
// Syncfusion bundles - UMD format
"@syncfusion/ej2-base": "syncfusion:ej2-base/dist/ej2-base.umd.min.js",
"@syncfusion/ej2-data": "syncfusion:ej2-data/dist/ej2-data.umd.min.js",
"@syncfusion/ej2-navigations": "syncfusion:ej2-navigations/dist/ej2-navigations.umd.min.js",
"@syncfusion/ej2-inputs": "syncfusion:ej2-inputs/dist/ej2-inputs.umd.min.js",
"@syncfusion/ej2-lists": "syncfusion:ej2-lists/dist/ej2-lists.umd.min.js",
"@syncfusion/ej2-popups": "syncfusion:ej2-popups/dist/ej2-popups.umd.min.js",
"@syncfusion/ej2-buttons": "syncfusion:ej2-buttons/dist/ej2-buttons.umd.min.js",
"@syncfusion/ej2-splitbuttons": "syncfusion:ej2-splitbuttons/dist/ej2-splitbuttons.umd.min.js",
"@syncfusion/ej2-angular-base": "syncfusion:ej2-angular-base/dist/ej2-angular-base.umd.min.js",
"@syncfusion/ej2-angular-navigations": "syncfusion:ej2-angular-navigations/dist/ej2-angular-navigations.umd.min.js",
// other libraries
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
defaultExtension: 'js',
meta: {
'./*.js': {
loader: 'systemjs-angular-loader.js'
}
}
},
rxjs: {
defaultExtension: 'js'
}
}
});
})(this);Key Configuration Points
| Element | Purpose |
|---|---|
paths | Create aliases for commonly used folders (npm:, syncfusion:) |
map | Map module names to their physical locations in node_modules |
packages | Define how specific packages should be loaded |
| Syncfusion UMD paths | Point to pre-built .umd.min.js files in each package |
Adding Styles
Import Syncfusion CSS themes in your main styles.css file:
/* Material3 theme for Syncfusion components */
@import '../../node_modules/@syncfusion/ej2-base/styles/material3.css';
/* Navigation components theme (includes Sidebar) */
@import '../../node_modules/@syncfusion/ej2-angular-navigations/styles/material3.css';Available Themes
Replace material3 with your preferred theme:
material- Material Designmaterial3- Material Design 3bootstrap- Bootstrap Themebootstrap5- Bootstrap 5 Themefluent- Fluent Designtailwind- Tailwind CSS Themehighcontrast- High Contrast Theme
Using Custom Resource Generator (CRG)
For combined component styles and reduced file size, use Syncfusion CRG:
1. Select components and themes you need 2. Download the combined CSS file 3. Add to your project and reference instead of individual imports
Creating a Sidebar Component
Step 1: Create Component Template
Create the Sidebar component in your app.component.ts:
import { Component, ViewChild } from '@angular/core';
import { SidebarComponent } from '@syncfusion/ej2-angular-navigations';
@Component({
selector: 'app-root',
styleUrls: ['./app.component.css'],
template: `
<ejs-sidebar
id="default-sidebar"
#sidebar
(created)="onCreated($event)"
style="visibility: hidden">
<div class="sidebar-header">
<h3>Navigation</h3>
</div>
<ul class="sidebar-menu">
<li><a href="#">Home</a></li>
<li><a href="#">Products</a></li>
<li><a href="#">Settings</a></li>
<li><a href="#">About</a></li>
</ul>
</ejs-sidebar>
<div>
<div class="topbar">
<button (click)="toggleSidebar()">☰ Menu</button>
<h2>Main Content</h2>
</div>
<div class="content">
<p>Welcome to Sidebar with SystemJS</p>
<p>Click the menu button to toggle the sidebar.</p>
</div>
</div>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
@ViewChild('sidebar') sidebar?: SidebarComponent;
onCreated(args: any) {
// Make sidebar visible after creation
(this.sidebar as SidebarComponent).element.style.visibility = '';
}
toggleSidebar() {
this.sidebar?.toggle();
}
}Step 2: Add Component Styles
Create app.component.css:
.topbar {
display: flex;
align-items: center;
gap: 15px;
padding: 15px 20px;
background-color: #f5f5f5;
border-bottom: 1px solid #ddd;
}
.topbar button {
padding: 8px 12px;
font-size: 18px;
border: none;
background-color: #007bff;
color: white;
border-radius: 4px;
cursor: pointer;
}
.topbar button:hover {
background-color: #0056b3;
}
.content {
padding: 30px;
font-size: 16px;
}
.sidebar-header {
padding: 20px;
border-bottom: 1px solid #e0e0e0;
background-color: #f9f9f9;
}
.sidebar-header h3 {
margin: 0;
font-size: 18px;
}
.sidebar-menu {
list-style: none;
margin: 0;
padding: 10px 0;
}
.sidebar-menu li {
padding: 0;
}
.sidebar-menu a {
display: block;
padding: 12px 20px;
text-decoration: none;
color: #333;
border-bottom: 1px solid #f0f0f0;
transition: background-color 0.2s;
}
.sidebar-menu a:hover {
background-color: #f5f5f5;
}Step 3: Create AppModule
Create the Angular module in app.module.ts:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { AppComponent } from './app.component';
@NgModule({
imports: [
BrowserModule,
SidebarModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }Step 4: Create Main Entry Point
Create main.ts:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));Step 5: Create HTML Host File
Create index.html in the project root:
<!DOCTYPE html>
<html>
<head>
<title>Syncfusion Sidebar with SystemJS</title>
<base href="/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Syncfusion Styles -->
<link rel="stylesheet" href="styles.css">
<!-- Zone.js for Angular -->
<script src="node_modules/zone.js/bundles/zone.umd.js"></script>
</head>
<body>
<app-root></app-root>
<!-- SystemJS Configuration -->
<script src="systemjs.config.js"></script>
<!-- Bootstrap the Angular Module -->
<script>
System.import('app').catch(function(err) {
console.error(err);
});
</script>
</body>
</html>Running the Application
Development Server
Start the development server using npm:
npm startThis command:
- Starts a local web server (typically http://localhost:3000)
- Watches for file changes
- Automatically reloads the browser when changes are detected
- Shows compilation errors in console
Access the Application
Open your browser and navigate to:
http://localhost:3000You should see:
- A topbar with "Menu" button
- A sidebar that toggles when you click the button
- Main content area with welcome text
Build for Production
Create an optimized build:
npm run buildThis creates production-ready files in the dist/ folder.
Comparison: SystemJS vs Angular CLI
SystemJS
| Aspect | Details |
|---|---|
| Setup | Clone QuickStart, configure systemjs.config.js |
| Module Loading | Dynamic module loading at runtime |
| Bundle Format | UMD (Universal Module Definition) |
| Development | Fast reload with System.import() |
| Bundle Size | Larger (UMD bundles unoptimized) |
| Production | Requires manual bundling and optimization |
| Modern Support | Limited, older Angular versions |
| Learning Curve | More manual configuration |
Angular CLI (Recommended)
| Aspect | Details |
|---|---|
| Setup | ng new command, automated setup |
| Module Loading | Webpack-based static module bundling |
| Bundle Format | ES Modules with tree-shaking |
| Development | Fast rebuild with ng serve |
| Bundle Size | Optimized with tree-shaking |
| Production | Automated production optimization |
| Modern Support | Full support for latest Angular |
| Learning Curve | Convention-based, less configuration |
When to Use Each
Use SystemJS when:
- Working with legacy projects already using SystemJS
- Requiring dynamic module loading capabilities
- Need quick development iteration with hot reload
- Working with specific hosting constraints
Use Angular CLI when:
- Starting new projects (default choice)
- Need modern tooling and optimization
- Want automated build and deployment
- Building production applications
- Team is using Angular CLI standards
Next Steps
After setting up SystemJS:
1. Customize the Sidebar - Explore different sidebar types (Push, Slide, Over) from Sidebar Positioning Guide 2. Add Content - Use ListView or TreeView for structured navigation from Sidebar Content Guide 3. Configure Interactions - Control behavior with show(), hide(), toggle() from Sidebar Interactions Guide 4. Apply Animations - Add visual effects from Animations and Styling Guide 5. Troubleshoot Issues - Refer to Advanced Features Guide for common problems
Related References
- Angular CLI Setup (Recommended) - Modern approach using Angular CLI
- Sidebar Positioning - Explore different sidebar types and positions
- Sidebar Interactions - Control methods and event handling
- Official Angular SystemJS Guide - Angular documentation
- SystemJS Official Repository - SystemJS project
Troubleshooting
Module Not Found Errors
Problem: System.import() fails with "module not found"
Solution:
- Verify all Syncfusion modules are mapped in
systemjs.config.js - Check that npm packages are installed:
npm install - Ensure paths in systemjs.config.js match actual node_modules structure
Styles Not Loading
Problem: Sidebar appears unstyled or broken
Solution:
- Verify CSS imports in
styles.cssare correct - Check that theme files exist in node_modules
- Use browser DevTools to confirm CSS files are loaded
- Verify
<link>tag references correct path
Sidebar Not Displaying
Problem: Sidebar div or content doesn't appear
Solution:
- Check that
style="visibility: hidden"is set andonCreated()removes it - Verify SidebarModule is imported in AppModule
- Check browser console for JavaScript errors
- Confirm Sidebar component template is in app.component.ts
Port Already in Use
Problem: npm start fails - port 3000 already in use
Solution:
# Kill process on port 3000 (Windows PowerShell)
Get-Process -Id (Get-NetTCPConnection -LocalPort 3000).OwningProcess | Stop-Process
# Or specify different port
npm start -- --port 3001