Textarea
A Quill rich-text editor with Material styling and native textarea form integration.
Basic example
Write formatted text using Quill 2. Headings, emphasis, lists, quotes, and links use a Material toolbar. The original textarea keeps the serialized value for normal form submission.
Loading the rich-text editor…
Submit the form to inspect its serialized HTML.<div class="rich-textarea-field">
<label for="brief">Project brief</label>
<textarea id="brief" name="brief" data-editor="quill" required
placeholder="Describe your project…"><p>Hello <strong>world</strong>!</p></textarea>
</div>Setup
Start with the kmaterialize CSS and JavaScript from Getting started, then follow the component setup below.
Quill is an optional peer dependency. Load its Snow stylesheet before Materialize. The editor code loads when an opted-in textarea is initialized.
npm install kmaterialize quillimport 'quill/dist/quill.snow.css';
import 'kmaterialize/dist/css/materialize.css';
import { RichTextarea } from 'kmaterialize';
const field = RichTextarea.init(
document.querySelector<HTMLTextAreaElement>('#brief')!
);
await field.ready;
console.log(field.getHTML());
console.log(field.getText());Alternatively, M.AutoInit() enhances textarea[data-editor="quill"]. Add no-autoinit when you want to initialize a field yourself. Await the instance’s ready promise before using field.quill.
Without a bundler, load quill.snow.css, then Materialize CSS, followed by quill.js and materialize.js. The component can use window.Quill.
Examples and variants
Compact toolbar and plain-text value
Choose which controls to show. This example preserves formatting in the editor while storing plain text in the native textarea.
const note = RichTextarea.init(textarea, {
valueFormat: 'text',
toolbar: [['bold', 'italic'], [{ list: 'bullet' }], ['clean']]
});
await note.ready;HTML is the default value format. Use valueFormat: 'text' or data-value-format="text" for plain text; formatting is not preserved when that plain-text value is reloaded.
Read-only and disabled
Use the native readonly and disabled attributes. Disabled fields are omitted from form submission. State changes are reflected in the editor and toolbar automatically.
Validation
Native textareas support required and text-length constraints. For rich text, validate the editor’s plain text if your limit counts readable characters; the original textarea stores HTML. Native maxlength is not a limit for Quill’s editable content.
These previews keep their error state visible. In your form, show errors after checking a field or submitting, then clear them when the value is valid.
For text fields, use .input-field.error, aria-invalid="true", and a message linked with aria-describedby. Remove the error state when resolved. Use aria-live="polite" for messages updated dynamically.
Required rich text
error Enter your notes.
Maximum length
<div class="rich-textarea-field">
<label for="validation-notes">Notes</label>
<textarea id="validation-notes" data-editor="quill" required aria-invalid="true" aria-describedby="validation-notes-error"></textarea>
<p id="validation-notes-error" class="supporting-text error-text"><i class="material-icons" aria-hidden="true">error</i> Enter your notes.</p>
</div>
<div class="input-field error">
<textarea id="validation-bio" class="materialize-textarea" maxlength="40" placeholder=" " aria-invalid="true" aria-describedby="validation-bio-error">This description contains more than forty characters.</textarea>
<label for="validation-bio">Short description</label>
<span id="validation-bio-error" class="supporting-text"><i class="material-icons" aria-hidden="true">error</i> Use 40 characters or fewer.</span>
</div>Reference
Values, events, and cleanup
await field.ready;
field.setValue('<p>A <strong>formatted</strong> update.</p>');
const html = field.getHTML();
const text = field.getText();
const storedValue = field.getValue();
// Native input fires as content changes; change fires when leaving the editor.
textarea.addEventListener('input', () => console.log(textarea.value));
// After assigning textarea.value directly:
textarea.value = '<p>Loaded from a saved draft.</p>';
field.refresh();
// Access Quill's API and Delta document:
const delta = field.quill!.getContents();
// Restore the native textarea, retaining the latest serialized value:
field.destroy();The native name, required, and form reset behavior are preserved. An empty editor stores an empty string, so required validation works. HTML is normalized through Quill’s supported formats; it is not stored byte-for-byte.
The default toolbar supports text formatting and links. Customize toolbar and formats, or set toolbar: false for a toolbar-free editor. TypeScript options are exported as RichTextareaOptions.
Set fontFamily in the RichTextarea.init() options to choose the default editor content font, for example { fontFamily: 'Arial, sans-serif' }. You can also set --rich-textarea-font-family on the wrapper. Without an override, content inherits the application font. Load any web fonts separately, including weight 800 for extra-bold text. Toolbar typography is unchanged.
Set --rich-textarea-min-height and --rich-textarea-max-height on the generated .rich-textarea to adjust the writing area. All component styles are shipped by kmaterialize.