Erwähnungen und Tags
RichText unterstützt benutzerdefinierte Trigger-Zeichen, die ein Vorschlag-Dropdown im Dokument öffnen. Wenn der Benutzer ein Element auswählt, fügt RichText ein nicht bearbeitbares Token in das Dokument ein. Typische Anwendungsfälle:
@— eine Person erwähnen#— einen Tag anwenden/— einen Befehl oder eine Vorlage einfügen$— ein Finanzsymbol oder eine Variable einfügen:— ein Emoji einfügen
Konfigurieren Sie das Verhalten über die Eigenschaft triggers. Jeder Eintrag bindet ein Zeichen an eine Datenquelle.
Trigger konfigurieren
Jeder Trigger ist ein Objekt { trigger, data, showTrigger?, action? } innerhalb des triggers-Arrays. Das Feld data kann drei Formen annehmen:
- Ein statisches Array — RichText filtert es automatisch nach
label(Groß-/Kleinschreibung wird ignoriert,startsWith):
{ trigger: "@", data: people }
- Eine synchrone Funktion — verwenden Sie diese, um Ergebnisse selbst zu filtern:
{
trigger: "#",
data: query => tags.filter(t =>
t.label.toLowerCase().startsWith(query.toLowerCase())
)
}
- Eine asynchrone Funktion — verwenden Sie diese für die serverseitige Suche:
{
trigger: "+",
data: async query => {
const res = await fetch(`/api/users?q=${encodeURIComponent(query)}`);
const users = await res.json();
return users.map(u => ({
id: String(u.id),
label: u.name,
url: u.website
}));
}
}
Verwandtes Beispiel: RichText. Erwähnungen, Tags und asynchrone Suche
Token-Darstellung
Wenn der Benutzer ein Element aus dem Dropdown auswählt, fügt RichText es als <a>-Element mit zwei Datenattributen ein:
<a
data-token="@"
data-token-id="alice"
href="mailto:alice@example.com">@Alice</a>
Das Token ist ein einzelner nicht bearbeitbarer Knoten. Backspace löscht es in einem Schritt. RichText speichert das Feld url in href, sodass Strg+Klick auf das Token dem Link folgt.
Sie können Tokens mit dem Selektor data-token gestalten:
.wx-editor-content a[data-token="@"][data-token-id="alice"] {
background: #fb8500;
color: #fff;
border-radius: 3px;
padding: 0 2px;
}
Verwandte Beispiele:
Trigger-Zeichen ausblenden
Setzen Sie showTrigger: false auf einem Trigger, um nur die Element-Beschriftung ohne das Trigger-Symbol einzufügen:
{
trigger: "/",
data: commands,
showTrigger: false
}
Tastaturinteraktion
Im Vorschlag-Dropdown können Sie die folgenden Tastenkürzel verwenden:
↑/↓— zwischen Elementen navigierenEnter— das aktive Element einfügenEscape— das Dropdown schließen ohne einzufügen
Vorschlags-Events abhören
Drei Events stellen den Dropdown-Lebenszyklus über den Event Bus bereit:
insert-token— wird ausgelöst, wenn ein Benutzer ein Element auswähltshow-suggest— wird ausgelöst, wenn das Dropdown geöffnet wirdhide-suggest— wird ausgelöst, wenn das Dropdown geschlossen wird
const editor = new richtext.Richtext("#root", {
triggers: [{ trigger: "@", data: people }]
});
editor.api.on("insert-token", ({ data, trigger, showTrigger }) => {
console.log(`Inserted ${trigger}${data.label} (id: ${data.id})`);
});
Dropdown-Element anpassen
Standardmäßig zeigt das Dropdown die label-Eigenschaft jedes Elements an. Um benutzerdefinierte Vorschläge darzustellen (z. B. Avatar, Name und E-Mail-Adresse), übergeben Sie eine Vorlage über die Eigenschaft triggerTemplate.
Beispiel
const { template } = richtext;
new richtext.Richtext("#root", {
triggers: [{ trigger: "@", data: people }],
triggerTemplate: template(({ data, trigger }) => `
<div className="user">
<div className="user-name">${trigger}${data.label}</div>
<div className="user-url">${data.url || ""}</div>
</div>
`)
});
Verwandtes Beispiel: RichText. Benutzerdefinierte Dropdown-Vorlage pro Trigger
Benutzerdefinierte Aktion bei Auswahl
Standardmäßig wird ein ausgewähltes Element als Token in das Dokument eingefügt. Um stattdessen eigenen Code auszuführen, fügen Sie dem Trigger einen action-Callback hinzu. RichText entfernt den eingegebenen Trigger-Text und ruft action(item) mit dem ausgewählten Element auf. Es wird kein Token eingefügt, sodass Sie selbst entscheiden können, was hinzugefügt wird.
action hat Vorrang vor showTrigger. Wenn action gesetzt ist, wird showTrigger ignoriert.
Emoji einfügen
Ein : Trigger kann ein Emoji einfügen, wobei jedes Element ein benutzerdefiniertes Feld code enthält. Kombinieren Sie action mit triggerTemplate, damit das Dropdown das Emoji statt nur seiner Beschriftung anzeigt:
const { template, Richtext } = richtext;
const emoji = [
{
id: "apple", label: "apple", code: "1F34E"
},
{
id: "blue_car", label: "blue_car", code: "1F699"
},
{
id: "computer", label: "computer", code: "1F4BB"
}
];
const editor = new Richtext("#root", {
triggers: [
{
trigger: ":",
data: emoji, // [{ id: "apple", label: "apple", code: "1F34E" }, ...]
action: item => editor.insertValue(`<span>${emojiFromCode(item.code)} </span>`)
}
],
// das Emoji selbst (nicht nur seine Beschriftung) im Dropdown anzeigen
triggerTemplate: template(({ data }) => `${emojiFromCode(data.code)} ${data.label}`)
});
function emojiFromCode(code) {
return String.fromCodePoint(parseInt(code, 16));
}
Verwandtes Beispiel: RichText. Emoji-Autovervollständigung
Emoji nach Kategorien gruppieren
Wenn der Parameter data eine Funktion ist, sind Sie nicht auf den integrierten label-Abgleich beschränkt. Sie können eigene Filterlogik implementieren und Kategorieüberschriften im Dropdown beibehalten. Fügen Sie Header-Elemente hinzu, die ein label-Feld enthalten, aber kein code-Feld. Die data-Funktion sucht zunächst die passenden Emoji und gibt diese dann zusammen mit den Überschriften der Kategorien zurück, die noch Treffer enthalten:
const { template, Richtext } = richtext;
// Header-Elemente haben kein `code`-Feld; Emoji-Elemente enthalten eines
const emoji = [
{ id: "$smileys", label: "Smileys", category: 1 }, // Kategorie
{ id: "grinning", label: "grinning", code: "1F600", category: 1 },
{ id: "smile", label: "smile", code: "1F604", category: 1 },
{ id: "$animals", label: "Animals", category: 2 }, // Kategorie
{ id: "dog", label: "dog", code: "1F436", category: 2 },
{ id: "cat", label: "cat", code: "1F431", category: 2 }
];
const editor = new Richtext("#root", {
triggers: [
{
trigger: ":",
data: query => {
const matched = emoji.filter(item =>
item.code &&
item.label.toLowerCase().startsWith(query.toLowerCase().trim())
);
const categories = new Set(matched.map(item => item.category));
// passende Emojis behalten plus die Überschriften der Kategorien, die noch Treffer enthalten
return emoji.filter(item =>
item.code ? matched.includes(item) : categories.has(item.category)
);
},
action: item => editor.insertValue(`<span>${emojiFromCode(item.code)} </span>`)
}
],
// Emoji-Zeilen normal und Kategorieüberschriften fett darstellen
triggerTemplate: template(({ data }) =>
data.code ? `${emojiFromCode(data.code)} ${data.label}` : `<b>${data.label}</b>`
)
});
function emojiFromCode(code) {
return String.fromCodePoint(parseInt(code, 16));
}
// Überschriften haben kein `code` — Auswahl auf ihnen ignorieren, damit sie nie eingefügt werden
editor.api.intercept("insert-token", ({ data }) => !!data.code);
Slash-Befehlsmenü hinzufügen
Sie können action verwenden, um ein Slash-Befehlsmenü zu erstellen (wie / in Notion oder Slack). Speichern Sie einen Befehlsnamen in der id jedes Elements, dessen Optionen in einem benutzerdefinierten Feld config, und lassen Sie den Callback ihn mit api.exec ausführen:
// jedes Element speichert einen api.exec-Aktionsnamen in `id` und seine Parameter in `config`
const commands = [
{ id: "set-text-style", label: "Heading 1", config: { tag: "h1" } },
{ id: "insert-list", label: "Bulleted list", config: { type: "bulleted" } },
{ id: "insert-line", label: "Divider" } // keine Konfiguration → `|| {}` wird angewendet
];
const editor = new richtext.Richtext("#root", {
triggers: [
{
trigger: "/",
data: commands,
action: item => editor.api.exec(item.id, item.config || {})
}
]
});
Verwandtes Beispiel: RichText. Slash-Befehle