AngularJS指令输入宽度通过keyup调整大小

时间:2013-07-01 18:09:54

标签: angularjs angularjs-directive

我创建了一个指令,以便在keyup(如Google Contacts)时自动调整宽度的输入。然而,似乎并不好,因为每个字符的宽度是不同的。你能帮我提一下更优化的方法吗? TKS。

http://plnkr.co/edit/DSn0JDDShOXvuXXF9PP2?p=preview

5 个答案:

答案 0 :(得分:6)

基于@ notme的答案,我为自己的自动调整大小输入角度指令版本创建了以下要点:

https://gist.github.com/Zmaster/6923413

以下是代码:

模板:

<span>
  <input type="text" ng-model="value">
  <span style="visibility:hidden; position:absolute; left:-1000; top:-1000;">{{value}}</span>
</span>

指令:

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');
          }   
        }); 
      }   
    };  
  });

答案 1 :(得分:5)

您可以创建一个虚拟范围来存储输入文本字段中的相同字符串 在keyup上,您可以刷新span内容并获得新的长度 最好为span和input文本创建带有文本样式定义的css规则,因此您可以确定它们具有相同的字体样式。

您的指令如下所示:

<强> 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
} 

在这里,您可以看到plunker

答案 2 :(得分:4)

所以问题是你必须测量输入中的文本。你不能猜测你是否希望它适合。

所以这个比听起来要复杂得多,但我认为我有Plunk here for you可以解决这个问题。

基本流程:

  1. 创建临时范围。
  2. 将相同的字体样式应用于范围。
  3. 将值作为文本放在范围内。
  4. 测量范围。
  5. 删除范围。
  6. 代码: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);
            });
    
        }
    });
    

    编辑:此外,我已将其更改为在 keydown 事件后异步更新输入大小。当您执行诸如按住键之类的操作时,这将使其更加流畅地更新。

答案 3 :(得分:2)

我以前做过这个。我使用的解决方案是使用屏幕外的SPAN,其中包含相同的文本,与文本框的字体完全相同,并询问其宽度。

我可能会有这样的事情:

<span class="textbox-copy"></span>

.textbox-copy {
  position: absolute;
  left: -9999px;
  top: -9999px;
  font: -webkit-small-control;
  font: -moz-field;
  font-size: 13px;
}

然后在keydown上设置该SPAN的innerHTML,并检查其当前宽度。请注意,至少在Chrome和Firefox中,无样式的文本框具有自己的特殊字体。它不只是继承Arial或其他任何东西。

答案 4 :(得分:0)

我知道这是一个古老的讨论,但我想分享我的解决方案,我认为这比所有给出的答案都要好。 我刚刚完成了一个角度指令:angular-autogrow

  • 没有jQuery依赖。
  • 简单而高性能(没有$观察者/昂贵的DOM操作)。
  • 适用于任何CSS定义(填充/大小调整)。