react-rte
react-rte copied to clipboard
Question: how to use customControls (with or without toolbarConfig)?
RTE is great! This is a usage question, not an issue. My goal is to customize the toolbar components with, e.g., material ui react components. Reading through the react-rte
docs, I think that there are two styling hooks:
-
toolbarConfig
for CSS (link); and -
customControls
for completely overriding components (as seen in demo).
I believe that my use case calls for customControls
, but from the provided demo I was not able to understand how to hook the custom components back into rte's functionality. For example, if I render a custom button component for BOLD, how does this button get the default functionality that would have gone to the default button provided by toolbarConfig?
In fact, it'd be wild if toolbarConfig
offered an optional component
attribute for each button type. For example:
INLINE_STYLE_BUTTONS: [
{ label: "Bold", style: "BOLD", component: MyBoldButtonComponent },
]
This would marry the best aspects of the toolbarConfig
and customControls
.
I am also interested in documentation about this. My use case is to add a way for the user to insert custom html tags in the input, so I want to add a button for that. However I struggle to understand the whole "CustControlFunc" type.
Just did a bit of snooping around, and managed to get bold and italic working in CustControlFunc
.
Other actions like align, ol, ul, links etc. are contained within the rte library and not draft.js. Maybe they can be implemented with some careful copy pasting, although it would be nice if all the toggle functions and other states could be exposed in some way into CustControlFunc
or another way.
On that subject, I have no idea if SetControlState
and GetControlState
give access to anything or if so to how to use them.
Here is roughly what I did:
Note: I am using one CustControlFunc
to render my whole toolbar at once, so customControls={[myCustomToolbar]}
instead of customControls={[function1, function2]}
.
import RichTextEditor, { EditorValue } from "react-rte";
import {RichUtils, EditorState} from "draft-js";
// typescript types for reference
type GetControlState = (key: string) => string | undefined;
type SetControlState = (key: string, value: string) => void;
const myCustomToolbar = (set: SetControlState, get: GetControlState, state: EditorState): ReactNode =>
{
// this uses the Draft.js EditorState to toggle changes, instead of rte's EditorValue. All functions I use here can be found in the draft.js docs
const activeInlineStyles = state.getCurrentInlineStyle();
const handleStyleToggle = (e: Event, style: string) =>
{
e?.preventDefault(); // you need to use onMouseDown for button clicks to prevent default focus, otherwise onClick will lose focus on the editor and the action will not happen
setEditorValue(EditorValue.createFromState(RichUtils.toggleInlineStyle(state, style))); // set your react-rte EditorValue state, I am using a useState outside of this function
};
return (
...your custom styled toolbar here...
<div>
<button active={activeInlineStyles.has("BOLD")} onMouseDown={(e: Event) => handleStyleToggle(e, "BOLD")} />
<button active={activeInlineStyles.has("ITALIC")} onMouseDown={(e: Event) => handleStyleToggle(e, "ITALIC")} />
</div>
);
}