Overview
The SuggestModal<T> class extends Modal to provide a search input with dynamic suggestions. It’s useful for creating interfaces where users can search and select from a list of items.
This is an abstract class that requires you to implement three key methods:
getSuggestions() - Return suggestions based on the query
renderSuggestion() - Render each suggestion in the list
onChooseSuggestion() - Handle when a user selects a suggestion
Since: 0.9.20
Type Parameter
The type of items that will be suggested
Constructor
Reference to the Obsidian App instance
class MyModal extends SuggestModal<string> {
constructor(app: App) {
super(app);
}
// ... implement required methods
}
Properties
Maximum number of suggestions to display at once. Default value varies.Since: 0.9.20
Text to display when no suggestions are found.Since: 0.9.20
The search input element.Since: 0.9.20
Container element for the suggestion results.Since: 0.9.20
Methods
setPlaceholder()
Sets the placeholder text for the search input.
this.setPlaceholder('Type to search...');
Since: 0.9.20
setInstructions()
Sets instruction prompts that appear below the input.
Array of instruction objects with command and purpose properties
this.setInstructions([
{ command: '↑↓', purpose: 'to navigate' },
{ command: '↵', purpose: 'to select' },
{ command: 'esc', purpose: 'to dismiss' }
]);
Since: 0.9.20
onNoSuggestion()
Called when there are no suggestions to display. Override this to customize the empty state.
onNoSuggestion() {
// Custom logic when no results found
}
Since: 0.9.20
selectSuggestion()
Programmatically selects a suggestion.
The suggestion item to select
evt
MouseEvent | KeyboardEvent
required
The triggering event
this.selectSuggestion(item, evt);
Since: 0.9.20
selectActiveSuggestion()
Selects the currently highlighted suggestion.
evt
MouseEvent | KeyboardEvent
required
The triggering event
this.selectActiveSuggestion(evt);
Since: 1.7.2
Abstract Methods
You must implement these methods when extending SuggestModal.
getSuggestions()
Returns an array of suggestions based on the user’s query.
Returns: T[] | Promise<T[]> - Array of suggestions or a Promise that resolves to suggestions
getSuggestions(query: string): string[] {
return ['apple', 'banana', 'cherry']
.filter(item => item.toLowerCase().includes(query.toLowerCase()));
}
Since: 1.5.7
renderSuggestion()
Renders a suggestion item into the provided HTML element.
The suggestion item to render
The HTML element to render the suggestion into
renderSuggestion(value: string, el: HTMLElement) {
el.createEl('div', { text: value });
}
Since: 1.5.7
onChooseSuggestion()
Called when the user selects a suggestion.
The selected suggestion item
evt
MouseEvent | KeyboardEvent
required
The event that triggered the selection
onChooseSuggestion(item: string, evt: MouseEvent | KeyboardEvent) {
new Notice(`You selected: ${item}`);
}
Since: 1.5.7
Example
import { App, SuggestModal, Notice } from 'obsidian';
interface Book {
title: string;
author: string;
}
class BookSuggestModal extends SuggestModal<Book> {
books: Book[];
constructor(app: App, books: Book[]) {
super(app);
this.books = books;
this.setPlaceholder('Search for a book...');
this.setInstructions([
{ command: '↑↓', purpose: 'to navigate' },
{ command: '↵', purpose: 'to select' },
{ command: 'esc', purpose: 'to dismiss' }
]);
}
getSuggestions(query: string): Book[] {
return this.books.filter(book =>
book.title.toLowerCase().includes(query.toLowerCase()) ||
book.author.toLowerCase().includes(query.toLowerCase())
);
}
renderSuggestion(book: Book, el: HTMLElement) {
el.createEl('div', { text: book.title, cls: 'book-title' });
el.createEl('small', { text: book.author, cls: 'book-author' });
}
onChooseSuggestion(book: Book, evt: MouseEvent | KeyboardEvent) {
new Notice(`Selected: ${book.title} by ${book.author}`);
}
}
// Usage
const books = [
{ title: 'The Great Gatsby', author: 'F. Scott Fitzgerald' },
{ title: '1984', author: 'George Orwell' },
{ title: 'To Kill a Mockingbird', author: 'Harper Lee' }
];
const modal = new BookSuggestModal(this.app, books);
modal.open();
Example: Async Suggestions
import { App, SuggestModal, requestUrl } from 'obsidian';
interface SearchResult {
id: string;
name: string;
}
class AsyncSuggestModal extends SuggestModal<SearchResult> {
async getSuggestions(query: string): Promise<SearchResult[]> {
if (!query) return [];
try {
const response = await requestUrl({
url: `https://api.example.com/search?q=${encodeURIComponent(query)}`
});
return response.json;
} catch (error) {
console.error('Search failed:', error);
return [];
}
}
renderSuggestion(result: SearchResult, el: HTMLElement) {
el.createEl('div', { text: result.name });
}
onChooseSuggestion(result: SearchResult, evt: MouseEvent | KeyboardEvent) {
console.log('Selected:', result);
}
}
See Also