Adaptive height using Vue.js

by ChangJoo Park

HTML

<div id="app">
  <div>
    <h1>Adaptive Height textarea</h1>
    <auto-expand-textarea></auto-expand-textarea>
  </div>
</div>

<template id="auto-expand-textarea">
  <textarea v-model="text" class="textarea" :rows="currentRows"></textarea>
</template>

CSS

.textarea {
  display: block;
  box-sizing: padding-box;
  overflow: auto;
  padding: 10px;
  width: 250px;
  font-size: 14px;
  margin: 50px auto;
  border-radius: 6px;
  box-shadow: 2px 2px 8px rgba(0, 0, 0, .3);
  border: 0;
}

body {
  background-color: #4A90E2;
}

JavaScript

var AUTO_EXPAND_TEXTAREA = {
  template: '#auto-expand-textarea',
  data: function() {
    return {
      text: '',
      minRows: 2,
      maxRows: 5,
      currentRows: 2,
      baseScrollHeight: -1
    }
  },
  mounted: function () {
		this.baseScrollHeight = this.$el.scrollHeight
    this.currentRows = this.minRows
  },
  watch: {
  	text: function () {
			this.updateRows()
		}
	},
  methods: {
  	updateRows: function () {
    	if (this.text === '') {
      	this.currentRows = this.minRows
        return
			}
    	const fontSize = 14
			let rows = Math.ceil((this.$el.scrollHeight - this.baseScrollHeight) / fontSize) 
      
      if (rows > this.maxRows) {
      	rows = this.maxRows
			} else if (rows < this.minRows) {
      	rows = this.minRows
      }
      
      this.currentRows = rows
    }
	}
}

new Vue({
  el: '#app',
  components: {
    'auto-expand-textarea': AUTO_EXPAND_TEXTAREA
  }
})