-
-
Save enapupe/2a59589168f33ca405d0 to your computer and use it in GitHub Desktop.
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"); | |
}; | |
}); |
Love it. My only wish is that the textarea
did not start out defaulting to two lines. Any idea how to get it to start with a single line, then expand by a line at a time as it does? I guess scrollHeight
is doing that?
Here it is in CoffeeScript, injected into a larger project:
autoGrow = ->
(scope, element, attrs) ->
update = ->
element.css 'height', 'auto'
height = element[0].scrollHeight
element.css 'height', height + 'px' if height > 0
scope.$watch attrs.ngModel, update
attrs.$set 'ngTrim', 'false'
# Register
App.Directives.directive 'autoGrow', autoGrow
Fixed for my purposes, though still curious if there might be a more elegant way to somehow control the children element sizes instead:
autoGrow = ->
(scope, element, attrs) ->
update = ->
if element[0].scrollWidth > element.outerWidth isBreaking = true else isBreaking = false
element.css 'height', 'auto' if isBreaking
height = element[0].scrollHeight
element.css 'height', height + 'px' if height > 0
scope.$watch attrs.ngModel, update
attrs.$set 'ngTrim', 'false'
# Register
App.Directives.directive 'autoGrow', autoGrow
@kimardenmiller can I use your code in my project ?
if I can convert your coffee code to native js code 😃
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>
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?
Thanks a lot.
thank you! It works for me on Chrome 57 and IOS 9.
Thank you ! works for me too.
@muratsplat
Excellent Work! Thanks!
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);
}
};
});
@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.
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();
}
});
}
Note: textarea won't resize if the
ng-maxlength
is exceeded, which is probably a good thing. Actually the$watcher
on ngModel doesn't fire anymore.