Skip to main content

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

T
generic
The type of items to search through

Constructor

app
App
required
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.
query
string
required
The current search query
Returns: FuzzyMatch<T>[] - Array of fuzzy matches Since: 0.9.20

renderSuggestion()

Already implemented. Renders a fuzzy match with highlighted matching characters.
item
FuzzyMatch<T>
required
The fuzzy match object containing the item and match data
el
HTMLElement
required
The HTML element to render into
Since: 0.9.20

onChooseSuggestion()

Already implemented. Calls your onChooseItem() method when a suggestion is selected.
item
FuzzyMatch<T>
required
The selected fuzzy match
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.
item
T
required
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.
item
T
required
The selected item
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();
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

FeatureSuggestModalFuzzySuggestModal
Search logicManual implementationBuilt-in fuzzy search
FilteringYou implement getSuggestions()Automatic via getItems()
HighlightingManualAutomatic
Best forCustom search logic, async operationsSimple item selection with fuzzy matching

See Also

Build docs developers (and LLMs) love