如何在Draft.js中限制最大字符数?
我可以使用以下方式获取状态的长度,但如何停止更新组件?
var length = editorState.getCurrentContent().getPlainText('').length;
如何在Draft.js中限制最大字符数?
我可以使用以下方式获取状态的长度,但如何停止更新组件?
var length = editorState.getCurrentContent().getPlainText('').length;
你需要定义 handleBeforeInput
和 handlePastedText
属性。在处理函数中,你需要检查当前内容的长度加上粘贴文本的长度是否达到了最大值,如果是,则应该返回字符串'handled'
。
更新于 2018 年 3 月 21 日:升级至 React/React-DOM(版本号为 16.2.0)和 Draft.js(版本号为 0.10.5)的最新版本。
工作示例 - https://jsfiddle.net/Ln1hads9/11/
const {Editor, EditorState} = Draft;
const MAX_LENGTH = 10;
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
editorState: EditorState.createEmpty()
};
}
render() {
return (
<div className="container-root">
<Editor
placeholder="Type away :)"
editorState={this.state.editorState}
handleBeforeInput={this._handleBeforeInput}
handlePastedText={this._handlePastedText}
onChange={this._handleChange}
/>
</div>
);
}
_getLengthOfSelectedText = () => {
const currentSelection = this.state.editorState.getSelection();
const isCollapsed = currentSelection.isCollapsed();
let length = 0;
if (!isCollapsed) {
const currentContent = this.state.editorState.getCurrentContent();
const startKey = currentSelection.getStartKey();
const endKey = currentSelection.getEndKey();
const startBlock = currentContent.getBlockForKey(startKey);
const isStartAndEndBlockAreTheSame = startKey === endKey;
const startBlockTextLength = startBlock.getLength();
const startSelectedTextLength = startBlockTextLength - currentSelection.getStartOffset();
const endSelectedTextLength = currentSelection.getEndOffset();
const keyAfterEnd = currentContent.getKeyAfter(endKey);
console.log(currentSelection)
if (isStartAndEndBlockAreTheSame) {
length += currentSelection.getEndOffset() - currentSelection.getStartOffset();
} else {
let currentKey = startKey;
while (currentKey && currentKey !== keyAfterEnd) {
if (currentKey === startKey) {
length += startSelectedTextLength + 1;
} else if (currentKey === endKey) {
length += endSelectedTextLength;
} else {
length += currentContent.getBlockForKey(currentKey).getLength() + 1;
}
currentKey = currentContent.getKeyAfter(currentKey);
};
}
}
return length;
}
_handleBeforeInput = () => {
const currentContent = this.state.editorState.getCurrentContent();
const currentContentLength = currentContent.getPlainText('').length;
const selectedTextLength = this._getLengthOfSelectedText();
if (currentContentLength - selectedTextLength > MAX_LENGTH - 1) {
console.log('you can type max ten characters');
return 'handled';
}
}
_handlePastedText = (pastedText) => {
const currentContent = this.state.editorState.getCurrentContent();
const currentContentLength = currentContent.getPlainText('').length;
const selectedTextLength = this._getLengthOfSelectedText();
if (currentContentLength + pastedText.length - selectedTextLength > MAX_LENGTH) {
console.log('you can type max ten characters');
return 'handled';
}
}
_handleChange = (editorState) => {
this.setState({ editorState });
}
}
ReactDOM.render(<Container />, document.getElementById('react-root'))
迈克尔的方法是正确的,但是处理程序返回值不正确。 'not_handled' 是一个穿透案例,允许编辑器组件正常处理输入。在这种情况下,我们希望停止编辑器处理输入。
在早期版本的DraftJS中,看起来字符串的存在在处理代码中被评估为'true',因此上述代码表现正确。在后续的DraftJS版本中,上面的fiddle不起作用-我没有声望在这里发布多个Fiddle,但是请尝试使用v0.10的DraftJS复制迈克尔的代码。
为了更正这个问题,请在您不想让编辑器继续处理输入时返回'handled'或'true'。
例如:
_handleBeforeInput = () => {
const currentContent = this.state.editorState.getCurrentContent();
const currentContentLength = currentContent.getPlainText('').length
if (currentContentLength > MAX_LENGTH - 1) {
console.log('you can type max ten characters');
return 'handled';
}
}
这是一个有点老的帖子,但我想为那些面临字符限制和粘贴文本时遇到问题的人分享一个解决方案...
根据Mikhail的上述代码,我很快就组合了一些东西来处理这个用例,它对我有效 - 尽管我没有尝试过优化它。
基本上,处理粘贴文本看起来像这样:
const __handlePastedText = (pastedText: any) => {
const currentContent = editorState.getCurrentContent();
const currentContentLength = currentContent.getPlainText('').length;
const selectedTextLength = _getLengthOfSelectedText();
if (currentContentLength + pastedText.length - selectedTextLength > MAX_LENGTH) {
const selection = editorState.getSelection()
const isCollapsed = selection.isCollapsed()
const tempEditorState = !isCollapsed ? _removeSelection() : editorState
_addPastedContent(pastedText, tempEditorState)
return 'handled';
}
return 'not-handled'
}
我们有一个辅助函数来处理在粘贴新字符之前删除选择的操作,该函数返回新的编辑器状态:
const _removeSelection = () => {
const selection = editorState.getSelection()
const startKey = selection.getStartKey()
const startOffset = selection.getStartOffset()
const endKey = selection.getEndKey()
const endOffset = selection.getEndOffset()
if (startKey !== endKey || startOffset !== endOffset) {
const newContent = Modifier.removeRange(editorState.getCurrentContent(), selection, 'forward')
const tempEditorState = EditorState.push(
editorState,
newContent,
"remove-range"
)
setEditorState(
tempEditorState
)
return tempEditorState
}
return editorState
}
最后是添加���有限制的粘贴文本的函数:
const _addPastedContent = (input: any, editorState: EditorState) => {
const inputLength = editorState
.getCurrentContent()
.getPlainText().length;
let remainingLength = MAX_LENGTH - inputLength;
const newContent = Modifier.insertText(
editorState.getCurrentContent(),
editorState.getSelection(),
input.slice(0,remainingLength)
);
setEditorState(
EditorState.push(
editorState,
newContent,
"insert-characters"
)
)
}
正如Mikhail所提到的,您需要处理输入和粘贴文本。以下是两个处理程序。请注意,粘贴处理程序将保留未超出限制的文本。
function handleBeforeInput(text: string, state: EditorState): DraftHandleValue {
const totalLength = state.getCurrentContent().getPlainText().length + text.length;
return totalLength > MAX_LENGTH ? 'handled' : 'not-handled';
}
function handlePastedText(text: string, _: string, state: EditorState): DraftHandleValue {
const overflowChars = text.length + state.getCurrentContent().getPlainText().length - MAX_LENGTH;
if (overflowChars > 0) {
if (text.length - overflowChars > 0) {
const newContent = Modifier.insertText(
state.getCurrentContent(),
state.getSelection(),
text.substring(0, text.length - overflowChars)
);
setEditorState(EditorState.push(state, newContent, 'insert-characters'));
}
return 'handled';
} else {
return 'not-handled';
}
}
让我们花一秒钟来思考一下。是什么被称为进行更改的呢?你的onChange
,对吧?很好。我们也知道length
。正确吗?我们连接上“工人”,也就是onChange
:
const length = editorState.getCurrentContent().getPlainText('').length;
// Your onChange function:
onChange(editorState) {
const MAX_LENGTH = 10;
const length = editorState.getCurrentContent().getPlainText('').length;
if (length <= MAX_LENGTH) {
this.setState({ editorState }) // or this.setState({ editorState: editorState })
}
} else {
console.log(`Sorry, you've exceeded your limit of ${MAX_LENGTH}`)
}
我没有尝试过这个,但我的第六感告诉我它可以正常工作。
maxlength
的属性。那一堆方法是限制所见即所得输入长度的荒谬方式。 - Firanolfind