Spaces:
Sleeping
Modals display information and accept input from the user. To create a modal, create a class that extends [[Reference/TypeScript API/Modal/Modal|Modal]]:
import { App, Modal } from "obsidian";
export class ExampleModal extends Modal {
constructor(app: App) {
super(app);
}
onOpen() {
let { contentEl } = this;
contentEl.setText("Look at me, I'm a modal! 👀");
}
onClose() {
let { contentEl } = this;
contentEl.empty();
}
}
- [[Reference/TypeScript API/View/onOpen|onOpen()]] is called when the modal is opened and is responsible for building the content of your modal. For more information, refer to HTML elements.
- [[Reference/TypeScript API/Modal/onClose|onClose()]] is called when the modal is closed and is responsible for cleaning up any resources used by the modal.
To open a modal, create a new instance of ExampleModal
and call [[Reference/TypeScript API/Modal/open|open()]] on it:
import { Plugin } from "obsidian";
import { ExampleModal } from "./modal";
export default class ExamplePlugin extends Plugin {
async onload() {
this.addCommand({
id: "display-modal",
name: "Display modal",
callback: () => {
new ExampleModal(this.app).open();
},
});
}
}
Accept user input
The modal in the previous example only displayed some text. Let's look at a little more complex example that handles input from the user.
![[modal-input.png]]
import { App, Modal, Setting } from "obsidian";
export class ExampleModal extends Modal {
result: string;
onSubmit: (result: string) => void;
constructor(app: App, onSubmit: (result: string) => void) {
super(app);
this.onSubmit = onSubmit;
}
onOpen() {
const { contentEl } = this;
contentEl.createEl("h1", { text: "What's your name?" });
new Setting(contentEl)
.setName("Name")
.addText((text) =>
text.onChange((value) => {
this.result = value
}));
new Setting(contentEl)
.addButton((btn) =>
btn
.setButtonText("Submit")
.setCta()
.onClick(() => {
this.close();
this.onSubmit(this.result);
}));
}
onClose() {
let { contentEl } = this;
contentEl.empty();
}
}
The result is stored in this.result
and returned in the onSubmit
callback when the user clicks Submit:
new ExampleModal(this.app, (result) => {
new Notice(`Hello, ${result}!`);
}).open();
Select from list of suggestions
[[SuggestModal|SuggestModal]] is a special modal that lets you display a list of suggestions to the user.
![[suggest-modal.gif]]
import { App, Notice, SuggestModal } from "obsidian";
interface Book {
title: string;
author: string;
}
const ALL_BOOKS = [
{
title: "How to Take Smart Notes",
author: "Sönke Ahrens",
},
{
title: "Thinking, Fast and Slow",
author: "Daniel Kahneman",
},
{
title: "Deep Work",
author: "Cal Newport",
},
];
export class ExampleModal extends SuggestModal<Book> {
// Returns all available suggestions.
getSuggestions(query: string): Book[] {
return ALL_BOOKS.filter((book) =>
book.title.toLowerCase().includes(query.toLowerCase())
);
}
// Renders each suggestion item.
renderSuggestion(book: Book, el: HTMLElement) {
el.createEl("div", { text: book.title });
el.createEl("small", { text: book.author });
}
// Perform action on the selected suggestion.
onChooseSuggestion(book: Book, evt: MouseEvent | KeyboardEvent) {
new Notice(`Selected ${book.title}`);
}
}
In addition to SuggestModal
, the Obsidian API provides an even more specialized type of modal for suggestions: the [[FuzzySuggestModal|FuzzySuggestModal]]. While it doesn't give you the same control of how each item is rendered, you get fuzzy string search out-of-the-box.
![[fuzzy-suggestion-modal.png]]
export class ExampleModal extends FuzzySuggestModal<Book> {
getItems(): Book[] {
return ALL_BOOKS;
}
getItemText(book: Book): string {
return book.title;
}
onChooseItem(book: Book, evt: MouseEvent | KeyboardEvent) {
new Notice(`Selected ${book.title}`);
}
}