Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto grow textarea with knockout js

I've implemented the logic of auto-expanding the height of a textarea on the keyup event. However, I want the textarea to also initialise its height once the value is bound to the textarea via a knockout custom binding. Any solutions? (With the use of only KnockoutJS, without using jQuery or any other library.)

like image 833
user2235768 Avatar asked Mar 12 '26 23:03

user2235768


1 Answers

I'd strongly advice against using an event to trigger the resize. Instead, you can use the textInput binding to keep track of the input in an observable and subscribe to changes there.

Here's an example:

<textarea data-bind="textInput: value, autoResize: value"></textarea>
ko.bindingHandlers.autoResize = {
  init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    ko.computed(function() {
      ko.unwrap(valueAccessor());
      resizeToFitContent(element);
    })
  }
};

This works because:

  • The textInput binding writes any input change to an observable value variable.
  • The computed uses this value to trigger a resize. This creates a subscription automatically.

This is better than a keydown approach because it deals with stuff like Right Mouse Button > cut

Example showing the event equivalent as well:

var resizeToFitContent = function(el) {
  // http://stackoverflow.com/a/995374/3297291
  el.style.height = "1px";
  el.style.height = el.scrollHeight + "px";
}


ko.bindingHandlers.autoResize = {
  init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    ko.computed(function() {
      ko.unwrap(valueAccessor());
      resizeToFitContent(element);
    })
  }
};

ko.applyBindings({ 
  value: ko.observable("Test"), 
  
  onKey: function(data, event) {
  	resizeToFitContent(event.target);
  } 
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<textarea data-bind="textInput: value, autoResize: value"></textarea>
<textarea data-bind="event: { keyup: onKey }"></textarea>
like image 57
user3297291 Avatar answered Mar 15 '26 13:03

user3297291