or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

file-dialog.mdfile-resource.mdfile-service.mdfile-tree.mdfilesystem-core.mdfilesystem-preferences.mdindex.md

file-dialog.mddocs/

0

# File Dialog System

1

2

Configurable file and folder selection dialogs with filtering, navigation controls, and support for both native (Electron) and web-based implementations. Provides standardized file selection interfaces across different Theia deployment environments.

3

4

## Capabilities

5

6

### FileDialogService Interface

7

8

High-level service providing convenient methods for showing file dialogs with proper type handling and result processing.

9

10

```typescript { .api }

11

/**

12

* High-level service for showing file open/save dialogs

13

*/

14

interface FileDialogService {

15

/** Show file open dialog for single file selection */

16

showOpenDialog(props: OpenFileDialogProps, folder?: FileStat): Promise<URI | undefined>;

17

18

/** Show file open dialog for multiple file selection */

19

showOpenDialog(props: OpenFileDialogProps & { canSelectMany: true }, folder?: FileStat): Promise<MaybeArray<URI> | undefined>;

20

21

/** Show file save dialog */

22

showSaveDialog(props: SaveFileDialogProps, folder?: FileStat): Promise<URI | undefined>;

23

}

24

25

type MaybeArray<T> = T | T[];

26

```

27

28

### Dialog Properties and Configuration

29

30

Comprehensive configuration options for customizing dialog behavior, appearance, and filtering.

31

32

```typescript { .api }

33

/**

34

* Base dialog properties with filters and modal settings

35

*/

36

interface FileDialogProps {

37

/** Dialog title text */

38

title?: string;

39

40

/** File type filters */

41

filters?: FileFilter[];

42

43

/** Default filter to select */

44

defaultFilter?: FileFilter;

45

46

/** Whether dialog should be modal */

47

modal?: boolean;

48

49

/** Initial directory to open */

50

defaultPath?: string;

51

52

/** Custom CSS class names */

53

className?: string;

54

}

55

56

/**

57

* Properties specific to open file dialogs

58

*/

59

interface OpenFileDialogProps extends FileDialogProps {

60

/** Allow file selection */

61

canSelectFiles?: boolean;

62

63

/** Allow folder selection */

64

canSelectFolders?: boolean;

65

66

/** Allow multiple selection */

67

canSelectMany?: boolean;

68

69

/** Label for open button */

70

openLabel?: string;

71

}

72

73

/**

74

* Properties specific to save file dialogs

75

*/

76

interface SaveFileDialogProps extends FileDialogProps {

77

/** Label for save button */

78

saveLabel?: string;

79

80

/** Default filename in input field */

81

inputValue?: string;

82

83

/** Placeholder text for filename input */

84

placeholder?: string;

85

}

86

87

/**

88

* File type filter definition

89

*/

90

interface FileFilter {

91

/** Display name for the filter */

92

name: string;

93

94

/** Array of file extensions (with or without dots) */

95

extensions: string[];

96

}

97

```

98

99

### Dialog Factory Functions

100

101

Factory functions for creating dialog instances with proper dependency injection.

102

103

```typescript { .api }

104

/**

105

* Factory function for creating open file dialogs

106

*/

107

type OpenFileDialogFactory = (props: OpenFileDialogProps) => OpenFileDialog;

108

109

/**

110

* Factory function for creating save file dialogs

111

*/

112

type SaveFileDialogFactory = (props: SaveFileDialogProps) => SaveFileDialog;

113

```

114

115

### Dialog Classes

116

117

Core dialog implementations providing the actual user interface and interaction logic.

118

119

```typescript { .api }

120

/**

121

* Base file dialog with navigation controls

122

*/

123

abstract class FileDialog<T> extends AbstractDialog<T> {

124

/** Back navigation button */

125

protected readonly back: HTMLSpanElement;

126

127

/** Forward navigation button */

128

protected readonly forward: HTMLSpanElement;

129

130

/** Home directory button */

131

protected readonly home: HTMLSpanElement;

132

133

/** Parent directory (up) button */

134

protected readonly up: HTMLSpanElement;

135

136

/** Current location URI */

137

protected location: URI | undefined;

138

139

/** Navigate to specific location */

140

protected navigateTo(location: URI): void;

141

142

/** Get available drives for navigation */

143

protected getDrives(): Promise<URI[]>;

144

}

145

146

/**

147

* File selection dialog implementation

148

*/

149

class OpenFileDialog extends FileDialog<URI | URI[]> {

150

/** Dialog properties */

151

readonly props: OpenFileDialogProps;

152

153

/** Currently selected items */

154

readonly selectedItems: URI[];

155

156

/** Accept the current selection */

157

accept(): void;

158

}

159

160

/**

161

* File save dialog implementation

162

*/

163

class SaveFileDialog extends FileDialog<URI> {

164

/** Dialog properties */

165

readonly props: SaveFileDialogProps;

166

167

/** Filename input element */

168

readonly fileNameInput: HTMLInputElement;

169

170

/** Get the entered filename */

171

readonly fileName: string;

172

173

/** Accept the current filename */

174

accept(): void;

175

}

176

```

177

178

### Dialog Model and Tree Integration

179

180

Model classes managing dialog state and file tree integration for directory navigation.

181

182

```typescript { .api }

183

/**

184

* Dialog model managing state and navigation

185

*/

186

interface FileDialogModel extends FileTreeModel {

187

/** Available file filters */

188

readonly filters: FileFilter[];

189

190

/** Currently active filter */

191

activeFilter: FileFilter | undefined;

192

193

/** Whether to show hidden files */

194

showHiddenFiles: boolean;

195

196

/** Apply current filter to tree nodes */

197

filterTree(): void;

198

}

199

200

/**

201

* Tree implementation for file dialogs

202

*/

203

interface FileDialogTree extends FileTree {

204

/** Dialog-specific tree model */

205

readonly model: FileDialogModel;

206

207

/** Handle file filter changes */

208

applyFileFilter(filter: FileFilter): void;

209

}

210

```

211

212

### Dialog Widget and Components

213

214

Complete widget implementation with all UI components and interaction handlers.

215

216

```typescript { .api }

217

/**

218

* Main dialog widget with all components

219

*/

220

interface FileDialogWidget extends DialogWidget {

221

/** Dialog model instance */

222

readonly model: FileDialogModel;

223

224

/** File tree component */

225

readonly tree: FileDialogTree;

226

227

/** Location navigation bar */

228

readonly locationBar: HTMLElement;

229

230

/** File filter dropdown */

231

readonly filterSelect: HTMLSelectElement;

232

233

/** Hidden files toggle */

234

readonly hiddenFilesToggle: HTMLInputElement;

235

}

236

```

237

238

### Default Implementation

239

240

Default service implementation with support for both web and Electron environments.

241

242

```typescript { .api }

243

/**

244

* Default implementation of FileDialogService

245

*/

246

@injectable()

247

class DefaultFileDialogService implements FileDialogService {

248

/** Open file dialog factory */

249

protected readonly openFileDialogFactory: OpenFileDialogFactory;

250

251

/** Save file dialog factory */

252

protected readonly saveFileDialogFactory: SaveFileDialogFactory;

253

254

async showOpenDialog(props: OpenFileDialogProps, folder?: FileStat): Promise<URI | URI[] | undefined> {

255

const dialog = this.openFileDialogFactory(props);

256

if (folder) {

257

dialog.model.location = folder.resource;

258

}

259

const result = await dialog.open();

260

return result;

261

}

262

263

async showSaveDialog(props: SaveFileDialogProps, folder?: FileStat): Promise<URI | undefined> {

264

const dialog = this.saveFileDialogFactory(props);

265

if (folder) {

266

dialog.model.location = folder.resource;

267

}

268

return dialog.open();

269

}

270

}

271

```

272

273

**Usage Examples:**

274

275

```typescript

276

import { FileDialogService, OpenFileDialogProps, SaveFileDialogProps } from "@theia/filesystem/lib/browser";

277

import { URI } from "@theia/core/lib/common/uri";

278

279

// Inject the service

280

const dialogService = container.get(FileDialogService);

281

282

// Open single file

283

const fileUri = await dialogService.showOpenDialog({

284

title: 'Select Configuration File',

285

canSelectFiles: true,

286

canSelectFolders: false,

287

filters: [

288

{ name: 'JSON Files', extensions: ['json'] },

289

{ name: 'YAML Files', extensions: ['yml', 'yaml'] },

290

{ name: 'All Files', extensions: ['*'] }

291

]

292

});

293

294

if (fileUri) {

295

console.log(`Selected file: ${fileUri.toString()}`);

296

}

297

298

// Open multiple files

299

const fileUris = await dialogService.showOpenDialog({

300

title: 'Select Source Files',

301

canSelectFiles: true,

302

canSelectFolders: false,

303

canSelectMany: true,

304

filters: [

305

{ name: 'TypeScript Files', extensions: ['ts', 'tsx'] },

306

{ name: 'JavaScript Files', extensions: ['js', 'jsx'] }

307

]

308

});

309

310

if (Array.isArray(fileUris)) {

311

console.log(`Selected ${fileUris.length} files`);

312

fileUris.forEach(uri => console.log(uri.toString()));

313

} else if (fileUris) {

314

console.log(`Selected single file: ${fileUris.toString()}`);

315

}

316

317

// Select folder

318

const folderUri = await dialogService.showOpenDialog({

319

title: 'Select Project Folder',

320

canSelectFiles: false,

321

canSelectFolders: true,

322

openLabel: 'Select Folder'

323

});

324

325

// Save file dialog

326

const saveUri = await dialogService.showSaveDialog({

327

title: 'Save Output File',

328

saveLabel: 'Save',

329

inputValue: 'output.json',

330

filters: [

331

{ name: 'JSON Files', extensions: ['json'] },

332

{ name: 'Text Files', extensions: ['txt'] }

333

]

334

});

335

336

if (saveUri) {

337

console.log(`Save location: ${saveUri.toString()}`);

338

}

339

340

// Advanced dialog with initial location

341

const workspaceFolder = URI.parse('file:///workspace');

342

const fileUri2 = await dialogService.showOpenDialog({

343

title: 'Select File from Workspace',

344

canSelectFiles: true,

345

defaultPath: workspaceFolder.fsPath

346

}, {

347

resource: workspaceFolder,

348

isDirectory: true

349

} as FileStat);

350

```

351

352

### Electron Native Dialog Integration

353

354

For Electron applications, native system dialogs are used when available:

355

356

```typescript

357

import { ElectronFileDialogService } from "@theia/filesystem/lib/electron-browser";

358

359

// Electron-specific service uses native dialogs

360

@injectable()

361

class ElectronFileDialogService implements FileDialogService {

362

// Uses Electron's dialog.showOpenDialog() and dialog.showSaveDialog()

363

// Provides native OS file dialog experience

364

}

365

```

366

367

### Custom Dialog Implementations

368

369

```typescript

370

// Custom dialog with additional validation

371

class ValidatingFileDialog extends OpenFileDialog {

372

373

protected accept(): void {

374

const selected = this.selectedItems;

375

376

// Custom validation logic

377

if (!this.validateSelection(selected)) {

378

this.setErrorMessage('Invalid file selection');

379

return;

380

}

381

382

super.accept();

383

}

384

385

private validateSelection(uris: URI[]): boolean {

386

// Custom validation logic

387

return uris.every(uri =>

388

uri.toString().includes('valid-directory')

389

);

390

}

391

}

392

```