
Syncfusion Angular File Manager
- 214 installs
- Updated August 4, 2026
- syncfusion/angular-ui-components-skills
Use syncfusion-angular-file-manager for development tasks
About
syncfusion-angular-file-manager: A skill for development. This provides functionality for development workflows.
- syncfusion-angular-file-manager
Syncfusion Angular File Manager by the numbers
- 214 all-time installs (skills.sh)
- +11 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,879 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/angular-ui-components-skills --skill syncfusion-angular-file-managerAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 214 |
|---|---|
| Last updated | August 4, 2026 |
| Repository | syncfusion/angular-ui-components-skills ↗ |
What it does
Use syncfusion-angular-file-manager for development tasks
Files
Implementing the Syncfusion Angular File Manager Component
The File Manager is a powerful graphical user interface component for managing file systems. It enables users to perform essential file operations—accessing, editing, sorting, uploading, downloading, and organizing files and folders—with an intuitive interface and comprehensive navigation functionality.
When to Use This Skill
Use the File Manager component when you need to:
- Browse and navigate files and folders in a file system
- Perform file operations (create, delete, rename, upload, download)
- Display files in different view modes (details view, large icons view)
- Implement drag-and-drop file management
- Handle large file sets efficiently with virtualization
- Customize toolbar, context menu, and file display
- Support multi-selection, sorting, and localization
Component Overview & Key Features
Core Capabilities
- File Operations: Read, create, delete, rename, upload, download files
- Navigation: Breadcrumb navigation, navigation pane, folder hierarchy
- View Options: Details view (sorted list) and Large Icons view (thumbnail display)
- User Interaction: Multi-selection, drag-and-drop, right-click context menu
- Performance: UI virtualization for large file sets, state persistence
- Customization: Toolbar/context menu customization, CSS theming, custom icons
- Accessibility: RTL support, localization, ARIA attributes
Architecture
- Server-based file operations via
ajaxSettings - Or client-side data binding with
fileSystemData(flat or nested JSON) - Feature modules: Navigation Pane, Toolbar, Details View, Virtualization
- Event-driven architecture for custom workflows
Documentation and Navigation Guide
API Reference (Start Here for API Details)
📄 Read: references/api-reference-complete.md
- Complete component properties with descriptions
- FileData interface for client-side binding
- Configuration models and best practices
- Service providers and utility functions
Methods and Events Reference
📄 Read: references/methods-and-events.md
- Complete list of all component methods with examples
- All component events with event arguments
- Event parameter interfaces and descriptions
- Practical examples for each method and event
Getting Started
📄 Read: references/getting-started.md
- Prerequisites (Angular 4+, TypeScript 2.6+)
- Angular project setup and CLI commands
- Package installation (Ivy vs ngcc compatibility)
- CSS theme imports and styling
- Basic component initialization
- ajaxSettings configuration (file operations, download, upload, preview URLs)
- Initial view and component rendering
File Operations
📄 Read: references/file-operations.md
- Core operations: read, create, delete, rename, upload, download, copy, move
- File system provider configuration
- Server integration patterns
- Custom file providers (Google Drive, Amazon S3, Azure)
- Directory upload support
- Error handling and validation
- Request/response patterns
Request and Response Parameters
📄 Read: references/request-response-parameters-reference.md
- Complete response parameters for ALL 11 operations
- Request structure and parameters for each operation
- Response format and structure specifications
- FileManagerDirectoryContent interface definition
- DetailsObject and error response formats
- Request/response examples for every operation
- Error codes and error handling patterns
- Common data structures and interfaces
- Best practices for backend implementation
Upload Customizations
📄 Read: references/upload-customizations.md
- Directory upload configuration (directoryUpload property)
- Sequential upload setup (sequentialUpload property)
- Chunk upload for large files (chunkSize configuration)
- Auto-upload behavior control
- File size validation (minFileSize, maxFileSize)
- File type restrictions (allowedExtensions)
- Upload events (beforeSend, onSuccess, onFailure)
- Backend implementation examples (ASP.NET Core)
- 3 practical examples covering image-only, document, and complete upload configs
Views and Layout
📄 Read: references/views-and-layout.md
- Details view (sorted file list with columns)
- Large Icons view (thumbnail display)
- Switching views dynamically or at initialization
- Initial view configuration
- CSS class customization for styling
- View-specific settings and configurations
Navigation Features
📄 Read: references/navigation-features.md
- Breadcrumb navigation (folder hierarchy tracking)
- Navigation pane configuration (left sidebar with folder tree)
- Path specification and dynamic navigation
- Folder hierarchy traversal
- Showing/hiding navigation elements
Data Structures
📄 Read: references/data-structures.md
- Flat JSON data binding (no backend required)
- Nested items (folder hierarchies in local data)
- fileData interface and properties (name, size, date, isFile, hasChild, etc.)
- Parent-child relationships via parentId
- Flat vs nested approaches and trade-offs
- Server-based vs client-side data
Nested Items Integration
📄 Read: references/nested-items-integration.md
- Dialog nesting with file selection pattern
- Tab nesting (multiple File Managers per tab)
- Splitter nesting (side-by-side layout)
- Accordion nesting (categorized file access)
- Managing multiple nested File Manager state
- Height calculation strategies
- Dimension management best practices
- 2 practical examples: file upload dialog, tabbed file management
Drag and Drop
📄 Read: references/drag-and-drop.md
- Enabling drag-and-drop functionality
- Drop target configuration
- File move operations via dragging
- Drag event handling (fileDragStart, fileDragging, fileDragStop, fileDropped)
- Constraints and drop restrictions
- Visual feedback during drag operations
Virtualization
📄 Read: references/virtualization.md
- What is UI virtualization and performance benefits
- Module injection (VirtualizationService)
- Enabling virtualization (enableVirtualization property)
- Handling large file sets (100s-1000s of files)
- Memory optimization and scrolling performance
- Virtual scrolling in details and large icons views
Sorting and Filtering
📄 Read: references/sorting-and-filtering.md
- Custom sorting via sortComparer function
- Natural sorting (like Windows Explorer)
- Sort orders (ascending/descending)
- Multi-column sorting in details view
- Column-specific sortComparer definitions
- Imported sortComparer utility or custom implementations
Toolbar Customization
📄 Read: references/toolbar-customization.md
- Toolbar configuration and items
- Default toolbar items (NewFolder, Upload, View, Refresh, Cut, Copy, Paste, Delete, Download, Rename)
- Adding custom toolbar items with templates
- Modifying toolbar item properties
- Toolbar icons (Syncfusion, Font Awesome, custom SVG)
- Template-based toolbar items (checkboxes, dropdowns)
- Toolbar click events and event handling
- Conditional toolbar items based on selection
Context Menu Customization
📄 Read: references/context-menu-customization.md
- Default context menu items (Open, Cut, Copy, Paste, Delete, Rename, Download)
- Adding custom context menu items
- Context menu configuration for files, folders, and layout
- Menu events (menuOpen, menuClose, menuClick)
- Dynamic menu modification and conditional items
- Adding icons to menu items
- Custom menu actions and implementations
- Submenu support
Access Control and Permissions
📄 Read: references/access-control-and-permissions.md
- Permission model and FileData permission structure
- Implementing role-based access control (RBAC)
- File-level and folder-level permissions
- Backend permission rules configuration
- Access rules with Permission enumeration (Allow/Deny)
- Frontend permission handling and UI disabling
- Administrator, Editor, and Viewer role examples
- Audit logging and compliance
Authentication and Custom Values
📄 Read: references/authentication-and-custom-values.md
- beforeSend event for adding authentication headers
- JWT token authentication implementation
- Bearer token patterns
- Custom headers (API keys, request IDs, correlation IDs)
- Custom data passing with requests
- Query parameters and body data
- CORS configuration and cross-origin requests
- OAuth2 token refresh patterns
- Multi-tenant file manager setup
- Audit trail and request logging
Custom File Providers
📄 Read: references/custom-file-provider.md
- Custom file provider architecture
- Required API endpoints (FileOperations, Upload, Download, GetImage)
- Request/response format specifications
- ASP.NET Core custom backend implementation
- Azure Blob Storage integration
- AWS S3 integration
- Database-backed file system (SQL)
- Google Drive and cloud storage patterns
- Implementing ICustomFileService interface
Advanced Features
📄 Read: references/advanced-features.md
- Multi-selection of files and folders
- State persistence (enablePersistence property)
- Maintaining view, path, and selected items across page reload
- Ajax events (success, failure)
- Component lifecycle (created event)
- Refresh file operations programmatically
- Multiple file selection with bulk operations
UI Customizations
📄 Read: references/ui-customizations.md
- Large icon customization (size, layout, styling)
- Custom file type icons mapping
- showFileExtension property and dynamic control
- showHiddenItems configuration with server-side filtering
- Tooltip customization with file information
- allowMultiSelection control with single/multi toggle
- Multi-selection limitation patterns
- showThumbnail: Control thumbnail display (performance tuning for large collections)
- showItemCheckBoxes: Enable selection checkboxes (mobile-friendly & accessibility)
- enableHtmlSanitizer: Security property to prevent XSS attacks (CRITICAL: keep enabled)
- popupTarget: Specify popup/dialog container (required for nested File Managers)
- 15+ working code examples with CSS patterns and advanced configurations
- Complete UI customization examples
Navigation Items Customization
📄 Read: references/navigation-items-customization.md
- navigationPaneTemplate basic and advanced usage
- Custom item rendering with hierarchical styling
- Icon and badge integration patterns
- CSS styling approaches for navigation items
- Dynamic theme application (light/dark toggle)
- Path-based icon customization
- Professional navigation design patterns
- 1 comprehensive professional navigation example
Customization and Styling
📄 Read: references/customization-styling.md
- CSS class customization (cssClass property)
- Theme customization and Theme Studio integration
- Custom thumbnails (showThumbnail property)
- Custom icon display for files and folders
- Responsive design and container sizing
- Advanced styling examples
- CSS variable overrides
Localization and RTL
📄 Read: references/localization-and-rtl.md
- Right-to-left (RTL) language support (enableRtl property)
- Localization library (l10) integration
- Language configuration and switching
- Custom text and message localization
- Regional date/time formatting
Quick Start Example
Basic File Manager Setup
import { Component } from '@angular/core';
import { FileManagerModule, NavigationPaneService, ToolbarService, DetailsViewService } from '@syncfusion/ej2-angular-filemanager';
@Component({
imports: [FileManagerModule],
providers: [NavigationPaneService, ToolbarService, DetailsViewService],
standalone: true,
selector: 'app-root',
template: `<ejs-filemanager
id='file-manager'
[ajaxSettings]='ajaxSettings'
height="500px">
</ejs-filemanager>`
})
export class AppComponent {
public ajaxSettings = {
url: 'url',
getImageUrl: 'url',
uploadUrl: 'url',
downloadUrl: 'url'
};
}With Local JSON Data (No Backend)
import { Component } from '@angular/core';
import { FileManagerModule } from '@syncfusion/ej2-angular-filemanager';
import { FileData } from '@syncfusion/ej2-filemanager';
@Component({
imports: [FileManagerModule],
standalone: true,
selector: 'app-root',
template: `<ejs-filemanager
id='file-manager'
[fileSystemData]='fileData'
height="500px">
</ejs-filemanager>`
})
export class AppComponent {
public fileData: { [key: string]: Object }[] = [
{
id: '1',
name: 'Documents',
isFile: false,
hasChild: true,
parentId: null,
dateModified: new Date('2024-01-15')
},
{
id: '2',
name: 'Resume.pdf',
isFile: true,
hasChild: false,
parentId: '1',
size: 204800,
dateModified: new Date('2024-01-10')
}
];
}Common Patterns
Pattern 1: Server Integration with Full Configuration
Use when: Building a production file manager with backend services
// app.component.ts
ajaxSettings = {
url: '/api/FileManager/FileOperations',
getImageUrl: '/api/FileManager/GetImage',
uploadUrl: '/api/FileManager/Upload',
downloadUrl: '/api/FileManager/Download'
};
toolbarSettings = {
items: ['NewFolder', 'Upload', 'Download', 'Delete', 'Refresh', 'View', 'Details']
};Pattern 2: Local Data with Custom Formatting
Use when: Data comes from API but doesn't need backend file operations
Transform API response into fileData format:
fileData = this.apiService.getFiles().map(file => ({
id: file.id,
name: file.fileName,
isFile: file.type === 'file',
parentId: file.parentId || null,
size: file.fileSize,
dateModified: new Date(file.modified)
}));Pattern 3: Virtualization for Large Datasets
Use when: Handling 1000+ files
// Inject VirtualizationService, enable enableVirtualization
providers: [VirtualizationService]
// In template
<ejs-filemanager
[enableVirtualization]="true"
[view]="'Details'"
...>
</ejs-filemanager>Pattern 4: Multi-Selection with Actions
Use when: Bulk file operations needed
onDownloadSelected() {
const selected = this.fileManager.selectedItems;
// Download multiple files (server returns ZIP)
}Key Props and Settings
Core Configuration
| Property | Type | Purpose |
|---|---|---|
ajaxSettings | AjaxSettingsModel | Server endpoints for file operations (url, uploadUrl, downloadUrl, getImageUrl) |
fileSystemData | FileData[] | Local JSON data (alternative to ajaxSettings) |
path | string | Initial directory path to display |
view | ViewType | Initial view mode: 'Details' or 'LargeIcons' |
height | string \ | number |
width | string \ | number |
Selection & Multi-Selection
| Property | Type | Purpose |
|---|---|---|
allowMultiSelection | boolean | Enable Ctrl+Click and Shift+Click selection |
enableRangeSelection | boolean | Enable drag-based selection (Windows Explorer style) |
File Operations
| Property | Type | Purpose |
|---|---|---|
allowDragAndDrop | boolean | Enable drag-and-drop file movement |
uploadSettings | UploadSettingsModel | Upload config (maxFileSize, minFileSize, autoUpload, allowedExtensions, directoryUpload) |
searchSettings | SearchSettingsModel | Search config (filterType, allowSearchOnTyping, caseSensitive) |
Display & Performance
| Property | Type | Purpose |
|---|---|---|
showThumbnail | boolean | Display image thumbnails |
showHiddenItems | boolean | Show/hide hidden files and folders (default: false) |
showFileExtension | boolean | Display file extensions (default: true) |
enableVirtualization | boolean | Virtualize large file sets (1000+ items) |
enablePersistence | boolean | Persist view, path, and selected items |
enableRtl | boolean | Right-to-left layout support |
enableHtmlSanitizer | boolean | Sanitize HTML for security |
UI Customization
| Property | Type | Purpose |
|---|---|---|
toolbarSettings | ToolbarSettingsModel | Toolbar items and visibility |
navigationPaneSettings | NavigationPaneSettingsModel | Left sidebar configuration |
contextMenuSettings | ContextMenuSettingsModel | Right-click menu customization |
detailsViewSettings | DetailsViewSettingsModel | Details view columns and sorting |
navigationPaneTemplate | string \ | object |
largeIconsTemplate | string \ | object |
cssClass | string | CSS class for theming |
locale | string | Localization culture (e.g., 'de-DE', 'ja-JP') |
Sorting & Comparison
| Property | Type | Purpose |
|---|---|---|
sortComparer | Function | Custom sort function (Windows Explorer-like sorting available) |
Decision Tree: Choose Your Approach
Do you have a backend file service?
├─ YES → Use ajaxSettings (see Getting Started)
│ └─ Need to handle 1000+ files?
│ ├─ YES → Enable enableVirtualization
│ └─ NO → Standard setup
│
└─ NO → Use fileSystemData with local JSON
└─ Need to organize hierarchically?
├─ YES → Use nested items with parentId
└─ NO → Use flat data structure---
Next Steps: Select the reference that matches your current task and dive into implementation details with code examples and best practices.
Access Control and Permissions in Syncfusion Angular File Manager
Overview
Access control allows you to restrict user actions by defining permissions for files and folders. The FileManager component can be configured to show or hide files/folders and enable/disable operations based on user permissions.
Table of Contents
- Permission Model
- Implementing Role-Based Access
- File-Level Permissions
- Backend Permission Rules
- Frontend Permission Handling
- Examples
---
Permission Model
FileData Permission Structure
The FileData interface includes a permission object that defines access control:
interface FileData {
id: string | number;
name: string;
isFile: boolean;
permission?: {
read?: boolean; // Can read/view file
readContent?: boolean; // Can read file contents
write?: boolean; // Can modify file
writeContent?: boolean; // Can modify folder contents
delete?: boolean; // Can delete file
download?: boolean; // Can download file
upload?: boolean; // Can upload to folder
copy?: boolean; // Can copy file
};
}Permission Values
| Value | Meaning |
|---|---|
true | Operation is allowed |
false | Operation is denied |
undefined | No restriction (allow by default) |
---
Implementing Role-Based Access
1. Backend Implementation (ASP.NET Core Example)
Define access rules based on user roles:
public class AccessRule
{
public string Path { get; set; }
public string Role { get; set; }
public Permission Read { get; set; }
public Permission Write { get; set; }
public Permission Copy { get; set; }
public Permission WriteContents { get; set; }
public Permission Upload { get; set; }
public Permission Download { get; set; }
public bool IsFile { get; set; }
}
public enum Permission
{
Allow = 1,
Deny = 2
}
// Configure rules for Administrator
var adminRules = new List<AccessRule>
{
new AccessRule
{
Path = "/*.*",
Role = "Administrator",
Read = Permission.Allow,
Write = Permission.Allow,
Copy = Permission.Allow,
Download = Permission.Allow,
IsFile = true
},
new AccessRule
{
Path = "*",
Role = "Administrator",
Read = Permission.Allow,
Write = Permission.Allow,
Copy = Permission.Allow,
WriteContents = Permission.Allow,
Upload = Permission.Allow,
Download = Permission.Allow,
IsFile = false
}
};
// Configure rules for Read-Only User
var readOnlyRules = new List<AccessRule>
{
new AccessRule
{
Path = "/*.*",
Role = "ReadOnly User",
Read = Permission.Allow,
Write = Permission.Deny,
Copy = Permission.Deny,
Download = Permission.Allow,
IsFile = true
},
new AccessRule
{
Path = "*",
Role = "ReadOnly User",
Read = Permission.Allow,
Write = Permission.Deny,
Copy = Permission.Deny,
WriteContents = Permission.Deny,
Upload = Permission.Deny,
Download = Permission.Allow,
IsFile = false
}
};2. Apply Permissions to FileData
[HttpPost("FileOperations")]
public IActionResult FileOperations(string path, string action, [FromHeader] string userRole)
{
try
{
switch(action.ToLower())
{
case "read":
var files = GetFiles(path);
var accessRules = GetAccessRulesForRole(userRole);
// Apply permissions to each file
foreach(var file in files)
{
var rule = accessRules.FirstOrDefault(r => MatchesPath(file.Path, r.Path));
if(rule != null)
{
file.Permission = new
{
read = rule.Read == Permission.Allow,
write = rule.Write == Permission.Allow,
delete = rule.Write == Permission.Allow,
download = rule.Download == Permission.Allow,
upload = rule.Upload == Permission.Allow,
copy = rule.Copy == Permission.Allow
};
}
}
return Ok(files);
default:
return BadRequest();
}
}
catch(Exception ex)
{
return StatusCode(500, new { error = ex.Message });
}
}---
File-Level Permissions
Denying Specific Operations
Restrict operations for specific folders or file types:
// Deny write permission for system files
new AccessRule
{
Path = "/System/*.*",
Role = "User",
Read = Permission.Allow,
Write = Permission.Deny,
IsFile = true
},
// Deny upload to specific folder
new AccessRule
{
Path = "/ReadOnlyFolder",
Role = "User",
Read = Permission.Allow,
WriteContents = Permission.Deny,
Upload = Permission.Deny,
IsFile = false
},
// Deny download for sensitive files
new AccessRule
{
Path = "/Confidential/*.pdf",
Role = "User",
Read = Permission.Allow,
Download = Permission.Deny,
IsFile = true
}Granting Specific Permissions
Allow specific operations while denying others:
// Allow read and download only
new AccessRule
{
Path = "/*.*",
Role = "ReadOnly User",
Read = Permission.Allow,
Write = Permission.Deny,
Download = Permission.Allow,
Copy = Permission.Deny,
IsFile = true
},
// Allow folder navigation and listing only
new AccessRule
{
Path = "*",
Role = "Viewer",
Read = Permission.Allow,
WriteContents = Permission.Deny,
Upload = Permission.Deny,
Download = Permission.Deny,
IsFile = false
}---
Backend Permission Rules
Complete ASP.NET Core Permission Handler
public interface IPermissionService
{
List<AccessRule> GetRulesForRole(string role);
bool CheckPermission(string filePath, string permission, string userRole);
}
public class PermissionService : IPermissionService
{
private readonly Dictionary<string, List<AccessRule>> _roleRules;
public PermissionService()
{
_roleRules = new Dictionary<string, List<AccessRule>>
{
["Administrator"] = GetAdministratorRules(),
["Editor"] = GetEditorRules(),
["Viewer"] = GetViewerRules()
};
}
public List<AccessRule> GetRulesForRole(string role)
{
return _roleRules.ContainsKey(role) ? _roleRules[role] : new List<AccessRule>();
}
public bool CheckPermission(string filePath, string permission, string userRole)
{
var rules = GetRulesForRole(userRole);
var rule = rules.FirstOrDefault(r => MatchesPath(filePath, r.Path));
if(rule == null) return true; // No rule = allow by default
return permission switch
{
"read" => rule.Read == Permission.Allow,
"write" => rule.Write == Permission.Allow,
"delete" => rule.Write == Permission.Allow,
"download" => rule.Download == Permission.Allow,
"upload" => rule.Upload == Permission.Allow,
"copy" => rule.Copy == Permission.Allow,
_ => false
};
}
private bool MatchesPath(string filePath, string rulePath)
{
// Wildcard matching logic
if(rulePath == "*" || rulePath == "/*.*") return true;
if(rulePath.EndsWith("/*")) return filePath.StartsWith(rulePath.TrimEnd('*'));
return filePath == rulePath;
}
private List<AccessRule> GetAdministratorRules()
{
return new List<AccessRule>
{
new AccessRule { Path = "/*.*", Role = "Administrator", Read = Permission.Allow,
Write = Permission.Allow, Copy = Permission.Allow, Download = Permission.Allow, IsFile = true },
new AccessRule { Path = "*", Role = "Administrator", Read = Permission.Allow,
Write = Permission.Allow, WriteContents = Permission.Allow, Upload = Permission.Allow,
Download = Permission.Allow, IsFile = false }
};
}
private List<AccessRule> GetEditorRules()
{
return new List<AccessRule>
{
new AccessRule { Path = "/Public/*.*", Role = "Editor", Read = Permission.Allow,
Write = Permission.Allow, Copy = Permission.Allow, Download = Permission.Allow, IsFile = true },
new AccessRule { Path = "/Confidential/*.*", Role = "Editor", Read = Permission.Allow,
Write = Permission.Deny, Copy = Permission.Deny, Download = Permission.Allow, IsFile = true }
};
}
private List<AccessRule> GetViewerRules()
{
return new List<AccessRule>
{
new AccessRule { Path = "/*.*", Role = "Viewer", Read = Permission.Allow,
Write = Permission.Deny, Copy = Permission.Deny, Download = Permission.Allow, IsFile = true }
};
}
}
// Usage in FileManagerController
[ApiController]
[Route("api/[controller]")]
public class FileManagerController : ControllerBase
{
private readonly IPermissionService _permissionService;
public FileManagerController(IPermissionService permissionService)
{
_permissionService = permissionService;
}
[HttpPost("FileOperations")]
public IActionResult FileOperations(
[FromBody] FileRequest request,
[FromHeader] string userRole = "Viewer")
{
try
{
// Check if user has read permission for path
if(!_permissionService.CheckPermission(request.Path, "read", userRole))
{
return Forbid("You don't have permission to read this folder");
}
// Process file operation...
return Ok();
}
catch(Exception ex)
{
return StatusCode(500, new { error = ex.Message });
}
}
}---
Frontend Permission Handling
Disabling UI Elements Based on Permissions
import { Component, ViewChild } from '@angular/core';
import { FileManagerComponent } from '@syncfusion/ej2-angular-filemanager';
import { FileSelectEventArgs, MenuClickEventArgs } from '@syncfusion/ej2-filemanager';
@Component({
selector: 'app-file-manager',
template: `<ejs-filemanager
#fileManager
[ajaxSettings]='ajaxSettings'
[toolbarSettings]='toolbarSettings'
[contextMenuSettings]='contextMenuSettings'
(fileSelect)='onFileSelect($event)'
(beforeDelete)='onBeforeDelete($event)'
(menuClick)='onMenuClick($event)'>
</ejs-filemanager>`
})
export class AppComponent implements AfterViewInit {
@ViewChild('fileManager')
fileManager?: FileManagerComponent;
ajaxSettings = {
url: '/api/FileManager/FileOperations',
uploadUrl: '/api/FileManager/Upload',
downloadUrl: '/api/FileManager/Download',
getImageUrl: '/api/FileManager/GetImage'
};
toolbarSettings = {
items: ['NewFolder', 'Upload', 'Delete', 'Download', 'Rename']
};
contextMenuSettings = {
file: ['Download', 'Copy'],
folder: ['NewFolder', 'Paste'],
layout: ['Refresh', 'NewFolder']
};
ngAfterViewInit() {
// Disable toolbar items based on user permissions
const currentUser = this.getCurrentUser();
if(currentUser.role === 'Viewer') {
this.fileManager?.disableToolbarItems(['Upload', 'Delete', 'Rename']);
}
}
onFileSelect(args: FileSelectEventArgs) {
// Update UI based on selected file permissions
const selectedFile = args.fileDetails[0];
if(selectedFile.permission?.write === false) {
this.fileManager?.disableToolbarItems(['Delete', 'Rename']);
} else {
this.fileManager?.enableToolbarItems(['Delete', 'Rename']);
}
}
onBeforeDelete(args: any) {
// Prevent deletion if user doesn't have permission
if(args.fileDetails[0].permission?.delete === false) {
args.cancel = true;
alert('You do not have permission to delete this file');
}
}
onMenuClick(args: MenuClickEventArgs) {
const selectedFile = this.fileManager?.selectedItems[0];
if(args.itemText === 'Delete' && selectedFile?.permission?.delete === false) {
alert('You do not have permission to delete this file');
}
}
private getCurrentUser() {
// Get from localStorage or auth service
return {
name: 'John Doe',
role: 'Editor'
};
}
}Sending User Role to Backend
@Component({
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforeSend)='onBeforeSend($event)'>
</ejs-filemanager>`
})
export class AppComponent {
ajaxSettings = {
url: '/api/FileManager/FileOperations',
uploadUrl: '/api/FileManager/Upload',
downloadUrl: '/api/FileManager/Download'
};
onBeforeSend(args: any) {
// Add user role to request headers
const userRole = this.getUserRole();
args.ajaxSettings.beforeSend = (request: any) => {
request.httpRequest.setRequestHeader('UserRole', userRole);
request.httpRequest.setRequestHeader('UserId', this.getUserId());
};
}
private getUserRole(): string {
// Get from JWT token or auth service
return localStorage.getItem('userRole') || 'Viewer';
}
private getUserId(): string {
return localStorage.getItem('userId') || '0';
}
}---
Examples
Example 1: Content Manager with Role-Based Access
@Component({
selector: 'app-content-manager',
template: `<div>
<h2>Content Manager ({{ userRole }})</h2>
<ejs-filemanager
#fileManager
[ajaxSettings]='ajaxSettings'
[toolbarSettings]='toolbarSettings'
(beforeSend)='onBeforeSend($event)'
height="500px">
</ejs-filemanager>
</div>`
})
export class ContentManagerComponent implements OnInit {
@ViewChild('fileManager')
fileManager?: FileManagerComponent;
userRole = 'Editor';
ajaxSettings = {
url: '/api/FileManager/FileOperations',
uploadUrl: '/api/FileManager/Upload',
downloadUrl: '/api/FileManager/Download'
};
toolbarSettings = {
items: ['NewFolder', 'Upload', 'Delete', 'Download']
};
ngOnInit() {
this.setupPermissions();
}
onBeforeSend(args: any) {
args.ajaxSettings.beforeSend = (request: any) => {
request.httpRequest.setRequestHeader('UserRole', this.userRole);
};
}
private setupPermissions() {
setTimeout(() => {
if(this.userRole === 'Viewer') {
this.fileManager?.disableToolbarItems(['Upload', 'Delete']);
}
}, 100);
}
}Example 2: Prevent Sensitive File Operations
@Component({
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforeDelete)='onBeforeDelete($event)'
(beforeMove)='onBeforeMove($event)'>
</ejs-filemanager>`
})
export class SecureFileManagerComponent {
ajaxSettings = {
url: '/api/FileManager/FileOperations'
};
onBeforeDelete(args: any) {
// Prevent deletion of system files
if(args.fileDetails[0].name.startsWith('.')) {
args.cancel = true;
alert('Cannot delete system files');
}
// Check permissions from FileData
if(args.fileDetails[0].permission?.delete === false) {
args.cancel = true;
alert('You do not have permission to delete this file');
}
}
onBeforeMove(args: any) {
// Prevent moving to restricted folders
if(args.path === '/System') {
args.cancel = true;
alert('Cannot move files to System folder');
}
}
}---
Best Practices
1. Always validate permissions on backend - Never rely solely on frontend permission checks 2. Use JWT tokens - Send authorization tokens with requests for secure authentication 3. Log access attempts - Track who accessed/modified what and when 4. Implement role hierarchy - Create roles with inheritance (Admin > Editor > Viewer) 5. Cache permissions - Store user permissions client-side for better performance 6. Handle permission errors gracefully - Show friendly messages instead of technical errors 7. Review permissions regularly - Audit access rules for security compliance
---
Next: Implement custom authentication at authentication-patterns.md or manage data structures at data-structures.md.
Advanced Features in Syncfusion Angular File Manager
Table of Contents
- Multi-Selection
- Range Selection
- State Persistence
- Component Lifecycle
- Event Handling
- File Operation Events
- Drag and Drop Events
- Dialog and Menu Events
- Ajax Events
- Programmatic Methods
- Complete Advanced Example
Multi-Selection
Enable Multi-Selection
Allow users to select multiple files at once:
import { Component } from '@angular/core';
import { FileManagerModule } from '@syncfusion/ej2-angular-filemanager';
@Component({
imports: [FileManagerModule],
standalone: true,
selector: 'app-root',
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
[allowMultiSelection]='true'
height="500px">
</ejs-filemanager>`
})
export class AppComponent {
public ajaxSettings = {
url: '/api/FileManager/FileOperations'
};
// Users can:
// - Click files to select
// - Ctrl+Click to select additional files
// - Shift+Click to select range
}Work with Selected Items
import { Component, ViewChild } from '@angular/core';
import { FileManagerComponent, FileManagerModule } from '@syncfusion/ej2-angular-filemanager';
@Component({
imports: [FileManagerModule],
standalone: true,
selector: 'app-root',
template: `<div>
<div class='selection-info'>
<span>Selected: {{ selectedCount }}</span>
<span>Total Size: {{ totalSize | number }}</span>
<button (click)='downloadSelected()' [disabled]='selectedCount === 0'>
Download Selected
</button>
</div>
<ejs-filemanager
#fileManager
[ajaxSettings]='ajaxSettings'
[allowMultiSelection]='true'
(fileSelect)='onFileSelect($event)'
height="500px">
</ejs-filemanager>
</div>`
})
export class AppComponent {
@ViewChild('fileManager')
public fileManager?: FileManagerComponent;
public selectedCount: number = 0;
public totalSize: number = 0;
public ajaxSettings = {
url: '/api/FileManager/FileOperations'
};
onFileSelect(args: any) {
const selected = this.fileManager?.selectedItems || [];
this.selectedCount = selected.length;
// Calculate total size of selected files
this.totalSize = selected.reduce((sum, file) =>
sum + (file.size || 0), 0);
}
downloadSelected() {
const selected = this.fileManager?.selectedItems || [];
if (selected.length > 0) {
console.log('Downloading:', selected.map(f => f.name));
// Download will be triggered automatically by toolbar
}
}
}Select/Clear All
import { Component, ViewChild } from '@angular/core';
import { FileManagerComponent, FileManagerModule } from '@syncfusion/ej2-angular-filemanager';
@Component({
template: `<div>
<button (click)='selectAll()'>Select All</button>
<button (click)='clearSelection()'>Clear Selection</button>
<button (click)='invertSelection()'>Invert Selection</button>
</div>`
})
export class AppComponent {
@ViewChild('fileManager')
public fileManager?: FileManagerComponent;
selectAll() {
this.fileManager?.selectAll();
}
clearSelection() {
this.fileManager?.clearSelection();
}
invertSelection() {
const all = this.fileManager?.getFiles() || [];
const selected = new Set(
(this.fileManager?.selectedItems || []).map(f => f.id)
);
const toSelect = all
.filter(f => !selected.has(f.id))
.map(f => f.id);
this.fileManager?.clearSelection();
this.fileManager?.selectedItems = toSelect as any;
}
}Range Selection
Enable Range Selection (Mouse Drag)
Enable Windows Explorer-style drag-based selection:
import { Component } from '@angular/core';
import { FileManagerModule } from '@syncfusion/ej2-angular-filemanager';
@Component({
imports: [FileManagerModule],
standalone: true,
selector: 'app-root',
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
[enableRangeSelection]='true'
height="500px">
</ejs-filemanager>`
})
export class AppComponent {
public ajaxSettings = {
url: '/api/FileManager/FileOperations'
};
// Users can now:
// - Drag over multiple files to select them
// - Works like Windows Explorer range selection
}State Persistence
Enable Persistence
Maintain view, path, and selected items across page reload:
import { Component } from '@angular/core';
import { FileManagerModule } from '@syncfusion/ej2-angular-filemanager';
@Component({
imports: [FileManagerModule],
standalone: true,
selector: 'app-root',
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
[enablePersistence]='true'
height="500px">
</ejs-filemanager>`
})
export class AppComponent {
public ajaxSettings = {
url: '/api/FileManager/FileOperations'
};
// File Manager will save and restore:
// - Current view (Details or LargeIcons)
// - Current path
// - Selected items
// Using localStorage
}What Gets Persisted
| Property | Persisted | Example |
|---|---|---|
| View | Yes | Details view preference |
| Path | Yes | /Music/Rock |
| SelectedItems | Yes | [file1.txt, file2.txt] |
| Scroll Position | No | Not restored |
Component Lifecycle
Initialization Event
import { Component } from '@angular/core';
import { FileManagerModule } from '@syncfusion/ej2-angular-filemanager';
@Component({
imports: [FileManagerModule],
standalone: true,
selector: 'app-root',
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(created)='onCreate($event)'
(destroyed)='onDestroy($event)'
height="500px">
</ejs-filemanager>`
})
export class AppComponent {
public ajaxSettings = {
url: '/api/FileManager/FileOperations'
};
onCreate(args: any) {
console.log('File Manager created successfully');
// Initialize custom features
}
onDestroy(args: any) {
console.log('File Manager destroyed');
// Clean up resources
}
}Event Handling
Understanding File Manager Events
The File Manager provides comprehensive events at different lifecycle stages:
- Selection Events:
fileSelect,fileSelection(before selection) - File Operation Events:
beforeDelete,delete,beforeRename,beforeFolderCreate,folderCreate,beforeMove - Opening Events:
fileOpen,fileLoad(before rendering) - Drag & Drop Events:
fileDragStart,fileDragging,fileDragStop,fileDropped - Dialog Events:
beforePopupOpen,beforePopupClose - Menu Events:
menuOpen,menuClose,menuClick - Server Events:
beforeSend,success,failure,beforeDownload,beforeImageLoad - Lifecycle Events:
created,destroyed
File Operation Events
Prevent Operations with beforeDelete
import { Component } from '@angular/core';
import { FileManagerModule } from '@syncfusion/ej2-angular-filemanager';
import { DeleteEventArgs } from '@syncfusion/ej2-filemanager';
@Component({
imports: [FileManagerModule],
standalone: true,
selector: 'app-root',
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforeDelete)='onBeforeDelete($event)'
height="500px">
</ejs-filemanager>`
})
export class AppComponent {
public ajaxSettings = {
url: '/api/FileManager/FileOperations'
};
onBeforeDelete(args: DeleteEventArgs) {
const fileNames = args.fileDetails.map(f => f.name);
// Prevent deletion of system files
if (fileNames.some(name => name.startsWith('.'))) {
args.cancel = true;
alert('Cannot delete system files');
}
// Prevent deletion of folders with special names
if (fileNames.includes('System') || fileNames.includes('Program Files')) {
args.cancel = true;
alert('Cannot delete protected folders');
}
}
}React After Delete
export class AppComponent {
onDelete(args: DeleteEventArgs) {
const deletedItems = args.fileDetails.map(f => f.name);
console.log('Deleted items:', deletedItems);
// Log to server
fetch('/api/audit-log', {
method: 'POST',
body: JSON.stringify({
action: 'delete',
items: deletedItems,
timestamp: new Date()
})
});
}
}Handle Rename Events
export class AppComponent {
onBeforeRename(args: RenameEventArgs) {
// Validate new name
const invalidChars = /[<>:"|?*]/;
if (invalidChars.test(args.newName)) {
args.cancel = true;
alert('Invalid characters in filename');
}
// Prevent renaming system files
if (args.fileDetails.name.startsWith('.')) {
args.cancel = true;
alert('Cannot rename system files');
}
}
}Handle Folder Creation
export class AppComponent {
onBeforeFolderCreate(args: FolderCreateEventArgs) {
// Validate folder name
if (args.folderName.length === 0) {
args.cancel = true;
alert('Folder name cannot be empty');
}
// Limit folder creation in certain directories
if (this.fileManager?.path === '/System') {
args.cancel = true;
alert('Cannot create folders in System directory');
}
}
onFolderCreate(args: FolderCreateEventArgs) {
console.log('Folder created:', args.folderName);
// Update UI or trigger other actions
}
}Drag and Drop Events
Prevent Specific Drops
import { Component } from '@angular/core';
import { FileManagerModule } from '@syncfusion/ej2-angular-filemanager';
import { FileDragEventArgs } from '@syncfusion/ej2-filemanager';
@Component({
imports: [FileManagerModule],
standalone: true,
selector: 'app-root',
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
[allowDragAndDrop]='true'
(fileDragStop)='onBeforeDrop($event)'
(fileDropped)='onAfterDrop($event)'
height="500px">
</ejs-filemanager>`
})
export class AppComponent {
public ajaxSettings = {
url: '/api/FileManager/FileOperations'
};
onBeforeDrop(args: FileDragEventArgs) {
// Prevent dropping into read-only folders
if (args.targetData?.permission?.write === false) {
args.cancel = true;
alert('Cannot drop into read-only folder');
}
// Prevent dropping large files
const totalSize = args.fileDetails.reduce((sum, f) => sum + (f.size || 0), 0);
if (totalSize > 500 * 1024 * 1024) { // 500MB
args.cancel = true;
alert('Total drop size exceeds 500MB limit');
}
}
onAfterDrop(args: FileDragEventArgs) {
console.log('Files dropped:', args.fileDetails.map(f => f.name));
console.log('Target folder:', args.targetData.name);
}
}Track Drag Progress
export class AppComponent {
isDragging: boolean = false;
onDragStart(args: FileDragEventArgs) {
this.isDragging = true;
console.log('Dragging started:', args.fileDetails);
}
onDragging(args: FileDragEventArgs) {
// Visual feedback during drag
console.log('Dragging over:', args.targetData);
}
onDragStop(args: FileDragEventArgs) {
this.isDragging = false;
console.log('Drag stopped');
}
}Dialog and Menu Events
Customize Dialog Behavior
import { Component } from '@angular/core';
import { BeforePopupOpenCloseEventArgs } from '@syncfusion/ej2-filemanager';
@Component({
selector: 'app-root',
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforePopupOpen)='onBeforePopupOpen($event)'
(beforePopupClose)='onBeforePopupClose($event)'
height="500px">
</ejs-filemanager>`
})
export class AppComponent {
onBeforePopupOpen(args: BeforePopupOpenCloseEventArgs) {
// Modify dialog content
console.log('Dialog type:', args.popupType);
// Prevent certain dialogs
if (args.popupType === 'Delete' && this.isRestrictedMode) {
args.cancel = true;
}
}
onBeforePopupClose(args: BeforePopupOpenCloseEventArgs) {
console.log('Dialog closing:', args.popupType);
}
isRestrictedMode: boolean = false;
}Handle Context Menu
import { Component } from '@angular/core';
import { MenuClickEventArgs, MenuOpenEventArgs } from '@syncfusion/ej2-filemanager';
@Component({
selector: 'app-root',
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(menuOpen)='onMenuOpen($event)'
(menuClick)='onMenuClick($event)'
height="500px">
</ejs-filemanager>`
})
export class AppComponent {
onMenuOpen(args: MenuOpenEventArgs) {
// Customize menu items based on selection
const selectedFiles = args.fileDetails;
// Hide items for certain file types
if (selectedFiles[0]?.type === '.exe') {
args.fileContextMenu?.disableItems(['Execute']);
}
}
onMenuClick(args: MenuClickEventArgs) {
console.log('Menu item clicked:', args.itemText);
// Custom actions for menu items
if (args.itemText === 'Custom Action') {
this.performCustomAction();
}
}
performCustomAction() {
console.log('Custom action performed');
}
}Customize Toolbar
import { Component } from '@angular/core';
import { ToolbarClickEventArgs, ToolbarCreateEventArgs } from '@syncfusion/ej2-filemanager';
@Component({
selector: 'app-root',
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(toolbarCreate)='onToolbarCreate($event)'
(toolbarClick)='onToolbarClick($event)'
height="500px">
</ejs-filemanager>`
})
export class AppComponent {
onToolbarCreate(args: ToolbarCreateEventArgs) {
// Modify toolbar at creation time
console.log('Toolbar items:', args.items);
// Add custom button or remove items
args.items?.push({
prefixIcon: 'e-icons e-print',
text: 'Print',
id: 'print'
});
}
onToolbarClick(args: ToolbarClickEventArgs) {
if (args.item?.id === 'print') {
this.printFiles();
}
}
printFiles() {
console.log('Printing selected files');
}
}Ajax Events
Success and Failure Events
import { Component } from '@angular/core';
import { FileManagerModule } from '@syncfusion/ej2-angular-filemanager';
@Component({
imports: [FileManagerModule],
standalone: true,
selector: 'app-root',
template: `<div>
<div class='status-bar'>{{ statusMessage }}</div>
<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(success)='onSuccess($event)'
(failure)='onFailure($event)'
height="500px">
</ejs-filemanager>
</div>`,
styles: [`
.status-bar {
padding: 10px;
background-color: #f5f5f5;
border-bottom: 1px solid #ddd;
}
`]
})
export class AppComponent {
public statusMessage: string = 'Ready';
public ajaxSettings = {
url: '/api/FileManager/FileOperations'
};
onSuccess(args: any) {
this.statusMessage = `✓ ${args.action} completed successfully`;
// Log different operation types
switch(args.action) {
case 'read':
console.log('Files loaded:', args.result.length);
break;
case 'create':
console.log('Folder created:', args.result.name);
break;
case 'delete':
console.log('Items deleted');
break;
}
}
onFailure(args: any) {
this.statusMessage = `✗ ${args.action} failed: ${args.error?.statusText}`;
console.error('Operation failed:', args);
}
}Before Send Event
@Component({
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforeSend)='onBeforeSend($event)'>
</ejs-filemanager>`
})
export class AppComponent {
public ajaxSettings = {
url: '/api/FileManager/FileOperations'
};
onBeforeSend(args: any) {
// Modify request before sending
args.ajaxSettings.beforeSend = (requestArgs: any) => {
// Add authentication
requestArgs.httpRequest.setRequestHeader('Authorization', 'Bearer token123');
// Add custom headers
requestArgs.httpRequest.setRequestHeader('X-Custom-Header', 'value');
// Modify request data
const data = JSON.parse(requestArgs.data);
data.userId = '12345';
data.timestamp = new Date().toISOString();
requestArgs.data = JSON.stringify(data);
};
}
}Event Properties
// success/failure event args
{
action: string, // Operation: read, create, delete, etc.
result?: any, // Server response data
error?: {
statusCode: number,
statusText: string,
message: string
}
}
// beforeSend event args
{
ajaxSettings: {
beforeSend: Function // Modify HTTP request
}
}Programmatic Methods
File and Folder Operations Methods
import { Component, ViewChild } from '@angular/core';
import { FileManagerComponent, FileManagerModule } from '@syncfusion/ej2-angular-filemanager';
@Component({
imports: [FileManagerModule],
standalone: true,
selector: 'app-root',
template: `<div>
<div class='operations'>
<button (click)='createNewFolder()'>Create Folder</button>
<button (click)='renameSelected()'>Rename</button>
<button (click)='deleteSelected()'>Delete</button>
<button (click)='downloadSelected()'>Download</button>
</div>
<ejs-filemanager
#fileManager
[ajaxSettings]='ajaxSettings'
height="500px">
</ejs-filemanager>
</div>`
})
export class AppComponent {
@ViewChild('fileManager')
public fileManager?: FileManagerComponent;
public ajaxSettings = {
url: '/api/FileManager/FileOperations'
};
// Create a new folder
createNewFolder() {
// With name - creates directly
this.fileManager?.createFolder('NewFolder');
// Without name - opens dialog
// this.fileManager?.createFolder();
}
// Rename selected file/folder
renameSelected() {
const selected = this.fileManager?.selectedItems;
if (selected && selected.length === 1) {
this.fileManager?.renameFile(selected[0] as any);
}
}
// Delete selected items
deleteSelected() {
if (confirm('Delete selected items?')) {
this.fileManager?.deleteFiles();
}
}
// Download selected items
downloadSelected() {
this.fileManager?.downloadFiles();
}
}Navigate and Refresh Methods
export class AppComponent {
@ViewChild('fileManager')
public fileManager?: FileManagerComponent;
// Open a specific file/folder by ID
openFile(fileId: string) {
this.fileManager?.openFile(fileId);
}
// Go back one level
goBack() {
this.fileManager?.traverseBackward();
}
// Refresh current folder
refreshCurrentFolder() {
this.fileManager?.refreshFiles();
}
// Refresh entire layout
refreshLayout() {
this.fileManager?.refreshLayout();
}
// Get selected files details
getSelectedFilesDetails() {
const files = this.fileManager?.getSelectedFiles();
console.log('Selected files:', files);
return files;
}
}Selection Methods
export class AppComponent {
@ViewChild('fileManager')
public fileManager?: FileManagerComponent;
// Select all files in current folder
selectAllFiles() {
this.fileManager?.selectAll();
}
// Deselect all
deselectAll() {
this.fileManager?.clearSelection();
}
// Select files by name
selectByName(names: string[]) {
this.fileManager?.clearSelection();
const nameSet = new Set(names);
const files = this.fileManager?.getFiles() || [];
files.forEach(file => {
if (nameSet.has(file.name)) {
// File manager handles selection internally
}
});
}
}Toolbar and Menu Methods
export class AppComponent {
@ViewChild('fileManager')
public fileManager?: FileManagerComponent;
// Enable specific toolbar items
enableToolbarItems(items: string[]) {
this.fileManager?.enableToolbarItems(items);
}
// Disable specific toolbar items
disableToolbarItems(items: string[]) {
this.fileManager?.disableToolbarItems(items);
}
// Get toolbar item index
getToolbarIndex(itemName: string) {
return this.fileManager?.getToolbarItemIndex(itemName);
}
// Enable context menu items
enableMenuItems(items: string[]) {
this.fileManager?.enableMenuItems(items);
}
// Disable context menu items
disableMenuItems(items: string[]) {
this.fileManager?.disableMenuItems(items);
}
// Get menu item index
getMenuIndex(itemName: string) {
return this.fileManager?.getMenuItemIndex(itemName);
}
}Dialog and Filter Methods
export class AppComponent {
@ViewChild('fileManager')
public fileManager?: FileManagerComponent;
// Close any open dialogs
closeDialogs() {
this.fileManager?.closeDialog();
}
// Open upload dialog
openUploadDialog() {
this.fileManager?.uploadFiles();
}
// Apply custom filtering
applyFilter(filterCriteria: any) {
this.fileManager?.filterFiles(filterCriteria);
}
// Filter by file type
filterByType(extension: string) {
this.fileManager?.filterFiles({
action: 'filter',
filterData: {
type: extension
}
});
}
}Component Lifecycle Methods
export class AppComponent {
@ViewChild('fileManager')
public fileManager?: FileManagerComponent;
// Destroy the component
destroy() {
this.fileManager?.destroy();
}
// The created and destroyed events are handled through event bindings
onCreate() {
console.log('File Manager initialized');
}
onDestroy() {
console.log('File Manager destroyed');
}
}Refresh File List
Refresh the current folder contents programmatically:
import { Component, ViewChild } from '@angular/core';
import { FileManagerComponent, FileManagerModule } from '@syncfusion/ej2-angular-filemanager';
@Component({
imports: [FileManagerModule],
standalone: true,
selector: 'app-root',
template: `<div>
<button (click)='refresh()'>Refresh Files</button>
<ejs-filemanager
#fileManager
[ajaxSettings]='ajaxSettings'
height="500px">
</ejs-filemanager>
</div>`
})
export class AppComponent {
@ViewChild('fileManager')
public fileManager?: FileManagerComponent;
public ajaxSettings = {
url: '/api/FileManager/FileOperations'
};
refresh() {
// Reload the current folder's files from server
this.fileManager?.refresh();
}
}Get All Files
getFiles() {
const allFiles = this.fileManager?.getFiles();
console.log('All files:', allFiles);
}Programmatic Refresh (Continued)
import { Component, ViewChild } from '@angular/core';
import { FileManagerComponent, FileManagerModule } from '@syncfusion/ej2-angular-filemanager';
@Component({
imports: [FileManagerModule],
standalone: true,
selector: 'app-root',
template: `<div>
<button (click)='refresh()'>Refresh Folder</button>
<button (click)='refreshAll()'>Refresh All</button>
<ejs-filemanager
#fileManager
[ajaxSettings]='ajaxSettings'
height="500px">
</ejs-filemanager>
</div>`
})
export class AppComponent {
@ViewChild('fileManager')
public fileManager?: FileManagerComponent;
public ajaxSettings = {
url: '/api/FileManager/FileOperations'
};
refresh() {
// Refresh current folder
this.fileManager?.refresh();
}
refreshAll() {
// Full refresh - go to root and reload
this.fileManager?.path = '/';
this.fileManager?.refresh();
}
}Complete Advanced Example with All Features
Full-Featured File Manager Component
import { Component, ViewChild } from '@angular/core';
import { FileManagerComponent, FileManagerModule } from '@syncfusion/ej2-angular-filemanager';
@Component({
imports: [FileManagerModule],
standalone: true,
selector: 'app-root',
template: `<div class='advanced-demo'>
<div class='header'>
<h2>Advanced File Manager</h2>
<div class='actions'>
<button (click)='selectAll()'>Select All</button>
<button (click)='clearSelection()'>Clear</button>
<span class='selection-stats'>
{{ selectedCount }} selected ({{ formattedSize }})
</span>
</div>
</div>
<div class='status-bar' [ngClass]='statusClass'>
{{ statusMessage }}
</div>
<ejs-filemanager
#fileManager
[ajaxSettings]='ajaxSettings'
[enablePersistence]='true'
[allowMultiSelection]='true'
(created)='onCreate($event)'
(fileSelection)='onSelection($event)'
(success)='onSuccess($event)'
(failure)='onFailure($event)'
height="500px">
</ejs-filemanager>
</div>`,
styles: [`
.advanced-demo {
display: flex;
flex-direction: column;
height: 100vh;
}
.header {
padding: 15px;
background-color: #f8f9fa;
border-bottom: 1px solid #ddd;
}
.actions {
display: flex;
gap: 10px;
margin-top: 10px;
align-items: center;
}
.status-bar {
padding: 10px 15px;
border-bottom: 1px solid #ddd;
font-weight: 500;
}
.status-bar.success {
background-color: #d4edda;
color: #155724;
}
.status-bar.error {
background-color: #f8d7da;
color: #721c24;
}
.selection-stats {
margin-left: auto;
font-size: 0.9em;
color: #666;
}
`]
})
export class AppComponent {
@ViewChild('fileManager')
public fileManager?: FileManagerComponent;
public selectedCount: number = 0;
public totalSize: number = 0;
public statusMessage: string = 'Ready';
public statusClass: string = '';
public ajaxSettings = {
url: '/api/FileManager/FileOperations'
};
get formattedSize(): string {
const units = ['B', 'KB', 'MB', 'GB'];
let size = this.totalSize;
let unitIndex = 0;
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024;
unitIndex++;
}
return `${size.toFixed(2)} ${units[unitIndex]}`;
}
onCreate(args: any) {
this.statusMessage = 'File Manager ready';
}
onSelection(args: any) {
const selected = this.fileManager?.selectedItems || [];
this.selectedCount = selected.length;
this.totalSize = selected.reduce((sum, file) =>
sum + (file.size || 0), 0);
}
onSuccess(args: any) {
this.statusClass = 'success';
this.statusMessage = `✓ ${args.action} completed`;
setTimeout(() => this.statusClass = '', 3000);
}
onFailure(args: any) {
this.statusClass = 'error';
this.statusMessage = `✗ ${args.action} failed`;
setTimeout(() => this.statusClass = '', 3000);
}
selectAll() {
this.fileManager?.selectAll();
}
clearSelection() {
this.fileManager?.clearSelection();
}
}---
Next: Customize appearance at customization-styling.md or add localization at localization-and-rtl.md.
Complete API Reference for Syncfusion Angular File Manager
Table of Contents
---
Component Properties
Core Configuration Properties
| Property | Type | Default | Description |
|---|---|---|---|
ajaxSettings | AjaxSettingsModel | - | Specifies the AJAX settings for server-side file operations (URLs for file operations, upload, download, getImage) |
fileSystemData | { [key: string]: Object }[] | - | Array of file/folder data for client-side binding (alternative to ajaxSettings) |
path | string | / | Initial directory path to display |
view | ViewType | LargeIcons | Initial view mode: 'Details' or 'LargeIcons' |
height | string \ | number | 400px |
width | string \ | number | 100% |
locale | string | `` | Localization culture (e.g., 'de-DE', 'ja-JP', 'es-ES') |
cssClass | string | `` | Custom CSS class for theming and styling |
rootAliasName | string | null | Specifies the root folder alias name in file manager |
sortBy | string | name | Specifies the field name being used as the sorting criteria |
sortOrder | SortOrder | Ascending | Specifies the file/folder sorting order ('None', 'Ascending', 'Descending') |
popupTarget | HTMLElement \ | string | null |
Selection and Multi-Selection
| Property | Type | Default | Description |
|---|---|---|---|
allowMultiSelection | boolean | true | Enable multiple file/folder selection with Ctrl+Click or Shift+Click |
enableRangeSelection | boolean | false | Allow drag-based multiple selection like Windows Explorer |
showItemCheckBoxes | boolean | true | Determines whether to display checkboxes in the file manager |
selectedItems | string[] | [] | (Read-only) Array of currently selected file/folder IDs or names |
File Operations
| Property | Type | Default | Description |
|---|---|---|---|
allowDragAndDrop | boolean | false | Enable drag-and-drop file/folder movement |
uploadSettings | UploadSettingsModel | - | Configuration for file upload (maxFileSize, minFileSize, autoUpload, allowedExtensions) |
searchSettings | SearchSettingsModel | - | Search configuration (filterType, allowSearchOnTyping, caseSensitive) |
Display and Behavior
| Property | Type | Default | Description |
|---|---|---|---|
showThumbnail | boolean | true | Display thumbnails for image files |
showFileExtension | boolean | true | Shows or hides the file extension in file manager |
showHiddenItems | boolean | false | Determines whether to show or hide hidden files and folders |
enablePersistence | boolean | false | Persist view, path, and selected items across page reload |
enableVirtualization | boolean | false | Enable UI virtualization for large file sets (1000+ items) |
enableRtl | boolean | false | Enable right-to-left layout for RTL languages |
enableHtmlSanitizer | boolean | true | Sanitize HTML content for security (prevent XSS) |
UI Customization
| Property | Type | Description |
|---|---|---|
detailsViewSettings | DetailsViewSettingsModel | Configure details view columns, sorting, gridlines |
navigationPaneSettings | NavigationPaneSettingsModel | Configure left sidebar (folders/favorites) |
navigationPaneTemplate | string \ | object |
largeIconsTemplate | string \ | object |
toolbarSettings | ToolbarSettingsModel | Configure toolbar items and display |
contextMenuSettings | ContextMenuSettingsModel | Configure context menu items |
Sorting and Comparison
| Property | Type | Description |
|---|---|---|
sortComparer | Function | Custom comparison function for sorting files/folders (Windows Explorer-like sorting available) |
---
Component Methods
Navigation Methods
// Navigate to a specific path
openFile(id: string): void
// Move back one level in the folder hierarchy
traverseBackward(): void
// Refresh the current folder contents
refreshFiles(): void
// Refresh the entire layout
refreshLayout(): voidFile/Folder Operations Methods
// Create a new folder
createFolder(name?: string): void
// If name is provided, creates folder directly; otherwise opens new folder dialog
// Delete files/folders
deleteFiles(ids?: string[]): void
// If IDs provided, deletes those items; otherwise deletes selected items
// Rename a file/folder
renameFile(id?: string, name?: string): void
// If both parameters provided, renames directly; otherwise opens rename dialog
// Download files/folders
downloadFiles(ids?: string[]): void
// If IDs provided, downloads those items; otherwise downloads selected items
// Open upload dialog
uploadFiles(): voidSelection Methods
// Select all files/folders in current path
selectAll(): void
// Deselect all currently selected items
clearSelection(): void
// Get details of selected files
getSelectedFiles(): Object[]Toolbar and Menu Methods
// Enable specific toolbar items
enableToolbarItems(items: string[]): void
// Disable specific toolbar items
disableToolbarItems(items: string[]): void
// Enable specific context menu items
enableMenuItems(items: string[]): void
// Disable specific context menu items
disableMenuItems(items: string[]): void
// Get index position of toolbar item
getToolbarItemIndex(item: string): number
// Get index position of menu item
getMenuItemIndex(item: string): numberDialog Methods
// Programmatically close open dialogs
closeDialog(): voidFiltering Methods
// Display custom filtered files
filterFiles(filterData?: Object): void
// filterData should include custom action name and filter detailsLifecycle Methods
// Destroy the component
destroy(): void---
Component Events
File Selection Events
| Event | EventArgs | Description |
|---|---|---|
fileSelect | FileSelectEventArgs | Fires when a file/folder is selected or unselected |
fileSelection | FileSelectionEventArgs | Fires before a file/folder is selected (can prevent selection) |
File Opening Events
| Event | EventArgs | Description |
|---|---|---|
fileOpen | FileOpenEventArgs | Fires before opening a file/folder (double-click or Enter) |
fileLoad | FileLoadEventArgs | Fires before rendering each file/folder item |
File Operation Events
| Event | EventArgs | Description |
|---|---|---|
beforeDelete | DeleteEventArgs | Fires before deleting a file/folder (can prevent deletion) |
delete | DeleteEventArgs | Fires after successful deletion |
beforeRename | RenameEventArgs | Fires before renaming a file/folder (can prevent rename) |
beforeFolderCreate | FolderCreateEventArgs | Fires before creating a folder (can prevent creation) |
folderCreate | FolderCreateEventArgs | Fires after successfully creating a folder |
beforeMove | MoveEventArgs | Fires before moving a file/folder (cut/paste) |
Drag and Drop Events
| Event | EventArgs | Description |
|---|---|---|
fileDragStart | FileDragEventArgs | Fires when drag operation starts |
fileDragging | FileDragEventArgs | Fires while dragging files/folders |
fileDragStop | FileDragEventArgs | Fires before dropping files/folders (can prevent drop) |
fileDropped | FileDragEventArgs | Fires after dropping files/folders |
Server Communication Events
| Event | EventArgs | Description |
|---|---|---|
beforeSend | BeforeSendEventArgs | Fires before sending AJAX request (customize request params) |
success | SuccessEventArgs | Fires after successful AJAX response |
failure | FailureEventArgs | Fires when AJAX request fails |
beforeDownload | BeforeDownloadEventArgs | Fires before download request to server |
beforeImageLoad | BeforeImageLoadEventArgs | Fires before loading images from server |
Dialog and Menu Events
| Event | EventArgs | Description |
|---|---|---|
beforePopupOpen | BeforePopupOpenCloseEventArgs | Fires before opening dialogs (can prevent opening) |
popupOpen | PopupOpenCloseEventArgs | Fires after opening dialogs (informational, cannot prevent) |
beforePopupClose | BeforePopupOpenCloseEventArgs | Fires before closing dialogs (can prevent closing) |
popupClose | PopupOpenCloseEventArgs | Fires after closing dialogs (informational) |
menuOpen | MenuOpenEventArgs | Fires before opening context menu |
menuClose | MenuCloseEventArgs | Fires before closing context menu |
menuClick | MenuClickEventArgs | Fires when context menu item is clicked |
toolbarCreate | ToolbarCreateEventArgs | Fires when toolbar is created (customize toolbar items) |
toolbarClick | ToolbarClickEventArgs | Fires when toolbar item is clicked |
Component Lifecycle Events
| Event | EventArgs | Description |
|---|---|---|
created | Object | Fires when component is created and initialized |
destroyed | Object | Fires when component is destroyed |
---
FileData Interface
The fileData interface defines the structure for files and folders in client-side data binding.
Required Properties
interface FileData {
// Unique identifier
id: string | number;
// File or folder name
name: string;
// Whether item is a file (true) or folder (false)
isFile: boolean;
// Parent folder ID (null/undefined for root items, use parentId for nested structure)
parentId?: string | number | null;
}Optional Properties for Enhanced Display
interface FileData {
// File size in bytes
size?: number;
// Last modified date
dateModified?: Date;
// Date created
dateCreated?: Date;
// File type/extension
type?: string;
// Whether folder has child items
hasChild?: boolean;
// Custom image URL for thumbnail
imageUrl?: string;
// Filter path for traversal (internally managed)
filterPath?: string;
// Access control permissions
permission?: {
read?: boolean;
readContent?: boolean;
write?: boolean;
writeContent?: boolean;
delete?: boolean;
download?: boolean;
upload?: boolean;
copy?: boolean;
};
}Example FileData Structure
// Basic flat structure with complete fields
const flatData = [
{
id: '0',
name: 'Files',
isFile: false,
parentId: undefined,
hasChild: true,
size: 1779448,
type: 'folder',
dateCreated: new Date('2023-11-15T19:02:02.3419426+05:30'),
dateModified: new Date('2024-01-08T18:16:38.4384894+05:30'),
filterPath: ''
},
{
id: '1',
name: 'Documents',
isFile: false,
parentId: '0',
hasChild: true,
size: 680786,
type: 'folder',
dateCreated: new Date('2023-11-15T19:02:02.3419426+05:30'),
dateModified: new Date('2024-01-08T16:55:20.9464164+05:30'),
filterPath: '\\'
},
{
id: '2',
name: 'Resume.pdf',
isFile: true,
parentId: '1',
hasChild: false,
size: 204800,
type: 'pdf',
dateCreated: new Date('2023-11-16T10:22:00.0000000+05:30'),
dateModified: new Date('2024-01-10T14:30:00.0000000+05:30'),
filterPath: '\\Files\\Documents\\'
},
{
id: '3',
name: 'Photo.jpg',
isFile: true,
parentId: '1',
hasChild: false,
size: 2048000,
type: 'jpg',
dateCreated: new Date('2023-11-17T08:15:00.0000000+05:30'),
dateModified: new Date('2024-01-11T11:45:00.0000000+05:30'),
filterPath: '\\Files\\Documents\\'
}
];Note: All fileData items should include these core fields:
id- Unique identifier (string)name- File/folder name (string)isFile- Whether item is a file (boolean)parentId- Parent folder ID or undefined for root (string | undefined)hasChild- Whether folder has children (boolean)size- Size in bytes (number)type- File type or 'folder' (string)dateCreated- Creation date (Date)dateModified- Last modification date (Date)filterPath- Hierarchical path (string)
Flat Data with Permissions (Advanced Example)
// Comprehensive flat data structure with access control permissions
export class FileManagerComponent {
// Define permission object for access control
public permission = {
copy: false,
download: false,
write: false,
writeContents: false,
read: true,
upload: false,
message: '',
};
public fileSystemData: { [key: string]: Object }[] = [
{
dateCreated: new Date('2023-11-15T19:02:02.3419426+05:30'),
dateModified: new Date('2024-01-08T18:16:38.4384894+05:30'),
filterPath: '',
hasChild: true,
id: '0',
isFile: false,
name: 'Files',
parentId: undefined,
size: 1779448,
type: 'folder',
},
{
dateCreated: new Date('2023-11-15T19:02:02.3419426+05:30'),
dateModified: new Date('2024-01-08T16:55:20.9464164+05:30'),
filterPath: '\\',
hasChild: true,
id: '1',
isFile: false,
name: 'Documents',
parentId: '0',
size: 680786,
type: 'folder',
permission: this.permission,
},
{
dateCreated: new Date('2023-11-16T10:22:00.0000000+05:30'),
dateModified: new Date('2024-01-09T14:30:00.0000000+05:30'),
filterPath: '\\Files\\Documents\\',
hasChild: false,
id: '2',
isFile: true,
name: 'ProjectProposal.pdf',
parentId: '1',
size: 256000,
type: 'pdf',
},
{
dateCreated: new Date('2023-11-17T08:15:00.0000000+05:30'),
dateModified: new Date('2024-01-10T11:45:00.0000000+05:30'),
filterPath: '\\Files\\Documents\\',
hasChild: false,
id: '3',
isFile: true,
name: 'Budget.xlsx',
parentId: '1',
size: 128000,
type: 'xlsx',
},
{
dateCreated: new Date('2023-11-18T14:30:00.0000000+05:30'),
dateModified: new Date('2024-01-11T09:20:00.0000000+05:30'),
filterPath: '\\Files\\',
hasChild: false,
id: '4',
isFile: true,
name: 'README.txt',
parentId: '0',
size: 4096,
type: 'txt',
}
];
}Permission Properties Used:
copy: false- Disables copying filesdownload: false- Disables file downloadswrite: false- Disables file renaming/editingwriteContents: false- Disables content modificationread: true- Allows viewing filesupload: false- Disables file uploadsmessage: ''- Custom restriction message
---
Support Services
Module Imports and Providers
The following services should be provided for specific features:
import {
FileManagerModule,
NavigationPaneService,
DetailsViewService,
ToolbarService,
VirtualizationService
} from '@syncfusion/ej2-angular-filemanager';
@Component({
imports: [FileManagerModule],
providers: [
NavigationPaneService, // For left sidebar navigation
DetailsViewService, // For details view with sorting/columns
ToolbarService, // For toolbar functionality
VirtualizationService // For virtualization (large datasets)
]
})
export class FileManagerComponent { }Static Utility Functions
import { FileManager } from '@syncfusion/ej2-filemanager';
// Check if fileSystemData is being used (not ajaxSettings)
const isLocalData = FileManager.isFileSystemData(fileManagerInstance);
// Sort comparison function (Windows Explorer-like natural sorting)
const sortResult = FileManager.sortComparer(
'file1.txt', // first string
'file2.txt' // second string
);
// Trigger fetch success event
FileManager.triggerFetchSuccess(instance, ajaxSettings);
// Trigger fetch failure event
FileManager.triggerFetchFailure(instance, ajaxSettings, errorResult);---
Configuration Models Reference
AjaxSettingsModel
ajaxSettings = {
url: '/api/FileManager/FileOperations',
getImageUrl: '/api/FileManager/GetImage',
uploadUrl: '/api/FileManager/Upload',
downloadUrl: '/api/FileManager/Download'
};UploadSettingsModel
Configures file upload behavior and validation for the File Manager component.
Properties:
| Property | Type | Default | Description |
|---|---|---|---|
allowedExtensions | string | `` | Specifies the extensions of the file types allowed in the file manager component. Pass extensions with comma separators (e.g., ".jpg,.png"). |
autoClose | boolean | false | Defines whether to close the upload dialog after uploading all the files. |
autoUpload | boolean | true | By default, the FileManager component initiates automatic upload when files are added to the upload queue. Disable this to manipulate files before uploading. The buttons "upload" and "clear" are hidden from the file list when autoUpload is true. |
chunkSize | number | - | Specifies the chunk size (in bytes) to split large files into chunks and upload sequentially. If specified, chunk upload is enabled by default. |
directoryUpload | boolean | false | Specifies whether folders (directories) can be browsed and uploaded. When enabled, all folder contents including hierarchy folders and files are uploaded. Supported for: Physical, NodeJS, Azure, and Amazon S3 providers. |
maxFileSize | number | 104857600 | Specifies the maximum allowed file size to be uploaded in bytes. Prevents uploading too large files. |
minFileSize | number | 0 | Specifies the minimum file size to be uploaded in bytes. Prevents uploading empty files and small files. |
sequentialUpload | boolean | false | Specifies whether files are uploaded sequentially (one at a time). When enabled, reduces network load for large files. |
Configuration Example:
uploadSettings = {
maxFileSize: 104857600, // 100MB in bytes
minFileSize: 0,
autoUpload: true,
autoClose: false,
allowedExtensions: '.jpg,.png,.pdf',
directoryUpload: false,
sequentialUpload: false,
chunkSize: 5242880 // 5MB chunks for large files
};SearchSettingsModel
searchSettings = {
allowSearchOnTyping: true,
caseSensitive: false,
filterType: 'StartsWith' // 'Contains', 'StartsWith', 'EndsWith'
};DetailsViewSettingsModel
detailsViewSettings = {
columns: [
{ field: 'name', headerText: 'Name', width: '30%' },
{ field: 'dateModified', headerText: 'Date Modified', width: '30%' },
{ field: 'type', headerText: 'Type', width: '15%' },
{ field: 'size', headerText: 'Size', width: '15%' }
]
};NavigationPaneSettingsModel
navigationPaneSettings = {
visible: true,
minWidth: '150px',
maxWidth: '500px'
};ToolbarSettingsModel
toolbarSettings = {
items: [
'NewFolder',
'Upload',
'Cut',
'Copy',
'Paste',
'Delete',
'Download',
'Rename',
'SortBy',
'Refresh',
'Selection',
'View',
'Details'
],
visible: true
};ContextMenuSettingsModel
contextMenuSettings = {
file: ['Open', '|', 'Cut', 'Copy', '|', 'Delete', 'Rename', '|', 'Details'],
folder: ['Open', '|', 'Cut', 'Copy', 'Paste', '|', 'Delete', 'Rename', '|', 'Details'],
layout: ['SortBy', 'View', 'Refresh', '|', 'Paste', '|', 'NewFolder', 'Upload', '|', 'Details', '|', 'SelectAll'],
visible: true
};---
Best Practices for API Usage
1. Accessing Component Methods with ViewChild
import { FileManagerComponent } from '@syncfusion/ej2-angular-filemanager';
@Component({
selector: 'app-root',
template: `
<ejs-filemanager #fileManager [ajaxSettings]="ajaxSettings">
</ejs-filemanager>
`
})
export class AppComponent implements AfterViewInit {
@ViewChild('fileManager')
fileManager?: FileManagerComponent;
ngAfterViewInit() {
// Now you can call methods
this.fileManager?.selectAll();
}
}2. Handling Events Properly
onFileSelect(args: FileSelectEventArgs) {
console.log('Selected files:', args.fileDetails);
console.log('Selection type:', args.isSelectAll);
}
onBeforeDelete(args: DeleteEventArgs) {
// Prevent deletion of system files
if (args.fileDetails[0].name.startsWith('.')) {
args.cancel = true; // Prevent deletion
}
}3. Programmatic File Operations
// Delete selected files with confirmation
deleteSelected() {
const selected = this.fileManager?.selectedItems;
if (selected && selected.length > 0) {
if (confirm(`Delete ${selected.length} items?`)) {
this.fileManager?.deleteFiles();
}
}
}4. Custom Sorting Implementation
import { FileManager } from '@syncfusion/ej2-filemanager';
sortComparer = (a: string, b: string): number => {
return FileManager.sortComparer(a, b); // Windows Explorer-like sorting
}Authentication and Custom Values in Syncfusion Angular File Manager
Overview
The FileManager can be configured to send authentication tokens and custom values with requests to the backend. This allows you to implement secure file access control and pass additional context (user ID, role, etc.) with each operation.
Table of Contents
- beforeSend Event
- JWT Token Authentication
- Bearer Token Implementation
- Custom Headers
- Custom Data Passing
- CORS Configuration
- Examples
---
beforeSend Event
The beforeSend event fires before each request to the server. Use it to modify request headers, add authentication tokens, and pass custom data.
Basic beforeSend Setup
import { Component } from '@angular/core';
import { BeforeSendEventArgs } from '@syncfusion/ej2-filemanager';
@Component({
selector: 'app-file-manager',
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforeSend)='onBeforeSend($event)'>
</ejs-filemanager>`
})
export class AppComponent {
ajaxSettings = {
url: '/api/FileManager/FileOperations',
uploadUrl: '/api/FileManager/Upload',
downloadUrl: '/api/FileManager/Download',
getImageUrl: '/api/FileManager/GetImage'
};
onBeforeSend(args: BeforeSendEventArgs) {
// Set request headers
args.ajaxSettings.headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.getToken()}`
};
}
private getToken(): string {
// Retrieve JWT token from localStorage or auth service
return localStorage.getItem('authToken') || '';
}
}---
JWT Token Authentication
Implement JWT Token with FileManager
import { Component } from '@angular/core';
import { AuthService } from './services/auth.service';
import { BeforeSendEventArgs } from '@syncfusion/ej2-filemanager';
@Component({
selector: 'app-secure-filemanager',
template: `<div>
<h3>Secure File Manager</h3>
<p>Authenticated as: {{ currentUser?.name }}</p>
<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforeSend)='onBeforeSend($event)'>
</ejs-filemanager>
</div>`
})
export class SecureFileManagerComponent {
currentUser: any;
ajaxSettings = {
url: '/api/FileManager/FileOperations',
uploadUrl: '/api/FileManager/Upload',
downloadUrl: '/api/FileManager/Download'
};
constructor(private authService: AuthService) {
this.currentUser = this.authService.getCurrentUser();
}
onBeforeSend(args: BeforeSendEventArgs) {
// Get JWT token from auth service
const token = this.authService.getToken();
// Set authorization header
args.ajaxSettings.headers = {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
};
}
}
// AuthService implementation
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private currentUserSubject = new BehaviorSubject<any>(null);
public currentUser$ = this.currentUserSubject.asObservable();
private tokenKey = 'authToken';
constructor(private http: HttpClient) {
this.loadUserFromStorage();
}
login(username: string, password: string) {
return this.http.post<any>('/api/auth/login', { username, password })
.subscribe(response => {
if(response.token) {
// Store JWT token
localStorage.setItem(this.tokenKey, response.token);
this.currentUserSubject.next(response.user);
}
});
}
logout() {
localStorage.removeItem(this.tokenKey);
this.currentUserSubject.next(null);
}
getToken(): string {
return localStorage.getItem(this.tokenKey) || '';
}
getCurrentUser() {
return this.currentUserSubject.value;
}
private loadUserFromStorage() {
const token = this.getToken();
if(token) {
// Decode JWT token to get user info
const user = this.decodeToken(token);
this.currentUserSubject.next(user);
}
}
private decodeToken(token: string): any {
try {
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const jsonPayload = decodeURIComponent(
atob(base64).split('').map((c: string) => {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join('')
);
return JSON.parse(jsonPayload);
} catch(e) {
return null;
}
}
}---
Bearer Token Implementation
Complete Bearer Token Authentication
@Component({
selector: 'app-bearer-auth-filemanager',
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforeSend)='onBeforeSend($event)'>
</ejs-filemanager>`
})
export class BearerAuthFileManagerComponent implements OnInit {
ajaxSettings = {
url: '/api/FileManager/FileOperations',
uploadUrl: '/api/FileManager/Upload',
downloadUrl: '/api/FileManager/Download'
};
bearerToken = '';
constructor(private authService: AuthService) {}
ngOnInit() {
// Get bearer token from auth service
this.authService.token$.subscribe(token => {
this.bearerToken = token;
});
}
onBeforeSend(args: BeforeSendEventArgs) {
// Add Bearer token to all requests
if(this.bearerToken) {
args.ajaxSettings.headers = {
'Authorization': `Bearer ${this.bearerToken}`,
'X-Requested-With': 'XMLHttpRequest'
};
}
}
}
// Backend controller with bearer token validation
import { Microsoft.AspNetCore.Authorization };
import { Microsoft.AspNetCore.Mvc };
[ApiController]
[Route("api/[controller]")]
[Authorize(AuthenticationSchemes = "Bearer")]
public class FileManagerController : ControllerBase
{
private readonly IAuthService _authService;
[HttpPost("FileOperations")]
[Authorize]
public IActionResult FileOperations(
[FromBody] FileRequest request,
[FromHeader(Name = "Authorization")] string authHeader)
{
try
{
// Extract token from Authorization header
var token = authHeader?.Replace("Bearer ", "").Trim();
if(string.IsNullOrEmpty(token))
{
return Unauthorized(new { error = "No authorization token provided" });
}
// Validate token and get user claims
var claims = _authService.ValidateToken(token);
if(claims == null)
{
return Unauthorized(new { error = "Invalid or expired token" });
}
var userId = claims.FindFirst("sub")?.Value;
var userRole = claims.FindFirst("role")?.Value;
// Process request with user context
var result = HandleFileOperation(request, userId, userRole);
return Ok(result);
}
catch(Exception ex)
{
return StatusCode(500, new { error = ex.Message });
}
}
private object HandleFileOperation(FileRequest request, string userId, string userRole)
{
// Implementation...
return new { };
}
}---
Custom Headers
Add Custom Headers to All Requests
@Component({
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforeSend)='onBeforeSend($event)'>
</ejs-filemanager>`
})
export class CustomHeadersFileManagerComponent {
ajaxSettings = {
url: '/api/FileManager/FileOperations',
uploadUrl: '/api/FileManager/Upload',
downloadUrl: '/api/FileManager/Download'
};
onBeforeSend(args: BeforeSendEventArgs) {
// Add multiple custom headers
args.ajaxSettings.headers = {
'Authorization': `Bearer ${this.getToken()}`,
'X-API-Key': 'your-api-key',
'X-User-ID': this.getUserId(),
'X-Request-ID': this.generateRequestId(),
'X-Client-Version': '1.0.0',
'X-Correlation-ID': this.getCorrelationId(),
'Accept': 'application/json',
'Content-Type': 'application/json'
};
}
private getToken(): string {
return localStorage.getItem('authToken') || '';
}
private getUserId(): string {
return localStorage.getItem('userId') || '';
}
private generateRequestId(): string {
return `REQ-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
private getCorrelationId(): string {
let correlationId = sessionStorage.getItem('correlationId');
if(!correlationId) {
correlationId = `COR-${Date.now()}`;
sessionStorage.setItem('correlationId', correlationId);
}
return correlationId;
}
}---
Custom Data Passing
Pass Custom Data with Requests
@Component({
selector: 'app-custom-data-filemanager',
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforeSend)='onBeforeSend($event)'>
</ejs-filemanager>`
})
export class CustomDataFileManagerComponent {
ajaxSettings = {
url: '/api/FileManager/FileOperations',
uploadUrl: '/api/FileManager/Upload',
downloadUrl: '/api/FileManager/Download'
};
userContext = {
userId: 'user-123',
role: 'Editor',
department: 'Engineering'
};
onBeforeSend(args: BeforeSendEventArgs) {
// Add custom data to request body
if(args.data && typeof args.data === 'object') {
// Add user context
args.data['userId'] = this.userContext.userId;
args.data['role'] = this.userContext.role;
args.data['department'] = this.userContext.department;
// Add timestamp
args.data['requestTime'] = new Date().toISOString();
// Add custom metadata
args.data['clientInfo'] = {
userAgent: navigator.userAgent,
language: navigator.language,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
};
}
}
}
// Backend receiving custom data
[HttpPost("FileOperations")]
public IActionResult FileOperations([FromBody] FileRequestWithContext request)
{
var userId = request.userId;
var userRole = request.role;
var requestTime = request.requestTime;
// Log audit information
_logger.LogInformation(
$"File operation {request.action} by user {userId} ({userRole}) at {requestTime}"
);
// Process request...
return Ok();
}Pass Query Parameters
@Component({
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforeSend)='onBeforeSend($event)'>
</ejs-filemanager>`
})
export class QueryParamFileManagerComponent {
ajaxSettings = {
url: '/api/FileManager/FileOperations',
uploadUrl: '/api/FileManager/Upload',
downloadUrl: '/api/FileManager/Download'
};
onBeforeSend(args: BeforeSendEventArgs) {
// Modify URL with query parameters
const url = new URL(args.ajaxSettings.url, window.location.origin);
url.searchParams.append('userId', 'user-123');
url.searchParams.append('locale', 'en-US');
url.searchParams.append('apiVersion', '2.0');
args.ajaxSettings.url = url.pathname + url.search;
}
}---
CORS Configuration
Enable CORS on Backend
// Startup.cs or Program.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Enable CORS
services.AddCors(options =>
{
options.AddPolicy("FileManagerPolicy", builder =>
{
builder
.WithOrigins(
"http://localhost:4200",
"http://localhost:3000",
"yourdomain"
)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
.WithExposedHeaders(
"Content-Disposition",
"X-Total-Count",
"X-Page-Count"
);
});
});
services.AddControllers();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseCors("FileManagerPolicy");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}CORS in FileManager Ajax Settings
@Component({
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforeSend)='onBeforeSend($event)'>
</ejs-filemanager>`
})
export class CorsFileManagerComponent {
ajaxSettings = {
url: 'url',
uploadUrl: 'url',
downloadUrl: 'url',
credentials: 'include' // Include cookies in CORS requests
};
onBeforeSend(args: BeforeSendEventArgs) {
args.ajaxSettings.headers = {
'Authorization': `Bearer ${this.getToken()}`
};
}
private getToken(): string {
return localStorage.getItem('authToken') || '';
}
}---
Examples
Example 1: OAuth2 Token Refresh
@Component({
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforeSend)='onBeforeSend($event)'>
</ejs-filemanager>`
})
export class OAuth2FileManagerComponent {
@ViewChild('fileManager')
fileManager?: FileManagerComponent;
ajaxSettings = {
url: '/api/FileManager/FileOperations',
uploadUrl: '/api/FileManager/Upload',
downloadUrl: '/api/FileManager/Download'
};
constructor(private authService: AuthService) {}
onBeforeSend(args: BeforeSendEventArgs) {
// Check if token is about to expire
const token = this.authService.getToken();
const isExpiringSoon = this.authService.isTokenExpiringSoon(token);
if(isExpiringSoon) {
// Refresh token before making request
this.authService.refreshToken().then(newToken => {
args.ajaxSettings.headers = {
'Authorization': `Bearer ${newToken}`
};
});
} else {
args.ajaxSettings.headers = {
'Authorization': `Bearer ${token}`
};
}
}
}Example 2: Multi-Tenant File Manager
@Component({
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforeSend)='onBeforeSend($event)'>
</ejs-filemanager>`
})
export class MultiTenantFileManagerComponent {
ajaxSettings = {
url: '/api/FileManager/FileOperations',
uploadUrl: '/api/FileManager/Upload',
downloadUrl: '/api/FileManager/Download'
};
tenantId = 'tenant-abc-123';
userId = 'user-456';
onBeforeSend(args: BeforeSendEventArgs) {
// Add tenant information to headers
args.ajaxSettings.headers = {
'Authorization': `Bearer ${this.getToken()}`,
'X-Tenant-ID': this.tenantId,
'X-User-ID': this.userId,
'X-Organization-ID': 'org-789'
};
// Add tenant context to request body
if(args.data && typeof args.data === 'object') {
args.data['tenantId'] = this.tenantId;
args.data['userId'] = this.userId;
}
}
private getToken(): string {
return localStorage.getItem('authToken') || '';
}
}
// Backend multi-tenant handler
[ApiController]
[Route("api/[controller]")]
public class FileManagerController : ControllerBase
{
[HttpPost("FileOperations")]
public IActionResult FileOperations(
[FromBody] FileRequest request,
[FromHeader(Name = "X-Tenant-ID")] string tenantId,
[FromHeader(Name = "X-User-ID")] string userId)
{
try
{
// Validate tenant access
if(!_tenantService.CanUserAccessTenant(userId, tenantId))
{
return Forbid();
}
// Scope all operations to tenant
var tenantContext = new TenantContext { TenantId = tenantId, UserId = userId };
var result = HandleFileOperation(request, tenantContext);
return Ok(result);
}
catch(Exception ex)
{
return StatusCode(500, new { error = ex.Message });
}
}
}Example 3: Request Logging and Audit Trail
@Component({
template: `<ejs-filemanager
[ajaxSettings]='ajaxSettings'
(beforeSend)='onBeforeSend($event)'>
</ejs-filemanager>`
})
export class AuditedFileManagerComponent {
ajaxSettings = {
url: '/api/FileManager/FileOperations',
uploadUrl: '/api/FileManager/Upload',
downloadUrl: '/api/FileManager/Download'
};
onBeforeSend(args: BeforeSendEventArgs) {
const requestId = this.generateRequestId();
const timestamp = new Date().toISOString();
// Add audit headers
args.ajaxSettings.headers = {
'Authorization': `Bearer ${this.getToken()}`,
'X-Request-ID': requestId,
'X-Timestamp': timestamp,
'X-Source': 'web-filemanager'
};
// Add audit data
if(args.data && typeof args.data === 'object') {
args.data['auditInfo'] = {
requestId: requestId,
timestamp: timestamp,
action: args.data.action,
path: args.data.path,
ipAddress: this.getClientIpAddress()
};
}
// Log to audit service
this.logToAuditService(requestId, args.data);
}
private generateRequestId(): string {
return `REQ-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
private getToken(): string {
return localStorage.getItem('authToken') || '';
}
private getClientIpAddress(): string {
// Get from request if available
return 'client-ip';
}
private logToAuditService(requestId: string, data: any) {
console.log('Audit:', { requestId, action: data?.action, time: new Date() });
}
}---
Best Practices
1. Store tokens securely - Use httpOnly cookies or secure storage 2. Always use HTTPS - Never send tokens over unencrypted connections 3. Validate tokens on backend - Don't trust tokens from client 4. Refresh tokens - Implement token refresh before expiration 5. Limit token scope - Use specific scopes for file operations 6. Add request IDs - Track requests for debugging and audit trails 7. Log all operations - Maintain comprehensive audit logs 8. Handle auth errors - Redirect to login on 401 responses 9. Use CORS properly - Only allow required origins and methods 10. Implement rate limiting - Prevent abuse with request throttling
---
Next: Explore custom file providers at custom-file-provider.md or learn about file operations at file-operations.md.
Context Menu Customization in Syncfusion Angular File Manager
Overview
The FileManager context menu appears when users right-click on files, folders, or empty space. You can customize which items appear in the menu, add custom items, and handle menu events for custom actions.
Table of Contents
- Context Menu Configuration
- Default Context Menu Items
- Adding Custom Menu Items
- Menu Events
- Dynamic Menu Modification
- Custom Menu Actions
- Examples
---
Context Menu Configuration
Basic Setup
@Component({
selector: 'app-file-manager',
template: `<ejs-filemanager
[contextMenuSettings]='contextMenuSettings'>
</ejs-filemanager>`
})
export class AppComponent {
contextMenuSettings = {
// Show context menu for files
file: ['Open', 'Cut', 'Copy', 'Delete', 'Download', 'Rename'],
// Show context menu for folders
folder: ['Open', 'Cut', 'Copy', 'Delete', 'Paste', 'Rename', 'NewFolder'],
// Show context menu for empty layout
layout: ['Paste', 'Refresh', 'NewFolder']
};
}Hide Entire Context Menu
export class AppComponent {
contextMenuSettings = {
visible: false // Disable context menu completely
};
}---
Default Context Menu Items
Available Built-in Items
| Item | Context | Function |
|---|---|---|
Open | File/Folder | Open file or navigate to folder |
Cut | File/Folder | Cut file/folder to clipboard |
Copy | File/Folder | Copy file/folder to clipboard |
Paste | Layout | Paste from clipboard |
Delete | File/Folder | Delete file/folder |
Rename | File/Folder | Rename file/folder |
Download | File/Folder | Download file/folder |
NewFolder | Folder/Layout | Create new folder |
Details | File/Folder | Show file details |
Customize Built-in Items
export class AppComponent {
contextMenuSettings = {
// Minimal file operations
file: ['Copy', 'Download'],
// Basic folder operations
folder: ['NewFolder', 'Delete', 'Rename'],
// Layout operations
layout: ['Refresh']
};
}---
Adding Custom Menu Items
Define Custom Menu Items
import { Component, ViewChild } from '@angular/core';
import { FileManagerComponent } from '@syncfusion/ej2-angular-filemanager';
import { MenuOpenEventArgs } from '@syncfusion/ej2-filemanager';
@Component({
selector: 'app-file-manager',
template: `<ejs-filemanager
#fileManager
[contextMenuSettings]='contextMenuSettings'
(menuOpen)='onMenuOpen($event)'
(menuClick)='onMenuClick($event)'>
</ejs-filemanager>`
})
export class AppComponent {
@ViewChild('fileManager')
fileManager?: FileManagerComponent;
contextMenuSettings = {
file: ['Copy', 'Download', 'Favorite', 'Share', 'Lock'],
folder: ['NewFolder', 'Delete', 'Favorite', 'Share'],
layout: ['Paste', 'Refresh']
};
onMenuOpen(args: MenuOpenEventArgs) {
// Set icons for custom menu items
args.items.forEach((item: any) => {
switch(item.text) {
case 'Favorite':
item.iconCss = 'e-icons e-star-fill';
break;
case 'Share':
item.iconCss = 'e-icons e-share';
break;
case 'Lock':
item.iconCss = 'e-icons e-lock';
break;
}
});
}
onMenuClick(args: MenuClickEventArgs) {
// Handle custom menu item clicks
const selectedFile = this.fileManager?.selectedItems[0];
switch(args.itemText) {
case 'Favorite':
this.addToFavorites(selectedFile);
break;
case 'Share':
this.shareFile(selectedFile);
break;
case 'Lock':
this.lockFile(selectedFile);
break;
}
}
private addToFavorites(file: any) {
console.log('Added to favorites:', file?.name);
}
private shareFile(file: any) {
console.log('Sharing file:', file?.name);
}
private lockFile(file: any) {
console.log('Locked file:', file?.name);
}
}---
Menu Events
menuOpen Event
The menuOpen event fires when context menu is about to open. Use it to:
- Add/remove menu items dynamically
- Set icons for menu items
- Show/hide items based on conditions
- Update menu item properties
@Component({
template: `<ejs-filemanager
(menuOpen)='onMenuOpen($event)'>
</ejs-filemanager>`
})
export class AppComponent {
onMenuOpen(args: MenuOpenEventArgs) {
// Add custom menu items
const customItems = [
{ text: 'Open With', iconCss: 'e-icons e-open' },
{ text: 'Properties', iconCss: 'e-icons e-info' }
];
// Append custom items to menu
args.items = [...args.items, ...customItems];
// Set icons for all items
args.items.forEach((item: any) => {
if(!item.iconCss) {
item.iconCss = 'e-icons e-file'; // Default icon
}
});
}
}menuClose Event
The menuClose event fires when context menu is closing:
@Component({
template: `<ejs-filemanager
(menuClose)='onMenuClose($event)'>
</ejs-filemanager>`
})
export class AppComponent {
onMenuClose(args: MenuCloseEventArgs) {
console.log('Context menu closed');
// Cleanup or reset state if needed
}
}menuClick Event
The menuClick event fires when user clicks a menu item:
@Component({
template: `<ejs-filemanager
(menuClick)='onMenuClick($event)'>
</ejs-filemanager>`
})
export class AppComponent {
onMenuClick(args: MenuClickEventArgs) {
console.log('Menu item clicked:', args.itemText);
console.log('Menu type:', args.menuType); // 'file', 'folder', 'layout'
console.log('Target element:', args.element);
// Prevent default action if needed
args.cancel = true;
}
}---
Dynamic Menu Modification
Show/Hide Items Based on Conditions
@Component({
template: `<ejs-filemanager
(menuOpen)='onMenuOpen($event)'
(menuClick)='onMenuClick($event)'>
</ejs-filemanager>`
})
export class AppComponent {
userRole = 'Editor';
contextMenuSettings = {
file: ['Copy', 'Download', 'Delete', 'Edit', 'Archive'],
folder: ['NewFolder', 'Delete', 'Archive'],
layout: ['Paste', 'Refresh']
};
onMenuOpen(args: MenuOpenEventArgs) {
// Show/hide items based on user role
if(this.userRole === 'Viewer') {
// Remove edit/delete options for viewers
args.items = args.items.filter((item: any) =>
!['Delete', 'Edit', 'Archive'].includes(item.text)
);
}
// Show/hide based on file type
if(args.menuType === 'file') {
const selectedFile = args.fileDetails[0];
const isPDF = selectedFile.name.endsWith('.pdf');
// Only show print for PDFs
if(!isPDF) {
args.items = args.items.filter((item: any) => item.text !== 'Print');
}
}
// Show/hide based on file existence
if(args.menuType === 'layout') {
const hasClipboard = this.hasClipboardContent();
if(!hasClipboard) {
args.items = args.items.filter((item: any) => item.text !== 'Paste');
}
}
}
private hasClipboardContent(): boolean {
// Check if clipboard has valid content
return true;
}
onMenuClick(args: MenuClickEventArgs) {
// Check permissions before executing action
if(this.userRole === 'Viewer' &&
['Delete', 'Edit'].includes(args.itemText)) {
args.cancel = true;
alert('You do not have permission to perform this action');
}
}
}Add Icons to Menu Items
@Component({
template: `<ejs-filemanager
(menuOpen)='onMenuOpen($event)'>
</ejs-filemanager>`
})
export class AppComponent {
onMenuOpen(args: MenuOpenEventArgs) {
const iconMap: { [key: string]: string } = {
'Open': 'e-icons e-open',
'Cut': 'e-icons e-cut',
'Copy': 'e-icons e-copy',
'Paste': 'e-icons e-paste',
'Delete': 'e-icons e-delete',
'Rename': 'e-icons e-rename',
'Download': 'e-icons e-download',
'NewFolder': 'e-icons e-folder-new',
'Details': 'e-icons e-details',
'Favorite': 'e-icons e-star-fill',
'Share': 'e-icons e-share',
'Lock': 'e-icons e-lock',
'Archive': 'e-icons e-zip',
'Edit': 'e-icons e-edit',
'Print': 'e-icons e-print'
};
// Apply icons to all menu items
args.items.forEach((item: any) => {
if(iconMap[item.text]) {
item.iconCss = iconMap[item.text];
}
});
}
}---
Custom Menu Actions
Implement Custom Actions
@Component({
selector: 'app-custom-menu-filemanager',
template: `<ejs-filemanager
#fileManager
[contextMenuSettings]='contextMenuSettings'
(menuOpen)='onMenuOpen($event)'
(menuClick)='onMenuClick($event)'>
</ejs-filemanager>`
})
export class CustomMenuFileManagerComponent {
@ViewChild('fileManager')
fileManager?: FileManagerComponent;
contextMenuSettings = {
file: ['Copy', 'Download', 'Favorite', 'Share', 'GetInfo'],
folder: ['NewFolder', 'Delete', 'Favorite', 'Share', 'Compress'],
layout: ['Paste', 'Refresh', 'CreateFolder']
};
onMenuOpen(args: MenuOpenEventArgs) {
// Add icons
const iconMap: { [key: string]: string } = {
'Favorite': 'e-icons e-star-fill',
'Share': 'e-icons e-share',
'GetInfo': 'e-icons e-info',
'Compress': 'e-icons e-zip',
'CreateFolder': 'e-icons e-folder-new'
};
args.items.forEach((item: any) => {
item.iconCss = iconMap[item.text] || 'e-icons e-file';
});
}
onMenuClick(args: MenuClickEventArgs) {
const selectedFiles = this.fileManager?.selectedItems || [];
switch(args.itemText) {
case 'Favorite':
this.addToFavorites(selectedFiles);
break;
case 'Share':
this.shareFiles(selectedFiles);
break;
case 'GetInfo':
this.showFileInfo(selectedFiles);
break;
case 'Compress':
this.compressFile(selectedFiles);
break;
case 'CreateFolder':
this.createNewFolder();
break;
}
}
private addToFavorites(files: any[]) {
files.forEach(file => {
console.log(`Added "${file.name}" to favorites`);
});
alert(`Added ${files.length} item(s) to favorites`);
}
private shareFiles(files: any[]) {
console.log('Sharing files:', files.map(f => f.name));
alert(`Sharing ${files.length} item(s)`);
}
private showFileInfo(files: any[]) {
if(files.length > 0) {
const file = files[0];
const info = `
Name: ${file.name}
Size: ${file.size} bytes
Modified: ${new Date(file.dateModified).toLocaleString()}
`;
alert(info);
}
}
private compressFile(files: any[]) {
console.log('Compressing:', files.map(f => f.name));
alert(`Compressing ${files.length} item(s) to archive`);
}
private createNewFolder() {
alert('Creating new folder...');
}
}---
Examples
Example 1: Complete Custom Context Menu
@Component({
selector: 'app-advanced-context-menu',
template: `<div class="filemanager-container">
<h3>Advanced File Manager with Custom Context Menu</h3>
<ejs-filemanager
#fileManager
[ajaxSettings]='ajaxSettings'
[contextMenuSettings]='contextMenuSettings'
(menuOpen)='onMenuOpen($event)'
(menuClick)='onMenuClick($event)'
height="500px">
</ejs-filemanager>
</div>`
})
export class AdvancedContextMenuComponent {
@ViewChild('fileManager')
fileManager?: FileManagerComponent;
ajaxSettings = {
url: '/api/FileManager/FileOperations',
uploadUrl: '/api/FileManager/Upload'
};
contextMenuSettings = {
file: [
'Copy',
'Download',
'Favorite',
'Tag',
'Share',
'GetProperties',
'Delete'
],
folder: [
'NewFolder',
'Copy',
'Favorite',
'Share',
'Compress',
'Delete'
],
layout: [
'Paste',
'Refresh',
'NewFolder'
]
};
onMenuOpen(args: MenuOpenEventArgs) {
// Set comprehensive icon mapping
const iconMap: { [key: string]: string } = {
'Open': 'e-icons e-open',
'Cut': 'e-icons e-cut',
'Copy': 'e-icons e-copy',
'Paste': 'e-icons e-paste',
'Delete': 'e-icons e-delete',
'Rename': 'e-icons e-rename',
'Download': 'e-icons e-download',
'NewFolder': 'e-icons e-folder-new',
'Details': 'e-icons e-details',
'Favorite': 'e-icons e-star-fill',
'Tag': 'e-icons e-tag',
'Share': 'e-icons e-share',
'GetProperties': 'e-icons e-info',
'Compress': 'e-icons e-zip',
'Refresh': 'e-icons e-refresh'
};
// Apply icons
args.items.forEach((item: any) => {
item.iconCss = iconMap[item.text] || 'e-icons e-file';
});
}
onMenuClick(args: MenuClickEventArgs) {
const selectedFiles = this.fileManager?.selectedItems || [];
switch(args.itemText) {
case 'Favorite':
this.toggleFavorite(selectedFiles);
break;
case 'Tag':
this.assignTag(selectedFiles);
break;
case 'Share':
this.openShareDialog(selectedFiles);
break;
case 'GetProperties':
this.showProperties(selectedFiles);
break;
case 'Compress':
this.compressFiles(selectedFiles);
break;
case 'Refresh':
this.fileManager?.refresh();
break;
}
}
private toggleFavorite(files: any[]) {
console.log('Toggling favorite for:', files.map(f => f.name));
}
private assignTag(files: any[]) {
const tag = prompt('Enter tag name:');
if(tag) {
console.log(`Tagged ${files.length} item(s) with "${tag}"`);
}
}
private openShareDialog(files: any[]) {
console.log('Opening share dialog for:', files.map(f => f.name));
}
private showProperties(files: any[]) {
if(files.length > 0) {
const file = files[0];
console.log('Properties:', file);
}
}
private compressFiles(files: any[]) {
console.log('Compressing:', files.map(f => f.name));
}
}Example 2: Context Menu with Confirmation Dialog
@Component({
template: `<ejs-filemanager
#fileManager
[contextMenuSettings]='contextMenuSettings'
(menuClick)='onMenuClick($event)'>
</ejs-filemanager>
<ejs-dialog
#confirmDialog
[header]="'Confirm Action'"
[animationSettings]="animationSettings"
[width]="'400px'"
[showCloseIcon]="true"
(overlayClick)="closeDialog()">
<p>{{ confirmMessage }}</p>
<ng-template #footerTemplate>
<button class="e-btn e-primary" (click)="confirmAction()">Yes</button>
<button class="e-btn" (click)="closeDialog()">Cancel</button>
</ng-template>
</ejs-dialog>`
})
export class ContextMenuWithDialogComponent {
@ViewChild('fileManager')
fileManager?: FileManagerComponent;
@ViewChild('confirmDialog')
confirmDialog?: DialogComponent;
contextMenuSettings = {
file: ['Delete', 'Archive'],
folder: ['Delete', 'Archive']
};
confirmMessage = '';
pendingAction = { type: '', files: [] as any[] };
onMenuClick(args: MenuClickEventArgs) {
const selectedFiles = this.fileManager?.selectedItems || [];
if(args.itemText === 'Delete') {
this.confirmMessage = `Delete ${selectedFiles.length} item(s)? This cannot be undone.`;
this.pendingAction = { type: 'delete', files: selectedFiles };
this.confirmDialog?.show();
args.cancel = true;
} else if(args.itemText === 'Archive') {
this.confirmMessage = `Archive ${selectedFiles.length} item(s)?`;
this.pendingAction = { type: 'archive', files: selectedFiles };
this.confirmDialog?.show();
args.cancel = true;
}
}
confirmAction() {
if(this.pendingAction.type === 'delete') {
console.log('Deleting:', this.pendingAction.files.map(f => f.name));
} else if(this.pendingAction.type === 'archive') {
console.log('Archiving:', this.pendingAction.files.map(f => f.name));
}
this.closeDialog();
}
closeDialog() {
this.confirmDialog?.hide();
}
}Example 3: Context Menu with Submenu
@Component({
template: `<ejs-filemanager
(menuOpen)='onMenuOpen($event)'
(menuClick)='onMenuClick($event)'>
</ejs-filemanager>`
})
export class ContextMenuWithSubmenuComponent {
contextMenuSettings = {
file: ['OpenWith', 'SendTo', 'Delete'],
folder: ['NewFolder', 'Copy', 'Delete']
};
onMenuOpen(args: MenuOpenEventArgs) {
// Add submenu structure
args.items.forEach((item: any) => {
if(item.text === 'OpenWith') {
item.items = [
{ text: 'Text Editor', iconCss: 'e-icons e-edit' },
{ text: 'Notepad', iconCss: 'e-icons e-edit' },
{ text: 'Visual Studio Code', iconCss: 'e-icons e-edit' }
];
} else if(item.text === 'SendTo') {
item.items = [
{ text: 'Email', iconCss: 'e-icons e-mail' },
{ text: 'OneDrive', iconCss: 'e-icons e-cloud' },
{ text: 'USB Drive', iconCss: 'e-icons e-export' }
];
}
});
}
onMenuClick(args: MenuClickEventArgs) {
console.log('Menu item clicked:', args.itemText);
}
}---
Best Practices
1. Always set icons - Use menuOpen event to assign icons to all menu items 2. Provide context - Show different items for files vs folders vs empty space 3. Validate before action - Check permissions in menuClick before executing 4. Use confirmation - Ask for confirmation for destructive actions (delete, archive) 5. Handle errors gracefully - Catch and display user-friendly error messages 6. Limit items - Don't overcrowd context menu with too many items 7. Group logically - Use similar menu items together 8. Test on mobile - Context menu behavior differs on touch devices
---
Next: Learn about file operations at file-operations.md or explore advanced features at advanced-features.md.