Используете $ index с директивой AngularJS 'ng-options'?

Скажем, я привязываю массив к тегу 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?


person Jim Cote    schedule 17.12.2012    source источник


Ответы (5)


$ index определен для ng-repeat, а не select. Я думаю, это объясняет undefined. (Так что нет, это не должно работать.)

Angular поддерживает привязку ко всему объекту. Документацию можно было бы сформулировать лучше, чтобы указать на это, но она намекает на это: «ngOptions ... следует использовать вместо ngRepeat, когда вы хотите, чтобы модель выбора была привязана к нестроковому значению».

person Mark Rajcok    schedule 17.12.2012
comment
См. Ответ Гарри ниже, который предлагает простой способ решения проблемы. - person gm2008; 01.12.2017

Поскольку массивы очень похожи на объекты в 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 и т. Д. Но в модели вы увидите только значение индекса.

Я адаптировал эту информацию из статьи «Освоение разработки веб-приложений с помощью AngularJS» от PACKT Publishing и проверил ее на странице Справочная документация по Angular для select.

person Harry Pehkonen    schedule 27.02.2014
comment
Умный трюк. Именно то, что мне нужно, за исключением того, что модель задана как строка вместо числа. - person manikanta; 15.04.2014
comment
Большое вам спасибо .. удивительно, как такие мелочи ускользают из вашей головы, когда наступает подходящий момент для их реализации - person Bhumi Singhal; 23.05.2014
comment
Милая, очень умная. Таким образом, вы можете использовать индексы с параметрами ng. - person Craig; 25.11.2014
comment
Не могли бы вы пояснить, как вы употребляете слово «скобки»? Вы имеете в виду пару переменных в скобках для ng-options? - person broc.seib; 14.01.2015
comment
Да, @ broc.seib - часть (idx, выбор). - person Harry Pehkonen; 14.01.2015
comment
Такой подход нарушает порядок выбранных элементов. - person New Dev; 04.03.2015
comment
Не понимаю, что вы имеете в виду, @NewDev. Можете ли вы показать пример того, как это портит порядок выбранных элементов? - person Harry Pehkonen; 04.03.2015
comment
Я должен был пояснить, что это применимо, когда у вас есть более 10 вариантов. Тогда порядок элементов станет: 0, 1, 10, 11, ... 2, - person New Dev; 04.03.2015
comment
Похоже, что этот подход не работает при установке предварительно выбранного параметра. Хотя ngModel явно получает номер при выборе вручную в пользовательском интерфейсе, вы не можете предварительно выбрать присвоение индекса ngModel. Похоже на ошибку в AngularJS или ненадлежащее использование. В конце концов, это уловка для не-массива - person Kirill Slatin; 10.03.2015
comment
Если вам нужно, чтобы idx было числом, просто умножьте его на 1, и это проанализирует его как int. idx*1 as choice for (idx, choice) in choices - person Michael Wilson; 10.06.2015
comment
@KirillSlatin, у меня он работает после адаптации хака от @MichaelWilson. По умолчанию angular делает idx строкой, а не числом. - person gfaceless; 23.06.2015
comment
Согласно документации данное решение недействительно для массивов источников данных. По крайней мере, не для последних версий Angular. - person Sjoerd222888; 20.05.2016
comment
@ Джим Кот, вы должны изменить этот ответ как ответ на ваш вопрос. Это полностью работает! - person Agat; 02.05.2017

Поскольку вы не можете использовать $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

Комментарий:

Array.prototype.indexOf не поддерживается в IE7 (8)

person Maxim Shoustin    schedule 09.10.2013
comment
Возможно, единственное, что следует отметить, это то, что Array.prototype.indexOf не поддерживается в IE8 (и IE7). - person PrimosK; 28.02.2014
comment
Другое дело - производительность .. для каждого элемента вам нужно пройти через массив и найти его индекс при распечатке .. - person Jan Jůna; 05.03.2015
comment
Это особенно полезно для неправильно определенных массивов, где индекс может содержать ключи, отличные от чисел. Кроме того, Array.prototype.indexOf можно полифиллировать, так что это не большая проблема. - person Lajos Mészáros; 08.01.2016
comment
Это не сработает, если значения массива не уникальны - person zlog; 22.04.2016

Вы также можете использовать ng-value = '$ index' в теге <option>.

<select ng-model="selData">
 <option ng-repeat="d in data track by $index" ng-value="$index">
   {{d.name}}
 </option>
</select>
person Brian McAuliffe    schedule 19.07.2016
comment
ng-value НЕ будет содержать числа, только строки - person Romko; 13.12.2017

Не используйте $index внутри тегов выбора. Используйте $index внутри тегов параметров, если вы хотите использовать индексы массива как значения или параметры.

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

Если вы хотите использовать внутренние значения, просто поместите его в атрибут значения как выражение привязки, например

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

и мой код контроллера будет таким:

var users = ['username':'bairavan', 'username':'testuser'];
person PyRu    schedule 30.05.2018