Overview
The Component class provides a foundation for lifecycle management in Obsidian. It handles loading, unloading, and automatic cleanup of resources like event handlers, DOM events, and intervals. The Plugin class extends Component, so all plugins inherit these lifecycle management capabilities.
Available since: v0.9.7
Lifecycle Methods
load()
Loads this component and all its child components. This triggers the onload() method.
Returns: void
Since: v0.9.7
const component = new Component();
component.load();
onload()
Virtual method to be overridden by subclasses. Called when the component is loaded. Use this to initialize your component and set up resources.
Returns: void
Since: v0.9.7
class MyComponent extends Component {
onload() {
console.log('Component loaded');
// Initialize resources
}
}
unload()
Unloads this component and all its child components. This triggers the onunload() method and automatically cleans up all registered resources.
Returns: void
Since: v0.9.7
component.unload(); // Automatically cleans up all registered resources
onunload()
Virtual method to be overridden by subclasses. Called when the component is unloaded. Use this for custom cleanup logic.
Returns: void
Since: v0.9.7
class MyComponent extends Component {
onunload() {
console.log('Component unloaded');
// Custom cleanup
}
}
Child Component Management
addChild()
Adds a child component. If this component is already loaded, the child will be loaded immediately.
component
T extends Component
required
The child component to add.
Returns: T - The added child component.
Since: v0.12.0
class ParentComponent extends Component {
onload() {
const childComponent = this.addChild(new ChildComponent());
// Child is automatically loaded if parent is loaded
}
}
removeChild()
Removes a child component and unloads it.
component
T extends Component
required
The child component to remove.
Returns: T - The removed child component.
Since: v0.12.0
const child = this.addChild(new ChildComponent());
// Later...
this.removeChild(child); // Automatically unloads the child
Resource Registration
register()
Registers a callback to be called when unloading. Use this for custom cleanup that doesn’t fit other registration methods.
The cleanup callback function.
Returns: void
Since: v0.9.7
class MyComponent extends Component {
onload() {
// Register cleanup for custom resources
this.register(() => {
console.log('Cleaning up custom resource');
// Cleanup logic here
});
}
}
registerEvent()
Registers an Obsidian event to be detached when unloading.
The event reference returned by Obsidian event methods.
Returns: void
Since: v0.9.7
class MyComponent extends Component {
onload() {
// Events are automatically detached on unload
this.registerEvent(
this.app.workspace.on('file-open', (file) => {
console.log('File opened:', file.path);
})
);
}
}
registerDomEvent()
Registers a DOM event listener to be detached when unloading. Overloaded for Window, Document, and HTMLElement targets.
el
Window | Document | HTMLElement
required
The DOM element to attach the listener to.
The event type (e.g., ‘click’, ‘keydown’, ‘resize’).
callback
(this: HTMLElement, ev: Event) => any
required
The event handler callback.
options
boolean | AddEventListenerOptions
Optional event listener options.
Returns: void
Since: v0.14.8
class MyComponent extends Component {
onload() {
// Window event
this.registerDomEvent(window, 'resize', () => {
console.log('Window resized');
});
// Document event
this.registerDomEvent(document, 'click', (evt) => {
console.log('Document clicked at', evt.clientX, evt.clientY);
});
// Element event
const button = document.createElement('button');
this.registerDomEvent(button, 'click', () => {
console.log('Button clicked');
});
// With options
this.registerDomEvent(document, 'scroll', () => {
console.log('Scrolled');
}, { passive: true });
}
}
registerInterval()
Registers an interval (from setInterval) to be cancelled when unloading. Use window.setInterval to avoid TypeScript confusion between NodeJS and Browser APIs.
The interval ID returned by setInterval.
Returns: number - The interval ID.
Since: v0.13.8
class MyComponent extends Component {
onload() {
// Register interval for automatic cleanup
this.registerInterval(
window.setInterval(() => {
console.log('Interval tick');
}, 1000)
);
}
}
Complete Example
import { Component, Notice } from 'obsidian';
class StatusMonitor extends Component {
private statusElement: HTMLElement;
private updateInterval: number;
constructor(private container: HTMLElement) {
super();
}
onload() {
console.log('StatusMonitor loaded');
// Create UI element
this.statusElement = this.container.createDiv({ cls: 'status-monitor' });
this.statusElement.setText('Monitoring active');
// Register cleanup for the element
this.register(() => {
this.statusElement.remove();
});
// Register DOM events
this.registerDomEvent(this.statusElement, 'click', () => {
new Notice('Status monitor clicked!');
});
this.registerDomEvent(window, 'resize', () => {
this.updateLayout();
});
// Register interval
this.updateInterval = window.setInterval(() => {
this.updateStatus();
}, 5000);
this.registerInterval(this.updateInterval);
// Add child component
const childMonitor = this.addChild(new ChildMonitor());
}
onunload() {
console.log('StatusMonitor unloaded');
// All registered resources are automatically cleaned up
}
private updateStatus() {
this.statusElement.setText(`Updated: ${new Date().toLocaleTimeString()}`);
}
private updateLayout() {
// Handle layout changes
console.log('Layout updated');
}
}
class ChildMonitor extends Component {
onload() {
console.log('Child monitor loaded');
}
onunload() {
console.log('Child monitor unloaded');
}
}
// Usage
const container = document.body;
const monitor = new StatusMonitor(container);
monitor.load();
// Later, cleanup everything automatically
monitor.unload(); // Removes all events, intervals, and child components
Usage in Plugins
Since Plugin extends Component, you can use all these methods in your plugin:
import { Plugin } from 'obsidian';
export default class MyPlugin extends Plugin {
async onload() {
// Register workspace event
this.registerEvent(
this.app.workspace.on('active-leaf-change', () => {
console.log('Active leaf changed');
})
);
// Register DOM event
this.registerDomEvent(document, 'keydown', (evt: KeyboardEvent) => {
if (evt.key === 'F2') {
console.log('F2 pressed');
}
});
// Register interval
this.registerInterval(
window.setInterval(() => {
this.checkForUpdates();
}, 60000) // Check every minute
);
// Register custom cleanup
this.register(() => {
console.log('Plugin is being unloaded');
// Custom cleanup logic
});
}
checkForUpdates() {
// Check for updates logic
}
}
Best Practices
-
Always use registration methods - Don’t manually track resources. Let Component handle cleanup automatically.
-
Use
window.setInterval - This avoids TypeScript confusion between NodeJS and Browser APIs.
-
Register early - Register resources during
onload() or immediately after creating them.
-
Child components for organization - Break complex components into smaller child components for better organization and lifecycle management.
-
Custom cleanup with
register() - For resources that don’t fit other registration methods, use register() with a cleanup callback.
Plugin - Extends Component and adds plugin-specific functionality
EventRef - Reference to an Obsidian event subscription
AddEventListenerOptions - Standard DOM event listener options