【问题标题】:Using $index with the AngularJS 'ng-options' directive?将 $index 与 AngularJS 'ng-options' 指令一起使用?
【发布时间】:2024-01-23 14:00:02
【问题描述】:

假设我使用以下代码将数组绑定到 select 标记:

<select ng-model="selData" ng-options="$index as d.name for d in data">

在这种情况下,关联的option 标签被分配了一系列索引值:(0, 1, 2, ...)。但是,当我从下拉列表中选择某些内容时,selData 的值将绑定到undefined。绑定是否真的有效?

另一方面,假设我改为执行以下操作:

<select ng-model="selData" ng-options="d as d.name for d in data">

在这里,option 标记获得相同的索引,但整个对象必然会发生变化。它是按设计方式工作的,还是这种行为只是 AngularJS 的一个很好的错误或副作用?

【问题讨论】:

    标签: angularjs html-select


    【解决方案1】:

    由于数组与 JavaScript 中的对象非常相似,因此您可以使用“对象数据源”的语法。诀窍在于ng-options 部分的括号

    var choices = [
      'One',
      'Two',
      'Three'
    ];
    

    在模板中:

    <select
      ng-model="model.choice"
      ng-options="idx as choice for (idx, choice) in choices">
    </select>
    

    最后,model.choice 的值将是 0、1 或 2。当它为 0 时,您将看到 One; 1 将显示Two 等。但在模型中,您只会看到索引值。

    我从 PACKT Publishing 的“Mastering Web Application Development with AngularJS”中改编了这些信息,并在Angular reference documentation for select 进行了验证。

    【讨论】:

    • 聪明的把戏。正是我需要的,除了模型设置为字符串而不是数字。
    • 是的,@broc.seib -- "(idx, choice)" 部分。
    • 这种方法搞乱了选择元素的顺序
    • 这种方法在设置预选选项时似乎不起作用。尽管在 UI 中手动选择 ngModel 时会清楚地得到一个数字,但您不能预先选择为 ngModel 分配索引。似乎是 AngularJS 中的错误或不打算使用。毕竟这是一个非数组的技巧
    • 如果您需要 idx 是一个数字,只需将其乘以 1 并将其解析为 int。 idx*1 as choice for (idx, choice) in choices
    【解决方案2】:

    因为你不能使用$index,但你可以试试indexOf

    HTML

    <div ng-app ng-controller="MyCtrl">
        <select 
              ng-model="selectedItem"
              ng-options="values.indexOf(selectedItem) as selectedItem for selectedItem in values"></select>
        selectedItem: {{selectedItem}}
    </div>
    

    控制器

    function MyCtrl($scope) {
        $scope.values = ["Value1","Value2"];
        $scope.selectedItem = 0;
    }
    

    演示Fiddle

    评论:

    IE7 (8) 不支持Array.prototype.indexOf

    【讨论】:

    • 也许唯一需要指出的是,IE8(和IE7)不支持Array.prototype.indexOf
    • 另一件事是性能..对于每个项目,您必须通过数组并在打印时找到它的索引..
    • 这对于定义不正确的数组特别有用,其中索引可能包含数字以外的键。此外, Array.prototype.indexOf 可以填充,所以这不是一个大问题。
    • 如果数组值不是唯一的,这将不起作用
    【解决方案3】:

    $index 是为 ng-repeat 定义的,而不是 select。我认为这解释了undefined。 (所以,不,这应该行不通。)

    Angular 支持对整个对象进行绑定。文档的措辞可以更好地表明这一点,但它确实暗示了这一点:“当您希望将选择模型绑定到非字符串值时,应该使用 ngOptions ... 而不是 ngRepeat。”

    【讨论】:

    • 请参阅下面 Harry 的回答,它提供了一个简单的解决方法。
    【解决方案4】:

    你也可以在&lt;option&gt;标签中使用ng-value='$index'。

    <select ng-model="selData">
     <option ng-repeat="d in data track by $index" ng-value="$index">
       {{d.name}}
     </option>
    </select>
    

    【讨论】:

    • ng-value 不会保存数字,只会保存字符串
    【解决方案5】:

    不要在选择标签中使用$index。如果要将数组索引用作值或选项,请在选项标签内使用 $index

    <option ng-repeat="user in users" value="{{user.username}}">{{$index+1}}</option>
    

    如果你想使用内部值,只需将它作为绑定表达式放在 value 属性中

    <option ng-repeat="user in users" value="{{$index+1}}">{{user.username}}</option>
    

    我的控制器代码如下:

    var users = ['username':'bairavan', 'username':'testuser'];
    

    【讨论】: