Overview
TextAreaComponent creates a <textarea> element for multi-line text input. It extends AbstractTextComponent<HTMLTextAreaElement> and is ideal for settings that require longer text input like descriptions, notes, or code snippets.
Constructor
The parent HTML element where the textarea will be created
const textArea = new TextAreaComponent(containerEl);
Properties
Direct access to the underlying HTML textarea element. Use this for advanced DOM manipulation like setting rows, cols, or maxlength.
Whether the component is currently disabled
Methods
setValue
Sets the current text content of the textarea.
The text content to set (can include line breaks)
textArea.setValue("Line 1\nLine 2\nLine 3");
Returns: this (for method chaining)
getValue
Retrieves the current text content from the textarea.
const content = textArea.getValue();
// Returns: string (may contain \n for line breaks)
Returns: string - The current text content
setPlaceholder
Sets placeholder text that appears when the textarea is empty.
The placeholder text to display
textArea.setPlaceholder("Enter your notes here...");
Returns: this (for method chaining)
setDisabled
Enables or disables the textarea.
Whether the component should be disabled
textArea.setDisabled(true);
Returns: this (for method chaining)
onChange
Registers a callback function that executes whenever the text content changes.
callback
(value: string) => any
required
Function to call when the content changes. Receives the new text value.
textArea.onChange((value) => {
console.log(`Content changed, length: ${value.length}`);
// Save to settings, validate, etc.
});
Returns: this (for method chaining)
onChanged
Internal method called when the value changes. Override this in subclasses for custom behavior.
then
Facilitates method chaining with a callback.
cb
(component: this) => any
required
Callback function that receives the component instance
textArea.then((component) => {
component.setValue("Initial content");
});
Returns: this (for method chaining)
Usage Examples
Basic TextArea
new Setting(containerEl)
.setName("Description")
.setDesc("Enter a detailed description")
.addTextArea((textArea) => {
textArea
.setPlaceholder("Your description here...")
.setValue(this.plugin.settings.description)
.onChange(async (value) => {
this.plugin.settings.description = value;
await this.plugin.saveSettings();
});
});
TextArea with Custom Size
new Setting(containerEl)
.setName("Notes")
.setDesc("Enter your notes")
.addTextArea((textArea) => {
textArea
.setValue(this.plugin.settings.notes)
.onChange(async (value) => {
this.plugin.settings.notes = value;
await this.plugin.saveSettings();
});
// Set custom dimensions
textArea.inputEl.rows = 10;
textArea.inputEl.cols = 50;
});
TextArea for Code Snippets
new Setting(containerEl)
.setName("Custom CSS")
.setDesc("Add custom CSS rules")
.addTextArea((textArea) => {
textArea
.setPlaceholder(".my-class {\n color: red;\n}")
.setValue(this.plugin.settings.customCss)
.onChange(async (value) => {
this.plugin.settings.customCss = value;
await this.plugin.saveSettings();
this.plugin.applyCustomCss(value);
});
// Style for code editing
textArea.inputEl.addClass("code-editor");
textArea.inputEl.rows = 15;
textArea.inputEl.style.fontFamily = "monospace";
});
TextArea with Character Counter
const counterEl = containerEl.createEl("div", {
cls: "character-counter"
});
new Setting(containerEl)
.setName("Bio")
.setDesc("Write your bio (max 500 characters)")
.addTextArea((textArea) => {
const updateCounter = (value: string) => {
const remaining = 500 - value.length;
counterEl.setText(`${value.length}/500 characters`);
counterEl.toggleClass("warning", remaining < 50);
};
textArea
.setValue(this.plugin.settings.bio)
.onChange(async (value) => {
// Limit to 500 characters
if (value.length > 500) {
value = value.substring(0, 500);
textArea.setValue(value);
}
this.plugin.settings.bio = value;
await this.plugin.saveSettings();
updateCounter(value);
});
// Initialize counter
updateCounter(this.plugin.settings.bio);
textArea.inputEl.rows = 6;
});
TextArea with Validation
new Setting(containerEl)
.setName("JSON Configuration")
.setDesc("Enter valid JSON")
.addTextArea((textArea) => {
textArea
.setPlaceholder('{\n "key": "value"\n}')
.setValue(this.plugin.settings.jsonConfig)
.onChange(async (value) => {
try {
// Validate JSON
JSON.parse(value);
// Valid JSON
this.plugin.settings.jsonConfig = value;
await this.plugin.saveSettings();
textArea.inputEl.removeClass("error");
} catch (error) {
// Invalid JSON
textArea.inputEl.addClass("error");
new Notice("Invalid JSON format");
}
});
textArea.inputEl.rows = 10;
textArea.inputEl.style.fontFamily = "monospace";
});
Multi-line Template Editor
new Setting(containerEl)
.setName("Note Template")
.setDesc("Customize your note template")
.addTextArea((textArea) => {
const defaultTemplate =
"# {{title}}\n\n" +
"Date: {{date}}\n" +
"Tags: {{tags}}\n\n" +
"## Notes\n";
textArea
.setPlaceholder(defaultTemplate)
.setValue(this.plugin.settings.noteTemplate || defaultTemplate)
.onChange(async (value) => {
this.plugin.settings.noteTemplate = value;
await this.plugin.saveSettings();
});
textArea.inputEl.rows = 12;
});
Disabled TextArea
new Setting(containerEl)
.setName("System Info")
.setDesc("Read-only system information")
.addTextArea((textArea) => {
const systemInfo = [
`OS: ${process.platform}`,
`Version: ${this.app.vault.adapter.getName()}`,
`Vault: ${this.app.vault.getName()}`
].join("\n");
textArea
.setValue(systemInfo)
.setDisabled(true);
textArea.inputEl.rows = 5;
});
TextArea with Auto-resize
new Setting(containerEl)
.setName("Content")
.addTextArea((textArea) => {
textArea
.setValue(this.plugin.settings.content)
.onChange(async (value) => {
this.plugin.settings.content = value;
await this.plugin.saveSettings();
// Auto-resize based on content
const lineCount = value.split("\n").length;
textArea.inputEl.rows = Math.max(3, Math.min(lineCount + 1, 20));
});
// Initialize with proper size
const initialLines = this.plugin.settings.content.split("\n").length;
textArea.inputEl.rows = Math.max(3, Math.min(initialLines + 1, 20));
});
TextArea for List Input
new Setting(containerEl)
.setName("Allowed Domains")
.setDesc("Enter one domain per line")
.addTextArea((textArea) => {
// Convert array to line-separated text
const domainsText = this.plugin.settings.allowedDomains.join("\n");
textArea
.setPlaceholder("example.com\ngithub.com\nobsidian.md")
.setValue(domainsText)
.onChange(async (value) => {
// Convert text back to array
const domains = value
.split("\n")
.map(line => line.trim())
.filter(line => line.length > 0);
this.plugin.settings.allowedDomains = domains;
await this.plugin.saveSettings();
});
textArea.inputEl.rows = 8;
});
Direct DOM Access
const textArea = new TextAreaComponent(containerEl);
textArea.setValue("Initial content");
// Access the underlying textarea element
textArea.inputEl.rows = 10;
textArea.inputEl.cols = 60;
textArea.inputEl.maxLength = 1000;
textArea.inputEl.wrap = "soft";
textArea.inputEl.spellcheck = false;
textArea.inputEl.addClass("custom-textarea");
See Also