Auto-resizing text fields with Stimulus

Having a text field grow with its contents is a much nicer experience than having to scroll all the way through it. Writing and reviewing articles for my website wasn’t the easiest because of that. I mostly wrote in a text editor and copied/pasted to avoid having to scroll as much. That work-flow put some barriers up in terms of getting an article written. I’ve been experimenting with Stimulus lately, and figured it would be a good learning experience to solve the problem using it.

It really isn’t all that complex. There are different, and likely better, ways to solve this problem.

// expandable_field_controller.js
import { Controller } from 'stimulus'

export default class extends Controller {

  static targets = ['input']

  initialize() {
    this.setup()
    this.resize()
  }

  setup() {
    this.inputTarget.style.height = `${this.inputTarget.scrollHeight}px`
  }

  resize() {
    this.inputTarget.style.height = 'auto'
    this.inputTarget.style.height = `${this.inputTarget.scrollHeight}px`
  }

}

It’s worth noting that I have a min-height set on <textarea> controls that this is used with. Setting the height to auto on the resize() call prevented a weird bug when reducing the height (?). I chose to use the input event to trigger the behaviour.

<div data-controller="expandable-field">
  <%=
    form.text_area :content,
      data: {
        target: "expandable-field.input",
        action: "input->expandable-field#resize"
      }
  %>
</div>