代码之家  ›  专栏  ›  技术社区  ›  BrandonLWhite

Angularjs ng选项使用模型编号,但未选择初始值

  •  65
  • BrandonLWhite  · 技术社区  · 11 年前

    我正在尝试将ng选项与 <select> 将数字整数值绑定到相应选项列表。在我的控制器中,我有这样的东西:

    myApp.controller('MyCtrl', function() {
        var self = this;
    
        var unitOptionsFromServer = {
            2: "mA",
            3: "A",
            4: "mV",
            5: "V",
            6: "W",
            7: "kW"
        };
    
        self.unitsOptions = Object.keys(unitOptionsFromServer).map(function (key) {
            return { id: key, text: unitOptionsFromServer[key] };
        });
    
        self.selectedUnitOrdinal = 4; // Assume this value came from the server.
    });
    

    HTML格式:

    <div ng-controller="MyCtrl as ctrl">
        <div>selectedUnitOrdinal: {{ctrl.selectedUnitOrdinal}}</div>
        <select ng-model="ctrl.selectedUnitOrdinal" ng-options="unit.id as unit.text for unit in ctrl.unitsOptions"></select>
    </div>
    

    这里有一个 jsFiddle 证明了问题,以及我已经采取但不满意的一些其他方法。

    选择选项初始化为空值,而不是本例中预期的“mV”。如果您选择不同的选项--selectedUnitOrdinal正确更新,那么绑定似乎可以正常工作。

    我注意到,如果您将初始模型值设置为字符串而不是数字,那么初始选择会起作用(请参见小提琴中的#3)。

    我真的很希望ng选项能很好地处理数字选项值。我如何才能优雅地做到这一点?

    12 回复  |  直到 11 年前
        1
  •  107
  •   Christophe L    9 年前

    Angular的文档 ng-select 指令解释了如何解决这个问题。看见 https://code.angularjs.org/1.4.7/docs/api/ng/directive/select (最后一节)。

    您可以创建 convert-to-number 指令并将其应用于您的select标记:

    JS文件 :

    module.directive('convertToNumber', function() {
      return {
        require: 'ngModel',
        link: function(scope, element, attrs, ngModel) {
          ngModel.$parsers.push(function(val) {
            return val != null ? parseInt(val, 10) : null;
          });
          ngModel.$formatters.push(function(val) {
            return val != null ? '' + val : null;
          });
        }
      };
    });
    

    HTML格式 :

    <select ng-model="model.id" convert-to-number>
      <option value="0">Zero</option>
      <option value="1">One</option>
      <option value="2">Two</option>
    </select>
    

    注意:我发现doc中的指令不处理null,所以我不得不稍微调整一下。

        2
  •  46
  •   re-gor    10 年前

    也许这有点混乱,但结果可以在没有特殊功能的情况下实现

    <select ng-model="ctrl.selectedUnitOrdinal" ng-options="+(unit.id) as unit.text for unit in ctrl.unitsOptions"></select>
    
        3
  •  17
  •   Mathew Berg Lucas    11 年前

    这是因为当你得到unit.id时,它返回的是字符串而不是整数。javascript中的对象将其键存储为字符串。所以,唯一的方法就是通过报价来围绕4。

    编辑

    <select ng-model="ctrl.selectedUnitOrdinal" ng-options="convertToInt(unit.id) as unit.text for unit in ctrl.unitsOptions"></select>
    
    $scope.convertToInt = function(id){
        return parseInt(id, 10);
    };
    
        4
  •  9
  •   zooblin    10 年前

    您还可以定义筛选器 number ,此筛选器将自动将字符串值解析为int:

    <select ng-model="ctrl.selectedUnitOrdinal" ng-options="unit.id|number as unit.text for unit in ctrl.unitsOptions"></select>
    
    
    angular.module('filters').filter('number', [function() {
            return function(input) {
                return parseInt(input, 10);
            };
        }]);
    
        5
  •  9
  •   s3r3k    10 年前

    只需添加Christophe的答案:实现和维护它的最简单方法是发出指令:

    JS文件:

    .directive('convertToNumber', function() {
      return {
        require: 'ngModel',
        link: function(scope, element, attrs, ngModel) {
          ngModel.$parsers.push(function(val) {
            //saves integer to model null as null
            return val == null ? null : parseInt(val, 10);
          });
          ngModel.$formatters.push(function(val) {
            //return string for formatter and null as null
            return val == null ? null : '' + val ;
          });
        }
      };
    });
    

    Christophe的答案对“0”不正确,因为在“val?”测试中返回false。

        6
  •  8
  •   Vid Stoschitzky    6 年前

    可以使用ng值属性。这样地:

    <select ng-model="model.id">
      <option ng-value="0">Zero</option>
      <option ng-value="1">One</option>
      <option ng-value="2">Two</option>
    </select>
        7
  •  7
  •   Ted Scheckler    7 年前

    我认为其他解决方案对于简单地将值建立为整数来说过于复杂。我会使用:

    <select ng-model="model.id">
        <option ng-value="{{ 0 }}">Zero</option>
        <option ng-value="{{ 1 }}">One</option>
        <option ng-value="{{ 2 }}">Two</option>
    </select>
    
        8
  •  3
  •   tymeJV    11 年前

    Angular正在查看您的 id 属性作为字符串,添加引号:

    self.selectedUnitOrdinal = "4";
    
        9
  •  3
  •   emil.c    10 年前

    与tymeJV的答案非常相似,简单的解决方法是将默认选择编号转换为如下字符串:

    self.selectedUnitOrdinal = valueThatCameFromServer.toString();
    

    这样,您不必对数字进行硬编码,只需转换任何收到的值即可。这是一个简单的解决方案,没有任何过滤器或指令。

        10
  •  2
  •   mangesh    8 年前
    <select ng-model="ctrl.selectedUnitOrdinal" ng-options="+(unit.id) as unit.text for unit in ctrl.unitsOptions"></select>
    
        11
  •  1
  •   oadcub    7 年前

    将unitsOptions中的id属性设置为数字

    self.unitsOptions = Object.keys(unitOptionsFromServer).map(function (key) {
            return { id: +key, text: unitOptionsFromServer[key] };
        });
    

    http://jsfiddle.net/htwc10nx/

        12
  •  0
  •   bwitkowicz    10 年前

    虽然Mathew Berg提供的解决方案有效,但它可能会打破使用字符串值选择选项的其他选择。如果您试图编写一个通用指令来处理选择,这可能是一个问题(就像我所做的那样)。

    一个很好的解决方法是检查值是否为数字(即使它是包含数字的字符串),然后只进行转换,如下所示:

    angular.module('<module name>').filter('intToString', [function() {
            return function(key) {
                return (!isNaN(key)) ? parseInt(key) : key;
            };
        }]);
    

    或作为控制器方法:

    $scope.intToString = function(key) {
        return (!isNaN(key)) ? parseInt(key) : key;
    };