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