I created a directive in order to make a input that has width automatically resized when keyup (like Google Contacts). However it seems not to be ok, because the width of ea
So this one is more complicated than it might sound, but I think I've got a Plunk here for you that will do the trick.
app.directive("editInline", function($window){
return function(scope, element, attr){
// a method to update the width of an input
// based on it's value.
var updateWidth = function () {
// create a dummy span, we'll use this to measure text.
var tester = angular.element('<span>'),
// get the computed style of the input
elemStyle = $window.document.defaultView
.getComputedStyle(element[0], '');
// apply any styling that affects the font to the tester span.
tester.css({
'font-family': elemStyle.fontFamily,
'line-height': elemStyle.lineHeight,
'font-size': elemStyle.fontSize,
'font-weight': elemStyle.fontWeight
});
// update the text of the tester span
tester.text(element.val());
// put the tester next to the input temporarily.
element.parent().append(tester);
// measure!
var r = tester[0].getBoundingClientRect();
var w = r.width;
// apply the new width!
element.css('width', w + 'px');
// remove the tester.
tester.remove();
};
// initalize the input
updateWidth();
// do it on keydown so it updates "real time"
element.bind("keydown", function(){
// set an immediate timeout, so the value in
// the input has updated by the time this executes.
$window.setTimeout(updateWidth, 0);
});
}
});
EDIT: also, I've changed it to update the input size asynchronously after a keydown event. This will cause it to update more fluidly when you do things like hold a key down.
Based on @notme's answer I created the following gist for my own version of an auto-resizing input angular directive:
https://gist.github.com/Zmaster/6923413
Here is the code:
Template:
<span>
<input type="text" ng-model="value">
<span style="visibility:hidden; position:absolute; left:-1000; top:-1000;">{{value}}</span>
</span>
Directive:
angular.module('autoSizeInput', [])
.directive('autoSizeInput', function() {
return {
replace: true,
scope: {
value: '=inputValue'
},
templateUrl: 'templates/directives/autoSizeInput.html',
link: function(scope, element, attrs) {
var elInput = element.find('input');
var elSpan = element.find('span');
elSpan.html(elInput.val());
scope.$watch('value', function(value) {
if(value) {
elSpan.html(elInput.val());
elInput.css('width', (elSpan[0].offsetWidth + 10) + 'px');
}
});
}
};
});
I've done this before. The solution I used is having an off-screen SPAN with the same text in it, with the same exact font as your textbox, and interrogating its width.
I might have something like this:
<span class="textbox-copy"></span>
.textbox-copy {
position: absolute;
left: -9999px;
top: -9999px;
font: -webkit-small-control;
font: -moz-field;
font-size: 13px;
}
Then on keydown set the innerHTML
of that SPAN, and check its current width. Note that, in Chrome and Firefox at least, an unstyled textbox has a special font of its own. It doesn't just inherit Arial or whatever.
I know it's an old discussion but I wanted to share my solution which I believe is better than all given answers. I've just completed writing an angular directive: angular-autogrow:
You can create a dummy span to store the same string you have in your input textfield.
On keyup you refresh the span content and get the new length.
It is better you create a css rule with text style definition for both span and input text, so you are sure they have the same font style.
Your directive would look like this:
.html
<div edit-inline>
<input type="text" value="hello world">
<span class="dummy">blbla</span>
</div>
.js
app.directive("editInline", function(){
return function(scope, element, attr){
var elInput = element.find('input');
var elDummy = element.find('span');
var inputText = elInput.val();
elDummy.html(inputText);
elInput.bind("keyup", function(){
var inputText = elInput.val();
elDummy.html(inputText);
elInput.css('width', elDummy[0].offsetWidth + 'px');
});
}
});
.css
input, .dummy {
font-size: 12px;
font-family: Arial;
white-space:pre;
}
.dummy {
visibility:hidden; // this would prevent the dummy text to be shown without losing its size
}
Here you can see the plunker