I am using blockRenderMap to give the option of small text while editing. By default react-rte does not support it. This is the code to do that:
import React, {Component} from 'react';
import RichTextEditor from 'react-rte';
import Immutable from 'immutable'
import Draft from 'draft-js'
const blockRenderMap = Immutable.Map({
'small': {
element: 'small'
}
});
// Include 'paragraph' as a valid block and updated the unstyled element but
// keep support for other draft default block types
const extendedBlockRenderMap = Draft.DefaultDraftBlockRenderMap.merge(blockRenderMap);
class MyStatefulEditor extends Component {
state = {
value: RichTextEditor.createEmptyValue()
}
onChange = (value) => {
console.log(value.toString('html'))
this.setState({value});
if (this.props.onChange) {
// Send the changes up to the parent component as an HTML string.
// This is here to demonstrate using `.toString()` but in a real app it
// would be better to avoid generating a string on each change.
this.props.onChange(
value.toString('html')
);
}
};
render ()
{
const toolbarConfig = {
// Optionally specify the groups to display (displayed in the order listed).
display: ['INLINE_STYLE_BUTTONS', 'BLOCK_TYPE_BUTTONS', 'LINK_BUTTONS', 'BLOCK_TYPE_DROPDOWN', 'HISTORY_BUTTONS'],
INLINE_STYLE_BUTTONS: [
{label: 'Bold', style: 'BOLD', className: 'custom-css-class'},
{label: 'Italic', style: 'ITALIC'},
{label: 'Underline', style: 'UNDERLINE'}
],
BLOCK_TYPE_DROPDOWN: [
{label : 'Small', style: 'small'},
{label: 'Normal', style: 'unstyled'},
{label: 'Heading Large', style: 'header-one'},
{label: 'Heading Medium', style: 'header-two'},
{label: 'Heading Small', style: 'header-three'}
],
BLOCK_TYPE_BUTTONS: [
{label: 'UL', style: 'unordered-list-item'},
{label: 'OL', style: 'ordered-list-item'}
]
};
return (
<RichTextEditor
value={this.state.value}
onChange={this.onChange}
toolbarConfig={toolbarConfig}
blockRenderMap={extendedBlockRenderMap}
/>
);
}
}
export default MyStatefulEditor;
While using the editor, this works fine
But inside the onChange
function, if I print the "value" variable, which contains the editorValue, it shows like this:
<p>asdas</p>
Instead of:
<small>asdas</small>
At the same time, if I select one of the default supported ones, like Heading Large:
And I print value
inside onChange
, I see this:
<h1>asdas</h1>
Why does my blockRenderMap
not work, while the default ones work? How can I make the value
variable contain the expected small
tags instead of the p
tags, for the case it applies?
There were many struggles here
<p>
. I really expected that the extension of the blockRenderMap will solve everything, but nope.<section>
as the style and then try to apply a CSS class to it. But section is not available by default. Even if you specify it as a custom blockRenderMap, it converts it to <p>
in the value
variable. So I ended up modifying <h4>
.Solution was
During editing:
.rte-small-font {
font-size: smaller;
font-weight:normal;
display:block;
margin:0;
padding:0;
}
<h4>
(because we were not using it anyway). The CSS class is basically converting the <h4>
to <small>
BLOCK_TYPE_DROPDOWN
: {label : 'Small', style: 'header-four'},
And then, when onChange()
gets called (basically 'saving' the edited text):
onChange()
by replacing <h4>
with <small>
: let newString = value.toString('html').replace("<h4>", "<small>").replace("</h4>", "</small>");