How to change the height of textarea with content?
Asked Answered
B

4

9

I am trying to change the height of the textarea as per the content height. I see that the event handler doesn't change the height since it is getting overwritten by the bootstrap style. Please help!

class PostForm extends React.Component {
  constructor(props){
    super(props);
    this.state = {titleHeight: '30', storyHeight: 1};                                                    
    this.handleKeyUp = this.handleKeyUp.bind(this);
  }
  handleKeyUp(event){
    this.setState({titleHeight: document.getElementById('post_title').scrollHeight});
    this.setState({storyHeight: document.getElementById('post_story').scrollHeight});
  }
  render () {
        var csrfToken = $('meta[name=csrf-token]').attr('content');
        return (
          <form action='create' method='post' acceptCharset='UTF-8' className= "form-group">
            <input type='hidden' name='_method' value='patch'/>
            <input type='hidden' name='utf8' value='✓' />
            <input type='hidden' name='authenticity_token' value={csrfToken} />
            <textarea id="post_title" name="post[title]" className="form-control boldText" style={formStyle.textArea} height={this.state.titleHeight} onKeyUp={this.handleKeyUp} placeholder="Title"/>
            <textarea id="post_story" name="post[story]" className="form-control" style={formStyle.textArea} height={this.state.storyHeight} onKeyUp={this.handleKeyUp} placeholder="Start telling the story"/>
            <input name="commit" type="submit" value="Post" className="btn" style={formStyle.button}/>
          </form>
        );
  }
}

const formStyle = {
  textArea: {
    border: 5,
    boxShadow: 'none',
    margin: 5,
    overflow: 'hidden',
    resize: 'none',
    ariaHidden: 'true',
  },
  button: {
    backgroundColor: 'black',
    color: 'white',
    width: 70,
    marginLeft: 18,
    marginRight: 5,
  },
}
Bangka answered 19/10, 2017 at 11:2 Comment(0)
X
12

The textarea HTML component has no attribute height but an attribute rows that you can use for that purpose (e.g. <textarea rows={Math.round(this.state.storyHeight)} ... />).

No CSS style will override what you pass in the style attribute, it works the opposite way. But there is no height in your formStyle definition anyway.

Xyloid answered 19/10, 2017 at 11:38 Comment(0)
S
5

You can do what you want with ref attribute

export default class Textarea extends Component {

  componentDidMount () {
    if (this.multilineTextarea) {
      this.multilineTextarea.style.height = 'auto';
    }
  }

  changeTextarea = () => {
    this.multilineTextarea.style.height = 'auto';
    this.multilineTextarea.style.height = this.multilineTextarea.scrollHeight + 'px';
  }

  render () {
    return (
      <textarea
        onChange={this.changeTextarea}
        ref={ref => this.multilineTextarea = ref}
      />
    );
  }
}

Also here is working DEMO

Sande answered 22/2, 2019 at 12:35 Comment(2)
This works, but it has the side effect of the browser rendering the textarea twice. This is an issue when adding text that goes below the browser view port, which makes the page jump to the top of the text area instead of staying at the bottom where you are editing.Cowrie
For me it works best to have a text area with style="height: auto;" , and update the rows attribute according to its content (by counting the number of lines it contains). this.multilineTextarea.rows = this.multilineTextarea.value.split(/\r\n|\r|\n/).length;Cowrie
E
1

This code can change the textarea height even if it has some text initially, and even after on any change :)

export default class dynamicTextArea extends Component {
    constructor(props){
        super(props);

        this.textAreaRef = React.createRef();
    }

    componentDidMount() {
        this.textareaChange(this.textAreaRef.current);
    }

    textareaChange(ta) {
        ta.style.height = "auto";
        ta.style.height = ta.scrollHeight + "px";
    }

    render() {
        return(
            <textarea
                ref={this.textAreaRef}
                onChange={(e) => this.textAreaChange(e.target)}
            />
        );
    }
}

If you want to decrease the initial height even more then change:

ta.style.height = "auto";

to

ta.styel.height = "30px"; // better if equal to line-height
Earphone answered 15/5, 2020 at 5:33 Comment(0)
E
-1

For any newcomer, checkout react-textarea-autosize to see it it's what you need

Epsomite answered 27/1, 2022 at 17:28 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Renunciation

© 2022 - 2024 — McMap. All rights reserved.