evyros / angularjs-autogrow

AngularJS 1.x directive for auto-grow / auto-resize of textarea elements.
16 stars 15 forks source link

Doesn't update on directive load with pre-existing text #9

Closed sjeannin closed 7 years ago

sjeannin commented 7 years ago

Hi, I was having an issue with the directive (very good, by the way!) when put inside another directive and then having initial text on page load.

I fixed this using a $timeout in the autogrowFn call and changing the event listener.

I hope it may help other users :)

(function(){
    'use strict';
    angular.module('angular-autogrow', []).directive('autogrow', ['$window', '$timeout', function($window, $timeout){
        return {
            link: function($scope, $element, $attrs){

                /**
                 * Default settings
                 */
                $scope.attrs = {
                    rows: 1,
                    maxLines: 999
                };

                /**
                 * Merge defaults with user preferences
                 */
                for(var i in $scope.attrs){
                    if($attrs[i]){
                        $scope.attrs[i] = parseInt($attrs[i]);
                    }
                }

                /**
                 * Calculates the vertical padding of the element
                 * @returns {number}
                 */
                $scope.getOffset = function(){
                    var style = $window.getComputedStyle($element[0], null),
                        props = ['paddingTop', 'paddingBottom'],
                        offset = 0;

                    for(var i=0; i<props.length; i++){
                        offset += parseInt(style[props[i]]);
                    }
                    return offset;
                };

                /**
                 * Sets textarea height as exact height of content
                 * @returns {boolean}
                 */
                $scope.autogrowFn = function(){
                    $timeout(function() {
                        var newHeight = 0, hasGrown = false;
                        if (($element[0].scrollHeight - $scope.offset) > $scope.maxAllowedHeight) {
                            $element[0].style.overflowY = 'scroll';
                            newHeight = $scope.maxAllowedHeight;
                        }
                        else {
                            $element[0].style.overflowY = 'hidden';
                            $element[0].style.height = 'auto';
                            newHeight = $element[0].scrollHeight - $scope.offset;
                            hasGrown = true;
                        }
                        $element[0].style.height = newHeight + 'px';
                        return hasGrown;
                    });
                };

                $scope.offset = $scope.getOffset();
                $scope.lineHeight = ($element[0].scrollHeight / $scope.attrs.rows) - ($scope.offset / $scope.attrs.rows);
                $scope.maxAllowedHeight = ($scope.lineHeight * $scope.attrs.maxLines) - $scope.offset;

                $scope.$watch($attrs.ngModel, $scope.autogrowFn);
                /**
                 * Auto-resize when there's content on page load
                 */
                if($element[0].value !== ''){
                    $scope.autogrowFn();
                }
            }
        }
    }]);
})();

Please note that I know it should be a Pull Request, but I didn't have the possibility to do this when I found the fix at work ;)

evyros commented 7 years ago

@sjeannin Thanks for sharing! I'll do the change myself.