EB2127
EB2127

Reputation: 1858

How to show count of number of characters entered in a contentEdible div?

Based on the code in this great answer, I have the following React app which will highlight user input text after N number of characters are entered. This uses an event change with the innerText of an HTML element, and puts the "extra characters" in a stylized span:

import React, { useRef} from "react";


export default function App() {

  // create a custon contentEditable div
  const EditDiv = (props) => {

    let textRef = useRef(null);  // grab innerHTML

    // on change event
    const contentChange = (event) => {

      let html = event.target.innerText; // inner text, no HTML tags

      // users add input, no problem
      // but once inner text length greater than the max length:
      if (html.length > props.charLimitLength) {

        // text before limit hit
        let start =  html.slice(0, props.charLimitLength);
        // text after limit hit
        let overlimit =  html.slice(props.charLimitLength);
        // style overlimit with span tag
        overlimit = `<span style="background:${props.highlightColor}">${overlimit}</span>`;
        //set text as innerHTML 
        textRef.current.innerHTML = start + overlimit
        
        // set the cursor at the end of innerHTML; otherwise, cursor jumps to start
        let range = document.createRange();
        let selection = window.getSelection();  // represents the range of text selected by the user 
        range.setStart(textRef.current.lastChild, 1);

        selection.removeAllRanges();
        selection.addRange(range);

      }
    }

    return <div>
         Characters: {countChar}
        <div ref={textRef} contentEditable onInput={contentChange}></div>
        </div>
  }
  
  return (
    <div>
      <b> Enter text in the div here, max length 10: </b>
      <EditDiv charLimitLength={10} highlightColor={"red"} />
    </div>
  )
}

My problem is that, I would like to show the count of the characters as well.

Normally, I would try this with the React hook useState(), e.g.

const [count, setCount] = useState(0);

but in this case, using setCount(html.length) i.e. setCount(event.target.innerText.length) isn't an option, as it's out of scope for showing the count, e.g. <p> You typed {count} characters </p>

I'm stumped how to do this.

In terms of my larger goals, I'm trying to recreate the Twitter character count feature here: enter image description here

After 280 characters, the text is highlighted:

enter image description here

Upvotes: 0

Views: 824

Answers (1)

Arun Kumar Mohan
Arun Kumar Mohan

Reputation: 11915

You can use a state variable to track the character count and update it in the contentChange function.

const [count, setCount] = useState(0)

const contentChange = (event) => {
  const html = event.target.innerText
  setCount(html.length)

  if (html.length > props.charLimitLength) {
    setCount(props.charLimitLength - html.length)
    // rest of the code
  }
}

Working CodeSandbox

Screenshots

Positive character count when the text length is less than the max length (10)

positive character count

Negative character count when the text length exceeds the max length (10)

negative character count

Upvotes: 1

Related Questions