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");
};
});
@muratsplat
Copy link

if I can convert your coffee code to native js code 😃

@muratsplat
Copy link

I have written my version with little changes

angular.module('mayApp')

  .directive('autogrow', function () {
    return {

      restrict: 'A',
      link: function postLink(scope, element, attrs) {
          // hidding the scroll of textarea
          element.css('overflow', 'hidden');

          var update = function(){

              element.css("height", "auto");

              var height = element[0].scrollHeight;

              if(height > 0){

                  element.css("height", height + "px");
                }

          };

          scope.$watch(attrs.ngModel, function(){

              update();
          });

          attrs.$set("ngTrim", "false");
      }
    };
  });

on view layer

<textarea autogrow class="form-control" rows="10" placeholder="Enter ..." ng-model="content.body" ng-maxlength="16777215" ng-minlength="10" required  name="content"></textarea>

@laurensnl
Copy link

Thanks guys! Works perfect! There does however seem to be an issue with Chrome (Version 46.0.2490.80 (64-bit) on Mac). Setting the element height twice every keystroke (first to auto, then to the desired height) causes a slight but annoying delay while typing. Any suggestions to solve that?

@pacificsharma
Copy link

Thanks a lot.

@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