AngularJS directive input width resize by keyup

前端 未结 5 794
余生分开走
余生分开走 2021-01-06 06:36

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

相关标签:
5条回答
  • 2021-01-06 07:02

    So the problem is that you have to measure the text in the input. You can't just guess if you want it to fit right.

    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.

    The basic process:

    1. Create a temporary span.
    2. Apply the same font styling to the span.
    3. Put the value in the span as text.
    4. Measure the span.
    5. Delete the span.

    Code: and Plunk

    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.

    0 讨论(0)
  • 2021-01-06 07:03

    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');
              }   
            }); 
          }   
        };  
      });
    
    0 讨论(0)
  • 2021-01-06 07:18

    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.

    0 讨论(0)
  • 2021-01-06 07:18

    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:

    • No jQuery dependency.
    • Simple and high-performance (no $watchers / expensive DOM manipulation).
    • Works well with any CSS definition (paddings / box-sizing).
    0 讨论(0)
  • 2021-01-06 07:24

    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

    0 讨论(0)
提交回复
热议问题