Text
The text composer holds what the user types into a message: the text, the cursor position, the mentions and the active command. Every message composer has one, messageComposer.textComposer.
What it holds
The text composer's state is in textComposer.state. These getters read its current values:
textComposer.text: the text;textComposer.selection: the cursor position, or the selected range, as{ start, end };textComposer.textIsEmpty: whether the text is empty, only whitespace, or only an empty formatting mark such as**;textComposer.mentions: the mentions in the text: users, roles, user groups,@channeland@here;textComposer.command: the active command, ornull. See Commands;textComposer.suggestions: the open suggestions, if any.
Changing the text
Some calls pass the text composer's state through the text middleware: a pipeline of functions that runs in order. Each function can change the state or pass it on unchanged, and it can stop the pipeline. The built-in functions find mentions and commands, and you can add your own, as Composer middleware explains. The last column says which middleware handler a call runs, if any.
What a text input needs, and the call for each:
| To… | Call | What happens | Text middleware |
|---|---|---|---|
| handle typing or deleting | TextComposer.handleChange({ text, selection }) |
Updates the text and cursor. The built-in middleware finds mentions and commands and opens suggestions for them. Reports typing, as below. | onChange |
| insert pasted text, or text such as an emoji, at the cursor | TextComposer.insertText({ text, selection }) |
Replaces the text in selection, or inserts at the cursor when selection is left out, then continues as TextComposer.handleChange(). Windows line endings become \n. |
onChange |
| format the selection, such as making it bold | TextComposer.wrapSelection({ head, tail, selection }) |
Puts head before and tail after the text in selection, or the current selection when selection is left out, and keeps it selected. |
none |
| move the cursor | TextComposer.setSelection(selection) |
Updates the cursor position that TextComposer.insertText() and TextComposer.wrapSelection() use. |
none |
| apply a suggestion the user picked | TextComposer.handleSelect(suggestion) |
Replaces the typed trigger with the mention or command. See Suggestions. | onSuggestionItemSelect |
| set the text from code | TextComposer.setText(text) |
Replaces the text. Mentions, commands and the cursor stay as they were, and no suggestions open. | none |
const { textComposer } = channel.messageComposer;
await textComposer.handleChange({
selection: { end: 5, start: 5 },
text: "Hello",
});Pasted files aren't text: a UI hands them to the attachment manager.
Sending the text
When the message is built, the text goes into the message's text field, and the mentions go into mentioned_users, mentioned_roles, mentioned_group_ids, mentioned_channel and mentioned_here. A mention is sent only while its @ name is still in the text, so a mention the user deleted from the text isn't sent.
A draft saves the text and its mentions too. When a draft or a message to edit is loaded into the composer, its text and mentions come back.
Typing events
While the publishTypingEvents setting is on, which is the default, each change that leaves text in the composer reports a keystroke to the channel, which sends the typing events. A send stops them. See Typing indicators.
Settings
Set them for every composer in client.config, under messageComposer.text:
client.config.set({
messageComposer: {
text: { maxLengthOnEdit: 2_000, publishTypingEvents: false },
},
});To change a setting for one composer only, set it on that composer's text composer, for example channel.messageComposer.textComposer.publishTypingEvents = false.
| Setting | Default | What it does |
|---|---|---|
enabled |
true |
false turns off text input: changes, inserts and selection are ignored. |
defaultValue |
none | The text the composer holds when it starts without a message, and again after it's cleared. |
maxLengthOnEdit |
none | Cuts the text while the user types or pastes. |
maxLengthOnSend |
none | Stops a longer message: MessageComposer.send() returns 'nothing-to-send', and no notification is published. A draft is cut to this length instead. |
publishTypingEvents |
true |
Reports typing, as above. |
The channel type's max_message_length caps both lengths. A composer that sets neither takes the server's limit.