【问题标题】:Angular Data Binding - Input type="number"角度数据绑定 - 输入类型 =“数字”
【发布时间】:2013-10-24 15:49:10
【问题描述】:

我在使用 AngularJS 绑定数值时遇到问题。

我在 JSFiddle 上放了一个简化的例子:http://jsfiddle.net/treerock/ZvdXp/

<div ng-controller="MyCont" ng-app>  
    <input type="number" min="0" max="50" value="{{value}}" ng-model="value" />    
    <input type="text" value="{{value}}" ng-model="value" />
    <input type="range" min="0" max="50" value="{{value}}" ng-model="value" />    
    {{value}}   
</div>

这应该是三种不同类型的输入字段,如果您更新一种,那么所有值都应该更新。除了数字输入之外,这是有效的。例如如果我在第一个数字框中输入 20,它会更新所有其他值实例。但如果我更新文本或范围输入,数字输入变为空白。

我想知道问题是否在于数字在字段之间的表示/转换方式。例如数字输入是浮点数,文本输入是字符串?

【问题讨论】:

    标签: javascript angularjs data-binding


    【解决方案1】:

    你是对的,它与字符串与数字类型有关。我使用了$scope.watch 语句来修复它:http://jsfiddle.net/ZvdXp/6/

    【讨论】:

      【解决方案2】:

      您也可以使用指令来解决此问题。我创建了一个指令来强制绑定到数字字段的输入为数字。

      HTML:

      myApp.directive('numericbinding', function () {
              return {
                  restrict: 'A',
                  require: 'ngModel',
                  scope: {
                      model: '=ngModel',
                  },                
                 link: function (scope, element, attrs, ngModelCtrl) {
                     if (scope.model && typeof scope.model == 'string') {
                         scope.model = parseInt(scope.model);
                     }                  
                  }
              };
      });
      

      您可以像这样将它添加到您的数字字段中:

      <input data-ng-model="stringnumber" numericbinding type="number"/>    
      

      完整示例:http://jsfiddle.net/tdjager/cMYQ3/1/

      【讨论】:

      • 据我所知,这只在链接阶段有效一次
      • @rweng 是否有机会以 $watch 的方式对其进行更新?我喜欢指令的想法,所以想在这里应用它。我的角度仍然很差。
      • 好的,我自己想出来的,见:stackoverflow.com/questions/27237827/…
      【解决方案3】:

      我已经扩展了蒂姆的答案,使其在用户更新控件值后更正数据类型。

      myApp.directive('numericbinding', function () {
          return {
              restrict: 'A',
              require: 'ngModel',
              scope: {
                  model: '=ngModel',
              },                
              link: function (scope, element, attrs, ngModelCtrl) {
                 if (scope.model && typeof scope.model == 'string') {
                     scope.model = parseInt(scope.model);
                 } 
                 scope.$watch('model', function(val, old) {
                     if (typeof val == 'string') {
                         scope.model = parseInt(val);
                     }
                 });                 
              }
          };
      });
      

      【讨论】:

        【解决方案4】:

        如果您更喜欢在模型中保存数值,您可以使用指令将文本输入和范围输入生成的字符串通过角度解析器转换为数值,如下所示:

        myApp.directive('numericsaving', function () {
            return {
                restrict: 'A',
                require: '?ngModel',
                scope: {
                    model: '=ngModel'
                },
                link: function (scope, element, attrs, ngModelCtrl) {
                    if (!ngModelCtrl) {
                        return;
                    }
                    ngModelCtrl.$parsers.push(function (value) {
                        if (!value || value==='' || isNaN(parseInt(value)) || parseInt(value)!==value) {
                            value=0;
                        }
                        return parseInt(value);
                    });
                }
            };
        });
        

        在 HTML 中,保持数字输入不变,并以这种方式在其他输入中添加指令:

        <input type="number" min="0" max="50" value="{{value}}" ng-model="value" />
        <input type="range" min="0" max="50" value="{{value}}" ng-model="value" numericsaving/>
        <input type="text" value="{{value}}" ng-model="value" numericsaving/>
        

        角度解析器将在将字符串输入保存到模型之前将其转换为数值,因此数值输入将自动工作。 Here the complete fiddle.

        此外,如果用户在文本输入中插入字母或任何奇怪的字符,它们将不会保存在模型中,从而防止在您的应用程序的单一事实来源中出现无效值。 只有文本开头的“+”和“-”字符会被正确解析,所以即使是负值也是允许的。 我希望这有帮助! :)

        【讨论】:

        • 能否请您提供一个打字稿版本?我遇到了 $parsers 无法识别的问题
        • parseInt(value)!==value 这个条件总是假的,因为值是一个字符串并且解析的值是一个数字,你可以把它改成 != (就像小提琴一样)但是然后没用的
        • 你是对的 Souhaieb,parseInt(value)!==value 永远是 false,正确的版本是 parseInt(value)!=value。这个检查不是绝对没用的,它可以防止字符串以数字开头,例如: var s="25"; parseInt(值)==值; //return true ----- var s="25abc"; parseInt(值)==值; //返回假
        • 检查也许不是没用的,但确实!==总是结果为假,因为解析的值是数字。 @ainos984:你最近的评论表明了你的想法,但并不完全正确:你需要说var s="25"; parseInt(value)===value,它总是错误的。
        【解决方案5】:

        TypeScript 版本启发了 ainos984,为了后代

             export class ngIntegerDirective implements ng.IDirective {
        
                static directiveKey: string = 'ngInteger';
        
                require: string = 'ngModel';
        
                link = (scope, ele, attr, ctrl: ng.INgModelController) => {
                    ctrl.$parsers.unshift(function (viewValue) {
                        let result: number = parseInt(viewValue,10);
                        if (isNaN(result)) {
                            result = 0;
                        }
                        return result;
                    });
                }
        
                public static Factory(): ng.IDirectiveFactory {
                    const directive = () => new ngIntegerDirective();
                    directive.$inject = []; //injecter les dépendances ici
                    return directive;
                }
            }
        

        【讨论】:

          猜你喜欢
          • 2017-11-17
          • 1970-01-01
          • 2019-03-31
          • 1970-01-01
          • 1970-01-01
          • 2013-12-14
          • 1970-01-01
          • 2021-11-30
          • 1970-01-01
          相关资源
          最近更新 更多