如何限制草稿最大长度js

时间:2017-09-04 21:30:50

标签: javascript reactjs draftjs

如何限制草稿js中的最大字符?

我可以像这样得到状态的长度,但是如何停止更新组件?

var length = editorState.getCurrentContent().getPlainText('').length;

4 个答案:

答案 0 :(得分:11)

您应该定义handleBeforeInputhandlePastedText道具。在处理程序函数中,检查当前内容的长度+粘贴文本的长度,如果达到最大值,则应返回'handled'字符串。

UPD 21.03.2018:升级到最新版本的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'))

答案 1 :(得分:4)

Mikhail的方法是正确的,但处理程序返回值不是。 'not_handled'是一个允许编辑器组件正常处理输入的漏洞案例。在这种情况下,我们希望停止编辑器处理输入。

在旧版本的DraftJS中,看起来在处理代码中存在一个被评估为'true'的字符串,因此上面的代码表现正常。在DraftJS的后续版本中,上面的小提琴不起作用 - 我没有在这里发布更多那个小提琴的声誉,但是尝试将Mikhail的代码与DraftJS的v0.10一起复制。

要纠正此问题,请在不希望编辑器继续处理输入时返回'已处理'或true。

Fiddle with corrected return values

例如,

msiexec /i

有关更多内容,请参阅有关可取消处理程序的DraftJS文档。

答案 2 :(得分:1)

这是一个有点旧的线程,但我想我会为其他人在粘贴文本时面临字符限制和行为问题分享一个解决方案......

根据 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"
            )
        )
      }

链接到工作示例: https://codesandbox.io/s/objective-bush-1h9x6

答案 3 :(得分:-1)

让我们暂时考虑一下。什么叫做改变?你的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}`)
}

我没试过这个,但我的第六感觉说它运作得很好。