问题描述
限时送ChatGPT账号..首先让我说这个问题与使用 ng-options 在 标签中选择的问题非常相似.例如,使用 AngularJS 的 ng-options 进行选择.具体问题是比较对象的两个不同实例,它们的引用不相等,但逻辑上表示相同的数据.
为了演示,假设我们在模型中有以下选项数组和选定的选项变量:
$scope.items = [{ID:1,标签:'Foo',额外:17},{ID: 2, 标签: 'Bar', Extra: 18},{ID:3,标签:'Baz',额外:19}];$scope.selectedItem = {ID: 1, 标签: 'Foo'};
请注意,以上对象仅用于演示.我特意省略了 selectedItem
上的Extra"属性,以表明有时我的模型对象的特定属性不同.重要的是我想比较 ID 属性.我的真实对象上有一个 equals()
函数,可以比较原型类"和 ID.
然后在视图中:
现在,这里的问题是Foo"的单选按钮不会开始被选中,因为 angular 对对象使用引用相等.如果我将范围内的最后一行更改为以下内容,一切都会按预期进行.
$scope.selectedItem = items[0];
但是,我遇到的问题是,在我的应用程序中,我不是简单地在作用域中声明这两个简单的变量.相反,选项列表和所选选项绑定的数据结构都是使用 $http 从服务器查询的较大 JSON 数据集的一部分.在一般情况下,我很难将数据绑定选定属性更改为数据查询中的等效选项.
所以,我的问题是:在 的 ng-options 中,angular 提供了一个
track by
表达式,允许我说类似object.ID"的内容并通知 angular 它应该比较通过 ID 属性将选定的模型值添加到选项中.是否有类似的东西可以用于一堆绑定到相同模型属性的无线电输入?理想情况下,我可以告诉 angular 使用我自己的自定义 equals() 方法,我已经放置在这些模型对象上,该方法检查对象类型和 ID.但是,如果失败,也可以指定 ID 比较.
我写了一个最简单的指令.使用一种跟踪"来映射两个不同的对象.请参阅 http://jsfiddle/xWWwT/146/.
HTML
<div ng-app ng-controller="ThingControl"><ul ><li ng-repeat="颜色中的颜色"><input type="radio" name="color" ng-model="$parent.thing" ng-value="color" radio-track-by="name"/>{{ color.name }}预览:{{东西}}
JS
var app = angular.module('app', []);app.controller('ThingControl', function($scope){$scope.colors = [{名称:白色",十六进制:#ffffff"},{名称:黑色",十六进制:#000000"},{名称:红色",十六进制:#000000"},{名称:绿色",十六进制:#000000"}];$scope.thing = { 名称:白色",十六进制:#ffffff"};});app.directive('radioTrackBy', function(){返回 {限制:A",范围: {ngModel:=",ngValue:=",radioTrackBy: "@"},链接:函数(ng){如果(ng.ngValue[ng.radioTrackBy] === ng.ngModel[ng.radioTrackBy]){ng.ngModel = ng.ngValue;}}};});
Let me start by saying that this question is very similar to issues with selection in a <select>
tag using ng-options. For example, Working with select using AngularJS's ng-options. The specific problem is comparing two different instances of an object which are not reference equal, but which logically represent the same data.
To demonstrate, let's say we have the following array of options and selected option variable in the model:
$scope.items = [
{ID: 1, Label: 'Foo', Extra: 17},
{ID: 2, Label: 'Bar', Extra: 18},
{ID: 3, Label: 'Baz', Extra: 19}
];
$scope.selectedItem = {ID: 1, Label: 'Foo'};
Note that the above objects are just for demonstration. I specifically left off the 'Extra' property on selectedItem
to show that sometimes my model objects differ in their specific properties. The important thing is that I want to compare on the ID property. I have an equals()
function on my real objects that compares both prototype 'class' and ID.
And then in the view:
<label class="radio inline" ng-repeat="item in items">
<input type="radio" ng-model="selectedItem" ng-value="item"> {{item.Label}}
</label>
Now, the problem here is that the radio button for 'Foo' will not start selected, because angular is using reference equality for the objects. If I changed the last line in my scope to the below, everything would work as expected.
$scope.selectedItem = items[0];
But, the problem I'm having is that in my application, I'm not simply declaring these two simple variables in scope. Rather, the options list and the data structure where the selected option are being bound are both part of larger sets of JSON data that are queried from the server using $http. In the general case, it's very difficult for me to go change the data-bound selected property to be the equivalent option from my data query.
So, my question:
In ng-options for the <select>
, angular offers a track by
expression that allows me to say something like "object.ID" and inform angular that it should compare the selected model value to the options via the ID property. Is there something similar that I can use for a bunch of radio inputs all bound to the same model property? Ideally, I would be able to tell angular to use my own custom equals() method that I've placed on these model objects, which checks both object type as well as ID. Failing that though, being able to specify ID comparison would also work.
I write a most simple directive. Using a kind of "track-by" to map two different objects. See the http://jsfiddle/xWWwT/146/.
HTML
<div ng-app="app">
<div ng-app ng-controller="ThingControl">
<ul >
<li ng-repeat="color in colors">
<input type="radio" name="color" ng-model="$parent.thing" ng-value="color" radio-track-by="name" />{{ color.name }}
</li>
</ul>
Preview: {{ thing }}
</div>
</div>
JS
var app = angular.module('app', []);
app.controller('ThingControl', function($scope){
$scope.colors = [
{ name: "White", hex: "#ffffff"},
{ name: "Black", hex: "#000000"},
{ name: "Red", hex: "#000000"},
{ name: "Green", hex: "#000000"}
];
$scope.thing = { name: "White", hex: "#ffffff"};
});
app.directive('radioTrackBy', function(){
return {
restrict: "A",
scope: {
ngModel: "=",
ngValue: "=",
radioTrackBy: "@"
},
link: function (ng) {
if (ng.ngValue[ng.radioTrackBy] === ng.ngModel[ng.radioTrackBy]) {
ng.ngModel = ng.ngValue;
}
}
};
});
这篇关于input[radio] 与 ng-model 和 ng-value 的对象相等性比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
更多推荐
[db:关键词]
发布评论