react-draft-wysiwyg
react-draft-wysiwyg copied to clipboard
how to set maxlength
hello,I want to set maxlength but I can not find any apis to set
Hi, I was handling the same issue as you.
Here is the solution:
- Based on this 1. demo with HTML content ( https://jpuri.github.io/react-draft-wysiwyg/#/demo) I was able to do this:
onEditorStateChange = (editorState) => {
this.setState({
editorState
});
};
handleBeforeInput = (input) => {
if (this.props.maxLength) {
if (draftToHtml(convertToRaw(this.state.editorState.getCurrentContent())).length >= this.props.maxLength) {
return 'handled';
}
}
};
<Editor
editorState={editorState} //this is actual state of editor
onEditorStateChange={this.onEditorStateChange}
handleBeforeInput={this.handleBeforeInput} // THIS IS THE IMPORTANT PART
/>
Basically it's preventing any other input if maxLength props is passed to my component and then use current "html as string" length to compare with editorState.
If you want to know more about draftJS handling, read this. https://github.com/facebook/draft-js/blob/master/docs/APIReference-Editor.md#cancelable-handlers-optional
I hope this helps.
@jpuri Let me know if my approach is correct, thanks
@tomffee this can't work. because the handleBeforeInput props is not passed to draft-js
@tomffee : approach looks good. @chaosforfun : all additional props passed to wysiwyg are passed down to the draft editor.
@jpuri https://github.com/jpuri/react-draft-wysiwyg/blob/84199ad37ab3f7c71e402687e3c824599091dd85/src/Editor/index.js#L316
the filterEditorProps
will filter handleBeforeInput
@chaosforfun: This filter function is not the usual js filter, it returns the filtered out props instead
Reference: https://github.com/jpuri/react-draft-wysiwyg/blob/84199ad37ab3f7c71e402687e3c824599091dd85/src/utils/common.js#L44-L55
So, all additional props passed to wysiwyg are actually indeed passed to draft-js Editor component.
including handleBeforeInput
@tomffee good approach, but might need to consider handlePastedText as well.
@jpuri Hello, this issue had official api now? I also want set maxLength to limit input, look forward to your reply, thanks!
I'm not sure why, but that proposal is not working for me. Any news about this feature?
Solved this issue. Just added handlePastedText and handleBeforeInput to Editor. Something like this:
<Editor
handleBeforeInput={val => {
const textLength = editorValue.getCurrentContent().getPlainText().length;
if (val && textLength >= maxLength) {
return 'handled';
}
return 'not-handled';
}}
handlePastedText={val => {
const textLength = editorValue.getCurrentContent().getPlainText().length;
return ((val.length + textLength) >= maxLength);
}}
...
/>
where maxLength is your number of limit and editorValue is your current state of Editor
@VadSiam I am using the same approach as yours, but the issue that I am facing is by returning 'handled' instructs the editor that the command has been handled and no more work is required, but what I want to add the following to it as well.
-
Notify the end-user with an error message that they won't be able to type or paste anything further as maxLength is exceeded.
-
If the text length of the pasted text is more than the maxLength, then at least slice the test till max length and paste that and show the errorMsg of maxLength.
not able to find any proper method to update the editorState, with the sliced text.
Any Suggestions?
@monk786 I played around with this for a while and came up with a solution, @jpuri I guess with this we can close this issue as well -> As @VadSiam explained, handledBeforeInput would be implemented this way ->
handleBeforeInput = input => {
const inputLength = this.state.editorState
.getCurrentContent()
.getPlainText().length;
if (input && inputLength >= maxChars) {
return "handled";
}
};
Now for slicing the content when copying, we would need to use the Modifier from Draft-JS, you can refer the documentation here. So the handledPastedText ->
handlePastedText = input => {
const inputLength = this.state.editorState
.getCurrentContent()
.getPlainText().length;
let remainingLength = maxChars - inputLength;
if (input.length + inputLength >= maxChars) {
const newContent = Modifier.insertText(
this.state.editorState.getCurrentContent(),
this.state.editorState.getSelection(),
input.slice(0,remainingLength)
);
this.onEditorStateChange(
EditorState.push(
this.state.editorState,
newContent,
"insert-characters"
)
);
return true;
} else {
return false;
}
};
Mind you here the onEditorStateChange is just the onChange method for updating the state of the editor. With this, it will be handled.
Max-length it's kind of the default attribute for text-area. Such trivial things should be implemented by the library itself.
@Gurubalan-GIT @VadSiam This is only working if the editor has only text inside. max-length check is not working if markup is applied to the text like bold or italics. Can anyone please help me in this case.
Hi, I was handling the same issue as you.
Here is the solution:
- Based on this 1. demo with HTML content ( https://jpuri.github.io/react-draft-wysiwyg/#/demo) I was able to do this:
onEditorStateChange = (editorState) => { this.setState({ editorState }); }; handleBeforeInput = (input) => { if (this.props.maxLength) { if (draftToHtml(convertToRaw(this.state.editorState.getCurrentContent())).length >= this.props.maxLength) { return 'handled'; } } }; <Editor editorState={editorState} //this is actual state of editor onEditorStateChange={this.onEditorStateChange} handleBeforeInput={this.handleBeforeInput} // THIS IS THE IMPORTANT PART />
Basically it's preventing any other input if maxLength props is passed to my component and then use current "html as string" length to compare with editorState.
If you want to know more about draftJS handling, read this. https://github.com/facebook/draft-js/blob/master/docs/APIReference-Editor.md#cancelable-handlers-optional
I hope this helps.
@jpuri Let me know if my approach is correct, thanks
handlebeforeInput is not acceptable new version of editor
Hello everybody,
I am having trouble setting the maxLength property on this component. Has anyone found a solution?
Here is the version I'm using. It's handling copy - paste mechanism Not perfect, but it does the job for me
// get selected text
const getSelectionText = (editorState: EditorState) => {
var selectionState = editorState.getSelection();
var anchorKey = selectionState.getAnchorKey();
var currentContent = editorState.getCurrentContent();
var currentContentBlock = currentContent.getBlockForKey(anchorKey);
var start = selectionState.getStartOffset();
var end = selectionState.getEndOffset();
var selectedText = currentContentBlock.getText().slice(start, end);
return selectedText;
};
// handling pasting text.. damn !
const handlePastedText = (text: string, html: string | undefined, editorState: EditorState) => {
if (!props.maxLength) return 'not-handled';
const getRemainingTextLength = (editorState: EditorState, maxLength: number, selectedTextLength: number) => {
const inputLength = editorState.getCurrentContent().getPlainText().length;
let remainingLength = Math.max(0, maxLength - (inputLength - selectedTextLength));
return remainingLength;
};
let currentEditorState: EditorState = editorState;
let selectedTextLength = getSelectionText(currentEditorState).length;
let remainingLength = getRemainingTextLength(currentEditorState, props.maxLength, selectedTextLength);
if (remainingLength <= 0) return 'handled';
if (remainingLength > 0) {
let newContent: ContentState;
let textToPaste = text;
// replacing selected text
if (selectedTextLength > 0) {
const length = Math.min(selectedTextLength, text.length);
let replacedText = text.slice(0, length);
newContent = Modifier.replaceText(currentEditorState.getCurrentContent(), currentEditorState.getSelection(), replacedText);
currentEditorState = EditorState.push(currentEditorState, newContent, 'insert-characters');
if (currentEditorState) {
setEditorState(currentEditorState);
}
textToPaste = text.slice(length - 1, text.length);
}
if (textToPaste.length > 0) {
let selectedTextLength = getSelectionText(currentEditorState).length;
let remainingLength = getRemainingTextLength(currentEditorState, props.maxLength, selectedTextLength);
if (remainingLength <= 0) return 'handled';
if (remainingLength > 0) {
newContent = Modifier.insertText(currentEditorState.getCurrentContent(), currentEditorState.getSelection(), textToPaste.slice(0, remainingLength));
currentEditorState = EditorState.push(currentEditorState, newContent, 'insert-characters');
if (currentEditorState) {
setEditorState(currentEditorState);
}
}
}
return 'handled';
}
return 'not-handled';
};