AngularJS 1.5 显示普通数组的 ngOptions 比较
AngularJS 1.5 ngOptions Comparison for Displaying a Plain Array
谁能告诉我为什么选择了第一个示例中的模型选项,而第二个没有选择普通数组:
// Plain old array
vm.owner = ['example', 'example2', 'example3', ...];
所在型号vm.model.address.owner = 2;
// EXAMPLE 1 - Works
// Force index to be a number: using id*1 instead of it being a string:
// and the option ('example3') is selected based on the model value of 2
// indicating the index
<select id="owner"
name="owner"
placeholder="Residential Status"
ng-model="vm.model.address.owner"
ng-required="true"
ng-options="id*1 as owner for (id, owner) in vm.owner">
<option value="">Select Value</option>
</select>
尝试不使用 hack 并使用 track by 而不是索引 2 未被选中,即使该值仍在模型中设置。
// EXAMPLE 2 - Doesn't Work
// Markup doesn't show value to be a string: using track by, but the
// option set in the model doesn't cause the option to be selected it
// remains as the default with a value of ''
<select id="owner"
name="owner"
placeholder="Residential Status"
ng-model="vm.model.address.owner"
ng-required="true"
ng-options="owner for (id, owner) in vm.owner track by id">
<option value="">Select Value</option>
</select>
我发现 ngOptions 非常令人困惑,所以对于示例 2 的任何解释或解决方案都很好,因为它更干净而不是 hack。
没有找到使用 track by
的解决方案,但是 Select 的 AngularJS 文档有一个使用解析器和格式化程序的解决方案,因此我可以避免使用 hack这个问题。我稍微调整了一下,所以如果密钥是一个字符串,它会保留它,否则它会转换它,这似乎有效。任何我没有看到的批评或问题请评论,否则希望这对某人有所帮助。
(function () {
'use strict';
/**
* Binds a select field to a non-string value via ngModel parsing and formatting,
* which simply uses these pipelines to convert the string value.
* @constructor
* @ngInject
* ---
* NOTE: In general matches between a model and an option is evaluated by strict
* comparison of the model value against the value of the available options.
* Setting the option value with the option's "value" attribute the value
* will always be a "string", which means that the model value must also
* be a string, otherwise the select directive cannot match them
* reliably.
*/
function selectConvertKey(_) {
return {
require: 'ngModel',
link: function ($scope, $element, $attrs, $ctrl) {
var ngModelCtrl = $ctrl;
// Do nothing if no ng-model
if (!ngModelCtrl) {
return;
}
// ---
// PRIVATE METHODS.
// ---
/**
* Convert the key to a number if the key is a number.
* @param key
* @returns {Number}
* ---
* NOTE: Using Number() instead of parseInt() means that a string
* composed of letters and numbers, and start with a number will
* not be converted.
*/
function selectConvertKeyParser(key) {
var keyAsNumber = Number(key);
// Check if the key is not a number
if(_.isNaN(keyAsNumber)) {
return key;
}
return keyAsNumber;
}
/**
* Convert the key to a string.
* @param key
* @returns {string}
*/
function selectConvertKeyFormatter(key) {
return '' + key;
}
// ---
// MODEL PROPERTIES.
// ---
/**
* Formatters used to control how the model changes are formatted
* in the view, also known as model-to-view conversion.
* ---
* NOTE: Formatters are not invoked when the model is changed
* in the view. They are only triggered if the model changes
* in code. So you could type forever into the input, and
* the formatter would never be invoked.
*/
ngModelCtrl.$formatters.push(selectConvertKeyFormatter);
/**
* Parsers used to control how the view changes read from the
* DOM are sanitized/formatted prior to saving them to the
* model, and updating the view if required.
*/
ngModelCtrl.$parsers.push(selectConvertKeyParser);
}
};
}
selectConvertKey.$inject = [
'_'
];
angular
.module('app')
.directive('selectConvertKey', selectConvertKey);
})();
是的,问题似乎是 select 被绑定到一个非字符串值。如果您执行以下操作,它将起作用:
//controller
vm.model.address.owner = "2"
//html
ng-options="id as owner for (id, owner) in vm.owner"
参见 。
此外,如果您想将模型值保留为数字(2,而不是“2”),您可以试试这个:
ng-options="vm.owner.indexOf(owner) as owner for (id, owner) in vm.owner"
但是,这可能不会比您的第一个工作示例少 "hackish":
ng-options="id*1 as owner for (id, owner) in vm.owner">
在 查看第一个答案。
谁能告诉我为什么选择了第一个示例中的模型选项,而第二个没有选择普通数组:
// Plain old array
vm.owner = ['example', 'example2', 'example3', ...];
所在型号vm.model.address.owner = 2;
// EXAMPLE 1 - Works
// Force index to be a number: using id*1 instead of it being a string:
// and the option ('example3') is selected based on the model value of 2
// indicating the index
<select id="owner"
name="owner"
placeholder="Residential Status"
ng-model="vm.model.address.owner"
ng-required="true"
ng-options="id*1 as owner for (id, owner) in vm.owner">
<option value="">Select Value</option>
</select>
尝试不使用 hack 并使用 track by 而不是索引 2 未被选中,即使该值仍在模型中设置。
// EXAMPLE 2 - Doesn't Work
// Markup doesn't show value to be a string: using track by, but the
// option set in the model doesn't cause the option to be selected it
// remains as the default with a value of ''
<select id="owner"
name="owner"
placeholder="Residential Status"
ng-model="vm.model.address.owner"
ng-required="true"
ng-options="owner for (id, owner) in vm.owner track by id">
<option value="">Select Value</option>
</select>
我发现 ngOptions 非常令人困惑,所以对于示例 2 的任何解释或解决方案都很好,因为它更干净而不是 hack。
没有找到使用 track by
的解决方案,但是 Select 的 AngularJS 文档有一个使用解析器和格式化程序的解决方案,因此我可以避免使用 hack这个问题。我稍微调整了一下,所以如果密钥是一个字符串,它会保留它,否则它会转换它,这似乎有效。任何我没有看到的批评或问题请评论,否则希望这对某人有所帮助。
(function () {
'use strict';
/**
* Binds a select field to a non-string value via ngModel parsing and formatting,
* which simply uses these pipelines to convert the string value.
* @constructor
* @ngInject
* ---
* NOTE: In general matches between a model and an option is evaluated by strict
* comparison of the model value against the value of the available options.
* Setting the option value with the option's "value" attribute the value
* will always be a "string", which means that the model value must also
* be a string, otherwise the select directive cannot match them
* reliably.
*/
function selectConvertKey(_) {
return {
require: 'ngModel',
link: function ($scope, $element, $attrs, $ctrl) {
var ngModelCtrl = $ctrl;
// Do nothing if no ng-model
if (!ngModelCtrl) {
return;
}
// ---
// PRIVATE METHODS.
// ---
/**
* Convert the key to a number if the key is a number.
* @param key
* @returns {Number}
* ---
* NOTE: Using Number() instead of parseInt() means that a string
* composed of letters and numbers, and start with a number will
* not be converted.
*/
function selectConvertKeyParser(key) {
var keyAsNumber = Number(key);
// Check if the key is not a number
if(_.isNaN(keyAsNumber)) {
return key;
}
return keyAsNumber;
}
/**
* Convert the key to a string.
* @param key
* @returns {string}
*/
function selectConvertKeyFormatter(key) {
return '' + key;
}
// ---
// MODEL PROPERTIES.
// ---
/**
* Formatters used to control how the model changes are formatted
* in the view, also known as model-to-view conversion.
* ---
* NOTE: Formatters are not invoked when the model is changed
* in the view. They are only triggered if the model changes
* in code. So you could type forever into the input, and
* the formatter would never be invoked.
*/
ngModelCtrl.$formatters.push(selectConvertKeyFormatter);
/**
* Parsers used to control how the view changes read from the
* DOM are sanitized/formatted prior to saving them to the
* model, and updating the view if required.
*/
ngModelCtrl.$parsers.push(selectConvertKeyParser);
}
};
}
selectConvertKey.$inject = [
'_'
];
angular
.module('app')
.directive('selectConvertKey', selectConvertKey);
})();
是的,问题似乎是 select 被绑定到一个非字符串值。如果您执行以下操作,它将起作用:
//controller
vm.model.address.owner = "2"
//html
ng-options="id as owner for (id, owner) in vm.owner"
参见
此外,如果您想将模型值保留为数字(2,而不是“2”),您可以试试这个:
ng-options="vm.owner.indexOf(owner) as owner for (id, owner) in vm.owner"
但是,这可能不会比您的第一个工作示例少 "hackish":
ng-options="id*1 as owner for (id, owner) in vm.owner">
在