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

javascript - How to create a “twitter like” remaining characters count with React - Stack Overflow

programmeradmin7浏览0评论

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 ponent (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?

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 ponent (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?

Share Improve this question asked Oct 12, 2015 at 10:46 ghostCoderghostCoder 7,6559 gold badges53 silver badges74 bronze badges 2
  • 1 This would be the exact way. – Henrik Andersson Commented Oct 12, 2015 at 11:05
  • 1 reactfordesigners./labs/… has an example of exactly that. – elithrar Commented Oct 12, 2015 at 11:26
Add a ment  | 

5 Answers 5

Reset to default 14

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/terda12/b0y4jL6t

I have made a version too,

I am using styled-ponents for styling.

import React from "react";
import styled from "styled-ponents";

class CharCountInput extends React.Component {
  state = {
    charsLeft: null
  };

  ponentDidMount() {
    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..."
/>

here is my version

setInterval(function (){
    var counter = document.getElementById('counter')
    var input = document.getElementById('input')
    var input_v = input.value;
    var input_vl = input_v.length;
    counter.innerHTML = input_vl;
},0)
<body>
    <textarea id="input" cols="30" rows="10"></textarea>
    <span id="counter"></span>
</body>

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>
        );
    }
});  

This answer above from Keith Young works great (tweaked some for my react app). To add the set limit for max characters so it doesn't go negative, simply add maxlength={max_chars} to the textarea element.

Here React Native Way to do this but you can use this method with react.js too

//your state
constructor() {
    super();
    this.state = {
        chars_left: 500,
        chars_exceed: false,
        post_text: ''
    };
};

//handle change function 
handleChange(text) {
    this.setState({
        chars_left: text.length,
        chars_exceed: text.length >  500  ?  true  :  false,
        post_text: text,
    });
}

//input inside render
render() { 
    return (
        <View>
            //text area
            <Textarea 
                rowSpan={10} 
                value={this.state.post_text}
                onChangeText={this.handleChange.bind(this)}
                placeholder="Type here"/>
            //text balance count
            <Text>{ this.state.chars_left }/500</Text>
        </View>
    )
}
发布评论

评论列表(0)

  1. 暂无评论