File manager
A file manager over any storage: a folder tree loaded folder by folder, the open folder as a list or a grid, a path, back / forward / up, sorting and search, selection with Ctrl and Shift, inline rename, new folders, delete, drag-to-move, drop-to-upload and a context menu.
Everything goes through a provider — a list function plus the operations you allow — so the same component browses a REST API, cloud storage or a database; a command the provider does not implement is hidden. The keyboard follows the APG tree view and listbox patterns. See the API.
Getting started
Double-click or Enter opens; F2 renames; Delete deletes; drag items onto a folder (in the list, the tree or the path) to move them, drop files from the desktop to upload; right-click or Shift+F10 for the context menu.
- Files
- Finance
- Photos
- Projects
- FinanceSep 14, 2026, 9:30 AM
- PhotosAug 30, 2026, 9:30 AM
- ProjectsOct 2, 2026, 9:30 AM
- Employee handbook.pdf2.5 MBMar 18, 2026, 9:30 AM
- Read me.txt1.3 KBJul 1, 2026, 9:30 AM
Opened: —
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { OgeFileManager, ogeMemoryFileProvider } from '@oge-ui/upload/file-manager';
import type { OgeFileItem, OgeFileProvider } from '@oge-ui/upload/file-manager';
@Component({
selector: 'demo-root',
imports: [OgeFileManager],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<!-- Double-click or Enter opens; F2 renames; Delete deletes; drag items
onto a folder to move them, drop files from the desktop to upload;
right-click for the context menu. -->
<oge-file-manager
[provider]="files"
(fileOpen)="open($event)"
style="height: 460px"
/>
<p>Opened: {{ opened() || '—' }}</p>
`,
})
export class Demo {
// a provider talks to your storage: list a folder, plus the operations you
// allow (createFolder, rename, delete, move, upload) — here, an in-memory one
readonly files: OgeFileProvider = ogeMemoryFileProvider([
{ id: 'projects', name: 'Projects', parentId: null, isFolder: true },
{ id: 'readme', name: 'Read me.txt', parentId: null, isFolder: false, size: 1284 },
{ id: 'spec', name: 'Specification.docx', parentId: 'projects', isFolder: false, size: 84210 },
]);
readonly opened = signal('');
open(item: OgeFileItem): void {
this.opened.set(item.name);
}
}Read-only grid
A provider with only list browses without the new folder, rename, delete, move and upload commands; [(view)] keeps the view in your own state.
- Files
- Finance
- Photos
- Projects
- FinanceSep 14, 2026, 9:30 AM
- PhotosAug 30, 2026, 9:30 AM
- ProjectsOct 2, 2026, 9:30 AM
- Employee handbook.pdf2.5 MBMar 18, 2026, 9:30 AM
- Read me.txt1.3 KBJul 1, 2026, 9:30 AM
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { OgeFileManager } from '@oge-ui/upload/file-manager';
import type { OgeFileProvider, OgeFileView } from '@oge-ui/upload/file-manager';
@Component({
selector: 'demo-root',
imports: [OgeFileManager],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<!-- a read-only browser in grid view; [(view)] keeps the view in your
own state -->
<oge-file-manager [provider]="archive" [(view)]="view" style="height: 400px" />
`,
})
export class Demo {
// only list(): no new folder, rename, delete, move or upload commands
readonly archive: OgeFileProvider = {
list: async (folderId) =>
(await fetch(`/api/archive?folder=${folderId ?? ''}`)).json(),
};
readonly view = signal<OgeFileView>('grid');
}Confirm before deleting
(deleting) is cancelable; event.wait() holds the delete until a dialog answers.
- Files
- INV-2026-0912.pdf92 KBSep 12, 2026, 9:30 AM
- INV-2026-0918.pdf89 KBSep 18, 2026, 9:30 AM
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { OgeFileManager, ogeMemoryFileProvider } from '@oge-ui/upload/file-manager';
import { OgeModalService } from '@oge-ui/overlay';
import type { OgeFileDeletingEvent } from '@oge-ui/upload/file-manager';
@Component({
selector: 'demo-root',
imports: [OgeFileManager],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<!-- (deleting) is cancelable; event.wait() holds it for a dialog -->
<oge-file-manager
[provider]="files"
(deleting)="confirmDelete($event)"
style="height: 300px"
/>
`,
})
export class Demo {
private readonly dialog = inject(OgeModalService);
readonly files = ogeMemoryFileProvider([
{ id: 'q3', name: 'Q3 report.pdf', parentId: null, isFolder: false, size: 92004 },
{ id: 'q4', name: 'Q4 report.pdf', parentId: null, isFolder: false, size: 88512 },
]);
confirmDelete(event: OgeFileDeletingEvent): void {
// wait() holds the delete until the answer: cancel on "No"
event.wait(
this.dialog
.confirm({
title: 'Delete files?',
message: `${event.items.length} item(s) will be deleted.`,
})
.then((ok) => (event.cancel = !ok)),
);
}
}