输入[radio]与ng-model和ng-value的对象相等性比较

Dan*_*ght 14 javascript angularjs

首先我要说的是,这个问题非常类似于<select>使用ng-options 在标签中进行选择的问题.例如,使用AngularJS的ng-options使用select.具体问题是比较对象的两个不同实例,这两个实例不是引用相等,但在逻辑上代表相同的数据.

为了演示,假设我们在模型中有以下数组选项和选定的选项变量:

$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'};
Run Code Online (Sandbox Code Playgroud)

请注意,上述对象仅用于演示.我特别省略了'Extra'属性,selectedItem以显示有时我的模型对象的特定属性不同.重要的是我想比较ID属性.我equals()在我的真实对象上有一个函数,可以比较原型'class'和ID.

然后在视图中:

<label class="radio inline" ng-repeat="item in items">
    <input type="radio" ng-model="selectedItem" ng-value="item"> {{item.Label}}
</label>
Run Code Online (Sandbox Code Playgroud)

现在,这里的问题是'Foo'的单选按钮不会被选中,因为angular正在使用对象的引用相等性.如果我将范围中的最后一行更改为以下内容,则一切都将按预期工作.

$scope.selectedItem = items[0];
Run Code Online (Sandbox Code Playgroud)

但是,我遇到的问题是,在我的应用程序中,我不是简单地在范围内声明这两个简单变量.相反,选项列表和绑定所选选项的数据结构都是使用$ http从服务器查询的较大JSON数据集的一部分.在一般情况下,我很难将数据绑定的选定属性更改为我的数据查询中的等效选项.

所以,我的问题:在ng的ng选项中<select>,angular提供了一个track by表达式,允许我说出类似"object.ID"的内容,并通知angular它应该通过ID属性将选定的模型值与选项进行比较.是否有类似的东西我可以用于一堆无线电输入都绑定到相同的模型属性?理想情况下,我可以告诉angular使用我自己定制的equals()方法,我将这些方法放在这些模型对象上,它们同时检查对象类型和ID.如果失败,那么能够指定ID比较也会有效.

Rod*_*ira 9

我写了一个最简单的指令.使用一种"跟踪"来映射两个不同的对象.请参阅http://jsfiddle.net/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>
Run Code Online (Sandbox Code Playgroud)

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;
            }
        }
    };
});
Run Code Online (Sandbox Code Playgroud)