Skip to content

Instantly share code, notes, and snippets.

@enapupe
Last active February 8, 2021 11:26
Show Gist options
  • Save enapupe/2a59589168f33ca405d0 to your computer and use it in GitHub Desktop.
Save enapupe/2a59589168f33ca405d0 to your computer and use it in GitHub Desktop.
Auto Grow/Shrink textarea directive for AngularJS (credits to this gist https://gist.github.com/thomseddon/4703968, specially @huyttq)
angular.module("myApp").directive("autoGrow", function(){
return function(scope, element, attr){
var update = function(){
element.css("height", "auto");
var height = element[0].scrollHeight;
if(height > 0){
element.css("height", height + "px");
}
};
scope.$watch(attr.ngModel, function(){
update();
});
attr.$set("ngTrim", "false");
};
});
@dcolley
Copy link

dcolley commented May 5, 2017

thank you! It works for me on Chrome 57 and IOS 9.

@JavyMB
Copy link

JavyMB commented May 9, 2017

Thank you ! works for me too.

@suisun2015
Copy link

@muratsplat
Excellent Work! Thanks!

@bettysteger
Copy link

In case someone uses debounced model updates - this will just work with a timeout, which is not very nice, so i changed the code a bit to also listen to the input event:

angular.module('myApp').directive('autogrow', function () {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      // hide scroll of textarea
      element.css('overflow', 'hidden');

      var autogrow = function () {
        element.css('height', 'auto');

        var height = element[0].scrollHeight;

        if(height > 0){
          element.css('height', height + 'px');
        }
      };

      // using 'input' event on element, because of debounced model update
      element.on('input', autogrow);

      // need this too, for initialize
      scope.$watch(attrs.ngModel, autogrow);
    }
  };
});

@suisun2015
Copy link

suisun2015 commented Aug 22, 2018

@lpsBetty
Your trick of binding input event is great! Thanks.
PS:
I was implementing autogrowing textarea in ionic 1 modal template while I should consider a delay effect of modal opening. So I added a modal.shown watcher.

angular.module('myApp').directive('autogrow', function () {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      // hide scroll of textarea
      element.css('overflow', 'hidden');

      var autogrow = function () {
        element.css('height', 'auto');

        var height = element[0].scrollHeight;

        if(height > 0){
          element.css('height', height + 'px');
        }
      };

      // using 'input' event on element, because of debounced model update
      element.on('input', autogrow);

      // need this too, for initialize
      scope.$watch(attrs.ngModel, autogrow);

      /////////////////////////////////////////////////
      // apply after modal is shown <- ADD HERE
      scope.$on('modal.shown', autogrow);
    }
  };
});

Hope this might help someone.

@bettysteger
Copy link

in case textarea is not yet visible:

if(!element.is(':visible')) {
  scope.$watch(function () { return element.is(':visible'); }, function (visible) {
    if(visible) {
      autogrow();
      scope.$applyAsync();
    }
  });
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment