Reputation: 1858
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:
After 280 characters, the text is highlighted:
Upvotes: 0
Views: 824
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
}
}
Screenshots
Positive character count when the text length is less than the max length (10)
Negative character count when the text length exceeds the max length (10)
Upvotes: 1