How to create a “twitter like” remaining characters count with React
Solution 1
Here is a rough version of what you wanted. Doesn't handle when chars_left
goes below zero, but should be easy to implement.
var TwitterInput = React.createClass({
getInitialState: function() {
return {
chars_left: max_chars
};
},
handleChange(event) {
var input = event.target.value;
this.setState({
chars_left: max_chars - input.length
});
},
render: function() {
return (
<div>
<textarea onChange={this.handleChange.bind(this)}></textarea>
<p>Characters Left: {this.state.chars_left}</p>
</div>
);
}
});
https://jsfiddle.net/terda12/b0y4jL6t
Solution 2
I have made a version too,
I am using styled-components for styling.
import React from "react";
import styled from "styled-components";
class CharCountInput extends React.Component {
state = {
charsLeft: null
};
componentDidMount() {
this.handleCharCount(this.props.value);
}
handleCharCount = value => {
const { maxChars } = this.props;
const charCount = value.length;
const charsLeft = maxChars - charCount;
this.setState({ charsLeft });
};
handleChange = event => {
this.handleCharCount(event.target.value);
this.props.onChange(event);
};
renderCharactersLeft = () => {
const { charsLeft } = this.state;
let content;
if (charsLeft >= 0) {
content = <SpanOK>{`characters left: ${charsLeft}`}</SpanOK>;
} else if (charsLeft != null && charsLeft < 0) {
const string = charsLeft.toString().substring(1);
content = <SpanError>{`too many characters: ${string}`}</SpanError>;
} else {
content = null;
}
return content;
};
render() {
const { onBlur, value, type, name, placeholder } = this.props;
return (
<Div>
<Input
onChange={this.handleChange}
value={value}
type={type}
name={name}
placeholder={placeholder}
/>
{this.renderCharactersLeft()}
</Div>
);
}
}
export default CharCountInput;
const Div = styled.div`
display: flex;
flex-direction: column;
`;
const Input = styled.input`
box-sizing: border-box;
display: block;
padding: 7px;
width: 100%;
margin: 0 0 0.1rem 0;
border: 1px solid blue;
border-radius: 7px;
font: inherit;
outline: none;
&:focus {
box-shadow: 0 0 4px blue;
}
`;
const Span = styled.span`
align-self: flex-end;
font-size: 0.9rem;
margin: 0 8px 10px 0;
`;
const SpanOK = styled(Span)`
color: black;
`;
const SpanError = styled(Span)`
color: red;
`;
And inside your form:
<CharCountInput
onChange={this.handleChange}
value={this.state.title}
type="text"
maxChars={150}
name="title"
placeholder="Enter text here..."
/>
ghostCoder
Love to code and explore. Check out http://thecamelcase.com/
Updated on June 28, 2022Comments
-
ghostCoder almost 2 years
I'm looking to make a react counter with "target character count" for a textarea just like Twitter's does, which reduces as the user types.
For example, on the "Meta Description" field, the target character count is 160. So, if the field is blank, the number would be 160. As the user types, the count is decreased with each character added to the input field until it reaches zero.
If the count is higher than the target, the numbers are written in red with a minus sign in front (again, just like twitter).
One way to do this is the listen to the onChange event on the textarea, and update the state of the component (which has the textarea and the counter), and then use that to calculate length and render the remaining char counter.
Is there a more efficient way?