Draft-js: how to limit the maximum input length?

Created on 29 Feb 2016  路  9Comments  路  Source: facebook/draft-js

question

Most helpful comment

Well, I don't know if I would recommend using undo for this, since it may jump you back to a previous boundary state that you don't want.

Ideally, you'd be able to do:

onChange(editorState) {
  const contentState = editorState.getCurrentContent();
  const oldContent = this.state.editorState.getCurrentContent();
  const {maxLength} = this.props;
  if (contentState === oldContent || contentState.getPlainText().length <= maxLength) {
      this.setState({editorState});
  }
}

But I think beforeInput native rendering might cause trouble for this, so for now, to be really safe, you'd also want to implement handleBeforeInput:

handleBeforeInput(chars) {
  const totalLength = this.state.editorState.getCurrentContent().getPlainText().length + chars.length;
  return totalLength > this.props.maxLength;
}

By returning true, we prevent the beforeInput event from rendering the new character or from executing onChange.

All 9 comments

You could check the size of the contents in onChange if the ContentState has changed, and slice off the contents that go beyond the limit.

to solve the problem, as follows:

onChange(editorState) {
    const contentState = editorState.getCurrentContent();
    if (contentState.getPlainText().length > this.props.maxLength) {
        editorState = EditorState.undo(editorState);
    }
    this.setState({editorState});
}

Well, I don't know if I would recommend using undo for this, since it may jump you back to a previous boundary state that you don't want.

Ideally, you'd be able to do:

onChange(editorState) {
  const contentState = editorState.getCurrentContent();
  const oldContent = this.state.editorState.getCurrentContent();
  const {maxLength} = this.props;
  if (contentState === oldContent || contentState.getPlainText().length <= maxLength) {
      this.setState({editorState});
  }
}

But I think beforeInput native rendering might cause trouble for this, so for now, to be really safe, you'd also want to implement handleBeforeInput:

handleBeforeInput(chars) {
  const totalLength = this.state.editorState.getCurrentContent().getPlainText().length + chars.length;
  return totalLength > this.props.maxLength;
}

By returning true, we prevent the beforeInput event from rendering the new character or from executing onChange.

chars type is String chars.length ?

That's correct, thanks. Fixed my comment.

when chars will be greater than an length?

Sorry, I don't understand the question.

@hellendag i tried your solution, but it dose not work for me and this is work for me
your solution prevent setState, but it still writing.

onChange = editorState => {
        const contentState = editorState.getCurrentContent();
        const oldContent = this.state.editorState.getCurrentContent();
        if(contentState === oldContent || contentState.getPlainText().length <= 25) {
            this.setState({ editorState });
        } else {
            const editorState = EditorState.moveFocusToEnd(
                EditorState.push(
                    this.state.editorState,
                    ContentState.createFromText(oldContent.getPlainText())
                )
            );
            this.setState({ editorState });
        }
    }

@AnasRezk to prevent focus move to end, use following solution. This also doesn't jump as mentioned from @hellendag

onChange = editorState => {
        const contentState = editorState.getCurrentContent();
        const oldContent = this.state.editorState.getCurrentContent();
        if(contentState === oldContent || contentState.getPlainText().length <= 25) {
            this.setState({ editorState });
        } else {
            const editorState = EditorState.undo(
                EditorState.push(
                    this.state.editorState,
                    ContentState.createFromText(oldContent.getPlainText()),
                    'delete-character'
                )
            );
            this.setState({ editorState });
        }
    }

here some typescript solution:

getStateWithMaxLengthEnsured(oldState: Draft.EditorState, newState: Draft.EditorState, maxLength: number): Draft.EditorState {
        const contentState = newState.getCurrentContent();
        const oldContent = oldState.getCurrentContent();
        if (contentState === oldContent || contentState.getPlainText().length <= maxLength) {
            return newState;
        } else {
            return Draft.EditorState.undo(
                Draft.EditorState.push(
                    oldState,
                    Draft.ContentState.createFromText(oldContent.getPlainText()),
                    'delete-character'
                )
            );
        }
    }
Was this page helpful?
0 / 5 - 0 ratings