Overview
The FuzzySuggestModal<T> class extends SuggestModal to provide automatic fuzzy search functionality. It handles the filtering and matching logic for you, so you only need to provide the items and define how they should be displayed.
This is ideal when you have a list of items and want users to quickly find one using fuzzy search (matching items even when the query doesn’t exactly match).
Since: 0.9.20
Type Parameter
The type of items to search through
Constructor
Reference to the Obsidian App instance
class MyFuzzyModal extends FuzzySuggestModal<string> {
constructor(app: App) {
super(app);
}
// ... implement required methods
}
Methods
The following methods are inherited from SuggestModal but are already implemented with fuzzy search logic:
getSuggestions()
Already implemented. Returns fuzzy-matched items based on the query.
Returns: FuzzyMatch<T>[] - Array of fuzzy matches
Since: 0.9.20
renderSuggestion()
Already implemented. Renders a fuzzy match with highlighted matching characters.
The fuzzy match object containing the item and match data
The HTML element to render into
Since: 0.9.20
onChooseSuggestion()
Already implemented. Calls your onChooseItem() method when a suggestion is selected.
evt
MouseEvent | KeyboardEvent
required
The triggering event
Since: 0.9.20
Abstract Methods
You must implement these methods when extending FuzzySuggestModal.
getItems()
Returns the complete list of items to search through.
Returns: T[] - Array of all searchable items
getItems(): string[] {
return ['apple', 'banana', 'cherry', 'date', 'elderberry'];
}
Since: 0.9.20
getItemText()
Returns the text representation of an item for searching and display.
The item to get text from
Returns: string - The searchable text for this item
getItemText(item: string): string {
return item;
}
Since: 0.9.20
onChooseItem()
Called when the user selects an item from the suggestions.
evt
MouseEvent | KeyboardEvent
required
The event that triggered the selection
onChooseItem(item: string, evt: MouseEvent | KeyboardEvent) {
new Notice(`You selected: ${item}`);
}
Since: 0.9.20
Example: Simple File Selector
import { App, FuzzySuggestModal, TFile, Notice } from 'obsidian';
class FileSuggestModal extends FuzzySuggestModal<TFile> {
constructor(app: App) {
super(app);
}
getItems(): TFile[] {
return this.app.vault.getMarkdownFiles();
}
getItemText(file: TFile): string {
return file.path;
}
onChooseItem(file: TFile, evt: MouseEvent | KeyboardEvent) {
new Notice(`Selected: ${file.path}`);
this.app.workspace.getLeaf().openFile(file);
}
}
// Usage
const modal = new FileSuggestModal(this.app);
modal.open();
Example: Custom Object Search
import { App, FuzzySuggestModal, Notice } from 'obsidian';
interface Task {
id: string;
title: string;
description: string;
completed: boolean;
}
class TaskSuggestModal extends FuzzySuggestModal<Task> {
tasks: Task[];
constructor(app: App, tasks: Task[]) {
super(app);
this.tasks = tasks;
this.setPlaceholder('Search tasks...');
}
getItems(): Task[] {
return this.tasks.filter(task => !task.completed);
}
getItemText(task: Task): string {
// Combine title and description for better search results
return `${task.title} ${task.description}`;
}
onChooseItem(task: Task, evt: MouseEvent | KeyboardEvent) {
new Notice(`Selected task: ${task.title}`);
// Mark task as completed or perform other action
task.completed = true;
}
}
// Usage
const tasks: Task[] = [
{ id: '1', title: 'Write documentation', description: 'API docs for Modal class', completed: false },
{ id: '2', title: 'Fix bug', description: 'Resolve issue #123', completed: false },
{ id: '3', title: 'Add tests', description: 'Unit tests for new feature', completed: true }
];
const modal = new TaskSuggestModal(this.app, tasks);
modal.open();
Example: Tag Selector
import { App, FuzzySuggestModal, Notice, getAllTags } from 'obsidian';
class TagSuggestModal extends FuzzySuggestModal<string> {
constructor(app: App) {
super(app);
this.setPlaceholder('Select a tag...');
}
getItems(): string[] {
// Get all unique tags from the vault
const tags = new Set<string>();
this.app.vault.getMarkdownFiles().forEach(file => {
const cache = this.app.metadataCache.getFileCache(file);
const fileTags = getAllTags(cache);
if (fileTags) {
fileTags.forEach(tag => tags.add(tag));
}
});
return Array.from(tags);
}
getItemText(tag: string): string {
return tag;
}
onChooseItem(tag: string, evt: MouseEvent | KeyboardEvent) {
new Notice(`Selected tag: ${tag}`);
// Insert tag into editor or perform other action
}
}
// Usage
const modal = new TagSuggestModal(this.app);
modal.open();
FuzzyMatch Interface
When you work with the inherited methods, you’ll encounter the FuzzyMatch<T> type:
interface FuzzyMatch<T> {
item: T; // The original item
match: SearchResult; // Match information including score and highlights
}
The fuzzy search algorithm automatically:
- Scores matches based on relevance
- Highlights matching characters in the rendered suggestions
- Sorts results by match quality
Comparison with SuggestModal
| Feature | SuggestModal | FuzzySuggestModal |
|---|
| Search logic | Manual implementation | Built-in fuzzy search |
| Filtering | You implement getSuggestions() | Automatic via getItems() |
| Highlighting | Manual | Automatic |
| Best for | Custom search logic, async operations | Simple item selection with fuzzy matching |
See Also