0
# Application Lifecycle
1
2
Application startup process and event handling for managing the complete application lifecycle from initialization to shutdown. The Application class provides comprehensive lifecycle management including plugin activation, DOM attachment, and event listener setup.
3
4
## Capabilities
5
6
### Application Startup
7
8
Start the application with optional configuration for hosting, plugin selection, and event handling behavior.
9
10
```typescript { .api }
11
/**
12
* Start the application.
13
* @param options - The options for starting the application
14
* @returns A promise which resolves when all bootstrapping work is complete and the shell is mounted to the DOM
15
*/
16
start(options?: Application.IStartOptions): Promise<void>;
17
18
interface Application.IStartOptions {
19
/** The ID of the DOM node to host the application shell */
20
hostID?: string;
21
/** The plugins to activate on startup (in addition to autoStart plugins) */
22
startPlugins?: string[];
23
/** The plugins to NOT activate on startup (overrides startPlugins and autoStart) */
24
ignorePlugins?: string[];
25
/** Whether to capture keydown events at bubbling or capturing phase */
26
bubblingKeydown?: boolean;
27
}
28
```
29
30
**Usage Examples:**
31
32
```typescript
33
import { Application } from "@lumino/application";
34
import { Widget } from "@lumino/widgets";
35
36
const app = new Application({ shell: new Widget() });
37
38
// Basic startup
39
await app.start();
40
41
// Startup with custom host element
42
await app.start({
43
hostID: 'my-app-container'
44
});
45
46
// Startup with specific plugins
47
await app.start({
48
startPlugins: ['essential-plugin', 'ui-plugin'],
49
ignorePlugins: ['debug-plugin']
50
});
51
52
// Startup with custom event handling
53
await app.start({
54
bubblingKeydown: true // Use bubbling phase for keyboard events
55
});
56
```
57
58
### Startup Process
59
60
The application startup process follows a specific sequence of steps:
61
62
1. **Check if Already Started**: Returns immediately if `start()` has already been called
63
2. **Mark as Started**: Sets internal started flag to prevent multiple startups
64
3. **Configure Event Handling**: Sets up keydown event capture mode
65
4. **Activate Startup Plugins**: Activates plugins marked with `autoStart: true` plus any specified in `startPlugins`
66
5. **Attach Shell**: Mounts the shell widget to the DOM
67
6. **Add Event Listeners**: Registers application-wide event handlers
68
7. **Resolve Started Promise**: Signals that startup is complete
69
70
**Monitoring Startup:**
71
72
```typescript
73
// Check if application has started
74
if (await app.started) {
75
console.log('Application startup complete');
76
}
77
78
// Wait for startup completion
79
app.start().then(() => {
80
console.log('Application is now running');
81
});
82
83
// Monitor startup with multiple operations
84
Promise.all([
85
app.start(),
86
// other async operations
87
]).then(() => {
88
console.log('Everything is ready');
89
});
90
```
91
92
### Event Handling System
93
94
The Application class implements comprehensive DOM event handling for application-wide functionality.
95
96
```typescript { .api }
97
/**
98
* Handle the DOM events for the application.
99
* @param event - The DOM event sent to the application
100
*/
101
handleEvent(event: Event): void;
102
```
103
104
**Supported Events:**
105
106
- **`keydown`**: Keyboard shortcuts and command processing
107
- **`keyup`**: Key release handling for command completion
108
- **`contextmenu`**: Right-click context menu activation
109
- **`resize`**: Window resize handling for layout updates
110
111
**Event Handling Behavior:**
112
113
```typescript
114
// The application automatically handles these events:
115
116
// Keyboard events - processed by command registry
117
document.addEventListener('keydown', app); // Triggers app.commands.processKeydownEvent()
118
document.addEventListener('keyup', app); // Triggers app.commands.processKeyupEvent()
119
120
// Context menu events - opens application context menu
121
document.addEventListener('contextmenu', app); // Opens app.contextMenu if not shift-clicked
122
123
// Window events - updates shell layout
124
window.addEventListener('resize', app); // Triggers app.shell.update()
125
```
126
127
### Custom Event Handling
128
129
Subclasses can override event handling methods for custom behavior:
130
131
```typescript { .api }
132
/**
133
* A method invoked on a document 'keydown' event.
134
* @param event - The keyboard event
135
*/
136
protected evtKeydown(event: KeyboardEvent): void;
137
138
/**
139
* A method invoked on a document 'keyup' event.
140
* @param event - The keyboard event
141
*/
142
protected evtKeyup(event: KeyboardEvent): void;
143
144
/**
145
* A method invoked on a document 'contextmenu' event.
146
* @param event - The pointer event
147
*/
148
protected evtContextMenu(event: PointerEvent): void;
149
150
/**
151
* A method invoked on a window 'resize' event.
152
* @param event - The resize event
153
*/
154
protected evtResize(event: Event): void;
155
```
156
157
**Custom Event Handling Example:**
158
159
```typescript
160
class CustomApplication extends Application {
161
protected evtKeydown(event: KeyboardEvent): void {
162
// Add custom keyboard shortcuts
163
if (event.ctrlKey && event.key === 'k') {
164
console.log('Custom shortcut triggered');
165
event.preventDefault();
166
return;
167
}
168
169
// Fall back to default behavior
170
super.evtKeydown(event);
171
}
172
173
protected evtContextMenu(event: PointerEvent): void {
174
// Custom context menu logic
175
if (event.target instanceof Element && event.target.classList.contains('no-context')) {
176
return; // Skip context menu for certain elements
177
}
178
179
super.evtContextMenu(event);
180
}
181
182
protected evtResize(event: Event): void {
183
console.log('Window resized, updating layout');
184
super.evtResize(event);
185
}
186
}
187
```
188
189
### DOM Integration
190
191
The application integrates with the DOM through shell attachment and event listener registration:
192
193
```typescript { .api }
194
/**
195
* Attach the application shell to the DOM.
196
* @param id - The ID of the host node for the shell, or empty string
197
*/
198
protected attachShell(id: string): void;
199
200
/**
201
* Add the application event listeners.
202
*/
203
protected addEventListeners(): void;
204
```
205
206
**Shell Attachment:**
207
208
```typescript
209
// Default behavior - attaches to document.body if no ID provided
210
app.start(); // Shell attached to document.body
211
212
// Custom host element
213
app.start({ hostID: 'app-root' }); // Shell attached to element with id="app-root"
214
215
// Custom attachment logic
216
class CustomApplication extends Application {
217
protected attachShell(id: string): void {
218
const host = id ? document.getElementById(id) : document.querySelector('.app-container');
219
if (host) {
220
Widget.attach(this.shell, host);
221
} else {
222
console.warn('Host element not found, using document.body');
223
super.attachShell('');
224
}
225
}
226
}
227
```
228
229
### Application State
230
231
The Application class provides properties to monitor application state:
232
233
```typescript { .api }
234
/** A promise which resolves after the application has started */
235
readonly started: Promise<void>;
236
237
/** The list of all the deferred plugins */
238
readonly deferredPlugins: string[];
239
```
240
241
**State Monitoring:**
242
243
```typescript
244
// Wait for application startup
245
await app.started;
246
console.log('Application is running');
247
248
// Check deferred plugins
249
const deferred = app.deferredPlugins;
250
if (deferred.length > 0) {
251
console.log('Deferred plugins:', deferred);
252
253
// Activate them later
254
await app.activateDeferredPlugins();
255
console.log('All deferred plugins now active');
256
}
257
258
// Check if specific functionality is available
259
const hasStarted = app.started.then(() => true).catch(() => false);
260
```
261
262
### Lifecycle Best Practices
263
264
1. **Single Startup**: Only call `start()` once - subsequent calls return the same promise
265
2. **Plugin Order**: Use `requires`/`optional` dependencies rather than `startPlugins` for plugin ordering
266
3. **Error Handling**: Handle startup failures gracefully as some plugins may fail to activate
267
4. **DOM Ready**: Ensure the DOM is ready before calling `start()` if using a custom `hostID`
268
5. **Event Bubbling**: Consider `bubblingKeydown: true` if you need to handle keyboard events in your own code first
269
6. **Cleanup**: The Application class doesn't provide explicit cleanup methods - manage this in your own application code