最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to Set a character length in React-Quill - Stack Overflow

programmeradmin2浏览0评论

How can I set Character Length in react-quill. In Docs it has been given that getLength() will return the length of the character in editor..

But I am Unable to figure out How to implement it.

My JSX

<ReactQuill theme='snow' 
                        onKeyDown={this.checkCharacterCount}
                        value={this.state.text}
                        onChange={this.handleChange}
                        modules={modules}
                        formats={formats}
                        //style={{height:'460px'}}
                         />
    // OnChange Handler
    handleChange = (value) =>  {
        this.setState({ text: value })
      }
      
      //Max VAlue checker
      checkCharacterCount = (event) => {
        if (this.getLength().length > 280 && event.key !== 'Backspace') {
            event.preventDefault();
        }
    }

How can I set Character Length in react-quill. In Docs it has been given that getLength() will return the length of the character in editor..

But I am Unable to figure out How to implement it.

My JSX

<ReactQuill theme='snow' 
                        onKeyDown={this.checkCharacterCount}
                        value={this.state.text}
                        onChange={this.handleChange}
                        modules={modules}
                        formats={formats}
                        //style={{height:'460px'}}
                         />
    // OnChange Handler
    handleChange = (value) =>  {
        this.setState({ text: value })
      }
      
      //Max VAlue checker
      checkCharacterCount = (event) => {
        if (this.getLength().length > 280 && event.key !== 'Backspace') {
            event.preventDefault();
        }
    }

The Above solution i found on GitHub . But its not working...

Share Improve this question edited Mar 29, 2019 at 12:55 Shubham Pratik asked Mar 24, 2019 at 7:28 Shubham PratikShubham Pratik 5423 gold badges7 silver badges19 bronze badges
Add a comment  | 

6 Answers 6

Reset to default 8

I believe you are missing a reference to the ReactQuill component itself. Without the reference you will not get access to any of its unprivileged methods (e.g. getLength()). You could get a copy via your handleChange method (https://github.com/zenoamaro/react-quill#props , i.e. 4th argument on the onChange prop) but I would recommend you simply add a separate ref prop to the ReactQuill component and use that. See below an example re-written as a functional component (...since its 2020 already):

export const Editor = () => {
  const [value, setValue] = React.useState(null);
  const reactQuillRef = React.useRef();

  const handleChange = (value) => setValue(value);

  const checkCharacterCount = (event) => {
    const unprivilegedEditor = reactQuillRef.current.unprivilegedEditor;
    if (unprivilegedEditor.getLength() > 280 && event.key !== 'Backspace')
      event.preventDefault();
  };

  return (
    <ReactQuill theme='snow' 
      onKeyDown={checkCharacterCount}
      ref={reactQuillRef}
      value={this.state.text}
      onChange={this.handleChange}
      modules={modules}
      formats={formats} /> 
  ) 
}

Following should work:

class Editor extends React.Component {
  constructor (props) {
    super(props)
    this.handleChange = this.handleChange.bind(this)
    this.quillRef = null;      // Quill instance
    this.reactQuillRef = null;
    this.state = {editorHtml : ''};
  }
  componentDidMount() {
    this.attachQuillRefs()
  }

  componentDidUpdate() {
    this.attachQuillRefs()
  }

  attachQuillRefs = () => {
    if (typeof this.reactQuillRef.getEditor !== 'function') return;
    this.quillRef = this.reactQuillRef.getEditor();
  }
  handleChange (html) {
    var limit = 10;
    var quill = this.quillRef;
    quill.on('text-change', function (delta, old, source) {
      if (quill.getLength() > limit) {
       quill.deleteText(limit, quill.getLength());
      }
    });
    this.setState({ editorHtml: html });
  }


  render () {
    return  <ReactQuill 
            ref={(el) => { this.reactQuillRef = el }}
            theme="snow"
            onChange={this.handleChange}
            value={this.state.editorHtml}
            />
  }
}

I've had the same problem! None of the solutions I've found were working for me but finally I managed to make it work.

I post my answer and maybe helps someone in a future!

This prevents the user to write more than 10 charcaters, in this case just for the example.

import ReactQuill, { Quill } from 'react-quill';
import 'react-quill/dist/quill.snow.css';
export Props from "./types";

const MAX_EDITOR_LENGTH = 10;
const modules = {
  toolbar: {
    container: [['bold', 'italic', 'underline'], [{ list: 'bullet' }]],
  },
};

function App({control, editorName}: Props) {
  Quill.register('modules/maxlength', function (quill: any, options: any) {
    quill.on('text-change', function () {
      const textLength = quill.getText().length;
      if (textLength > options.maxLength) {
        quill.deleteText(options.maxLength, textLength - options.maxLength);
      }
    });
  });

  return (
    <Box>
      <Controller
        control={control}
        name={editorName}
        render={({ field }) => {
          return (
            <ReactQuill
              {...field}
              modules={{
                ...modules,
                maxlength: { maxLength: MAX_EDITOR_LENGTH },
              }}
            />
          );
        }}
      />
      <FormHelperText>
        <Box display="flex">
          <span style={{ marginLeft: 'auto' }}>
            {fieldName ? characterCount : 0}/{MAX_EDITOR_LENGTH}
          </span>
        </Box>
      </FormHelperText>
    </Box>
  );
}

export default App;

I don't have a "proper" solution but more a workaround with tiny-emitter that works also with copy-paste situations.

  • First, we had to create a CopyPaste class extends from clipboard module. In that class, we put an emitter and pass the quill instance into parameter.

const Emitter = require('tiny-emitter/instance');

const { Quill } =
  typeof window === 'object' ? require('react-quill') : () => false;

const Delta = typeof window === 'object' ? require('quill-delta') : null;

const Clipboard =
  typeof window === 'object' ? Quill.import('modules/clipboard') : null;

export class CopyPasteQuill extends Clipboard {
  onPaste(e) {
    e.preventDefault();
    const range = this.quill.getSelection();
    const text = e.clipboardData.getData('text/plain');

    const delta = new Delta()
      .retain(range.index)
      .delete(range.length)
      .insert(text);

    const index = text.length + range.index;
    const length = 0;
    this.quill.updateContents(delta, 'silent');
    this.quill.setSelection(index, length, 'silent');

    Emitter.emit('reactQuill::paste', this.quill);
  }
}

  • Second, we have a normalize component ReactQuillInput to handle every cases . The only warning is linked to values that are passed to this component. You can't give him props directly, you have to store them in a state before.

import React, { useState } from 'react';

import ReactQuillInput from '@components/atoms/reactQuillInput/ReactQuillInput';

const component = props => {
 const { text } = props;

 const [quillValueState, setQuillValueState] = useState(
    text ? text : ''
  );
  
  const onChange = html => {
    setQuillValueState(html);
  };
  
  const reactQuillMaxLength = 300;
  
  return (
    <Container>
      <ReactQuillInput
        theme="bubble"
        defaultValue={captionState}
        value={captionState}
        onChangeText={onChange}
        placeholder={'Type your text ...'}
        maxLength={reactQuillMaxLength}
      />
    </Container>
    
  )
}

export default component;

import React, { useState } from 'react';
import PropTypes from 'prop-types';

import ReactQuill, { Quill } from 'react-quill';
import Emitter from 'tiny-emitter/instance';

import { CopyPasteQuill } from '@src/utils/copyPasteQuill';

import 'react-quill/dist/quill.snow.css';

require('medium-editor/dist/css/medium-editor.css');
require('../../../styles/content_editor.css');
require('../../../styles/quill.bubble.css');

const ReactQuillInput = props => {
  const { onChangeText, maxLength } = props;

  const [quillState, setQuillState] = useState({});
  const [isMountedState, setIsMontedState] = useState(false);

  if (typeof window === 'object' && isMountedState) {
    Quill.register('modules/clipboard', CopyPasteQuill, true);
  }

  const setQuill = ref => {
    if (!ref || ref === null) return;
    if (typeof ref.getEditor !== 'function') return;
    setQuillState(ref.getEditor());
    setIsMontedState(true);
  };

  const handleChange = html => {
    if (!isMountedState) return;
    if (maxLength) {
      quillState.on('text-change', () => {
        if (quillState.getLength() > maxLength) {
          quillState.deleteText(maxLength, quillState.getLength());
        }
      });
    }
    onChangeText(html);
  };

  Emitter.on('reactQuill::paste', _quill => {
    if (maxLength) {
      if (_quill.getLength() > maxLength) {
        _quill.deleteText(maxLength, _quill.getLength());
      }
    }
  });

  return (
    <ReactQuill
      ref={el => {
        setQuill(el);
      }}
      {...props}
      onChange={handleChange}
    />
  );
};

export default ReactQuillInput;

ReactQuillInput.propTypes = {
  onChangeText: PropTypes.func,
  maxLength: PropTypes.number,
};

ReactQuillInput.defaultProps = {
  onChangeText: () => {},
};

I think we should set the text length inside the onChange event. Something like this:

const handleSetValue: ReactQuill.ReactQuillProps["onChange"] = (
  _value,
  _delta,
  _source,
  _editor
) => {
  // _value is the html string
  setValue(_editor.getContents());
  onChange(_editor.getContents(), _value, _editor.getLength());
};

I Have the same Problem

found a solution

    <ReactQuill
value={this.p.state._sentMessage.message}
onChange={this.handleChange} // Handle change
style={{ height: "150px", maxHeight: "200px", marginBottom: "50px" }}
className="my-5 ReactQuill"
modules={modules}
theme="snow"
/>
//
handleChange = (value: string | any[]) => {
 const maxLength =300;
 if (value.length <= maxLength) {
 this.setState({ message: value });
} else {
 this.setState({ message: value.slice(0, maxLength) });
}
发布评论

评论列表(0)

  1. 暂无评论