Angularjs ng-options using number for model 不 select 初始值
Angularjs ng-options using number for model does not select initial value
我正在尝试使用带有 <select>
的 ng-options 将数字整数值绑定到相应选项的列表。在我的控制器中,我有这样的东西:
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 展示了这个问题,以及我采用但不满意的其他一些方法。
select 选项被初始化为一个空值,而不是本例中预期的 "mV"。如果您 select 一个不同的选项 -- selectedUnitOrdinal 更新正确,绑定似乎工作正常。
我注意到,如果将初始模型值设置为字符串而不是数字,那么初始 selection 会起作用(请参阅 fiddle 中的#3)。
我真的希望 ng-options 能够很好地处理数字选项值。我怎样才能优雅地实现这一目标?
这是因为当您获得 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);
};
Angular 将您的 id
属性 视为字符串,添加引号:
self.selectedUnitOrdinal = "4";
你也可以定义过滤器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);
};
}]);
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>
注意:我发现文档中的指令不处理空值,所以我不得不稍微调整一下。
虽然 Mathew Berg 提供的解决方案有效,但它可能会破坏其他使用 sting-valued select 选项的 selects。如果您尝试编写一个通用指令来处理 selects(就像我所做的那样),这可能是一个问题。
一个很好的解决方法是检查该值是否为数字(即使它是包含数字的字符串)并且只进行转换,如下所示:
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;
};
补充一下 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?" 测试中 returns 错误。
可能有点乱,但是不用特殊函数就可以在ng-options
中得到结果
<select ng-model="ctrl.selectedUnitOrdinal" ng-options="+(unit.id) as unit.text for unit in ctrl.unitsOptions"></select>
与 tymeJV 的回答非常相似,简单的解决方法是将默认选择编号转换为如下字符串:
self.selectedUnitOrdinal = valueThatCameFromServer.toString();
这样,您就不必对数字进行硬编码,只需转换任何接收到的值即可。这是一个简单的修复,无需任何过滤器或指令。
<select ng-model="ctrl.selectedUnitOrdinal" ng-options="+(unit.id) as unit.text for unit in ctrl.unitsOptions"></select>
我认为其他解决方案对于简单地将值建立为整数来说过于复杂。我会使用:
<select ng-model="model.id">
<option ng-value="{{ 0 }}">Zero</option>
<option ng-value="{{ 1 }}">One</option>
<option ng-value="{{ 2 }}">Two</option>
</select>
将 unitsOptions 中的 id 属性 设置为数字
self.unitsOptions = Object.keys(unitOptionsFromServer).map(function (key) {
return { id: +key, text: unitOptionsFromServer[key] };
});
您可以使用 ng-value 属性。像这样:
<select ng-model="model.id">
<option ng-value="0">Zero</option>
<option ng-value="1">One</option>
<option ng-value="2">Two</option>
</select>
我正在尝试使用带有 <select>
的 ng-options 将数字整数值绑定到相应选项的列表。在我的控制器中,我有这样的东西:
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 展示了这个问题,以及我采用但不满意的其他一些方法。
select 选项被初始化为一个空值,而不是本例中预期的 "mV"。如果您 select 一个不同的选项 -- selectedUnitOrdinal 更新正确,绑定似乎工作正常。
我注意到,如果将初始模型值设置为字符串而不是数字,那么初始 selection 会起作用(请参阅 fiddle 中的#3)。
我真的希望 ng-options 能够很好地处理数字选项值。我怎样才能优雅地实现这一目标?
这是因为当您获得 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);
};
Angular 将您的 id
属性 视为字符串,添加引号:
self.selectedUnitOrdinal = "4";
你也可以定义过滤器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);
};
}]);
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>
注意:我发现文档中的指令不处理空值,所以我不得不稍微调整一下。
虽然 Mathew Berg 提供的解决方案有效,但它可能会破坏其他使用 sting-valued select 选项的 selects。如果您尝试编写一个通用指令来处理 selects(就像我所做的那样),这可能是一个问题。
一个很好的解决方法是检查该值是否为数字(即使它是包含数字的字符串)并且只进行转换,如下所示:
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;
};
补充一下 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?" 测试中 returns 错误。
可能有点乱,但是不用特殊函数就可以在ng-options
中得到结果<select ng-model="ctrl.selectedUnitOrdinal" ng-options="+(unit.id) as unit.text for unit in ctrl.unitsOptions"></select>
与 tymeJV 的回答非常相似,简单的解决方法是将默认选择编号转换为如下字符串:
self.selectedUnitOrdinal = valueThatCameFromServer.toString();
这样,您就不必对数字进行硬编码,只需转换任何接收到的值即可。这是一个简单的修复,无需任何过滤器或指令。
<select ng-model="ctrl.selectedUnitOrdinal" ng-options="+(unit.id) as unit.text for unit in ctrl.unitsOptions"></select>
我认为其他解决方案对于简单地将值建立为整数来说过于复杂。我会使用:
<select ng-model="model.id">
<option ng-value="{{ 0 }}">Zero</option>
<option ng-value="{{ 1 }}">One</option>
<option ng-value="{{ 2 }}">Two</option>
</select>
将 unitsOptions 中的 id 属性 设置为数字
self.unitsOptions = Object.keys(unitOptionsFromServer).map(function (key) {
return { id: +key, text: unitOptionsFromServer[key] };
});
您可以使用 ng-value 属性。像这样:
<select ng-model="model.id">
<option ng-value="0">Zero</option>
<option ng-value="1">One</option>
<option ng-value="2">Two</option>
</select>