Работа с select с использованием AngularJS ng-options

Я читал об этом в других сообщениях, но я не мог понять это.

У меня есть массив,

$scope.items = [
   {ID: '000001', Title: 'Chicago'},
   {ID: '000002', Title: 'New York'},
   {ID: '000003', Title: 'Washington'},
];

Я хочу сделать это как:

<select>
  <option value="000001">Chicago</option>
  <option value="000002">New York</option>
  <option value="000003">Washington</option>
</select>

А также я хочу выбрать опцию с ID=000002.

Я прочитал выбор и попытался, но я не могу понять это.

8 ответов

Решение

Стоит отметить, что ngModel требуется для работы ngOptions... обратите внимание на ng-model="blah" который говорит "установить $scope.blah для выбранного значения".

Попробуй это:

<select ng-model="blah" ng-options="item.ID as item.Title for item in items"></select>

Вот еще из документации AngularJS (если вы ее еще не видели):

для источников данных массива:

  • метка для значения в массиве
  • выбрать в качестве метки для значения в массиве
  • метка группа по группе для значения в массиве = выбрать как метка группа по группе для значения в массиве

для источников данных объекта:

  • метка для (ключ, значение) в объекте
  • выбрать в качестве метки для (ключ, значение) в объекте
  • пометить группу за группой для (ключ, значение) в объекте
  • выбрать в качестве метки группу по группе для (ключ, значение) в объекте

Для пояснения значений тегов опций в AngularJS:

Когда вы используете ng-options значения тегов option, записанных с помощью ng-options, всегда будут индексом элемента массива, к которому относится тег option. Это потому, что AngularJS фактически позволяет вам выбирать целые объекты с помощью элементов управления select, а не только примитивные типы. Например:

app.controller('MainCtrl', function($scope) {
   $scope.items = [
     { id: 1, name: 'foo' },
     { id: 2, name: 'bar' },
     { id: 3, name: 'blah' }
   ];
});
<div ng-controller="MainCtrl">
   <select ng-model="selectedItem" ng-options="item as item.name for item in items"></select>
   <pre>{{selectedItem | json}}</pre>
</div>

Вышеуказанное позволит вам выделить весь объект в $scope.selectedItem непосредственно. Дело в том, что с AngularJS вам не нужно беспокоиться о том, что находится в вашем теге option. Пусть AngularJS справится с этим; Вы должны заботиться только о том, что находится в вашей модели в вашем объеме.

Вот плункер, демонстрирующий поведение выше и показывающий выписанный HTML


Работа с опцией по умолчанию:

Есть несколько вещей, которые я не упомянул выше, касающихся опции по умолчанию.

Выбор первого варианта и удаление пустого параметра:

Вы можете сделать это, добавив простой ng-init которая устанавливает модель (из ng-model) к первому элементу в пунктах, которые вы повторяете в ng-options:

<select ng-init="foo = foo || items[0]" ng-model="foo" ng-options="item as item.name for item in items"></select>

Примечание: это может немного сойти с ума, если foo случайно инициализируется к чему-то "ложному". В этом случае вы захотите обработать инициализацию foo в вашем контроллере, скорее всего.

Настройка опции по умолчанию:

Это немного по-другому; здесь все, что вам нужно сделать, это добавить тег option как дочерний элемент вашего выбора с пустым атрибутом value, а затем настроить его внутренний текст:

<select ng-model="foo" ng-options="item as item.name for item in items">
   <option value="">Nothing selected</option>
</select>

Примечание. В этом случае "пустая" опция останется там даже после выбора другой опции. Это не относится к поведению по умолчанию выбора в AngularJS.

Настраиваемая опция по умолчанию, которая скрывается после выбора:

Если вы хотите, чтобы настроенная опция по умолчанию исчезла после выбора значения, вы можете добавить атрибут ng-hide к опции по умолчанию:

<select ng-model="foo" ng-options="item as item.name for item in items">
   <option value="" ng-if="foo">Select something to remove me.</option>
</select>

Я изучаю AngularJS и тоже боролся с отбором. Я знаю, что на этот вопрос уже дан ответ, но я все же хотел поделиться еще одним кодом.

В моем тесте у меня есть два списка: марки автомобилей и модели автомобилей. Список моделей отключен, пока не будет выбрана какая-либо марка. Если выбор в списке марок позднее сбрасывается (устанавливается "Выбрать марку"), тогда список моделей снова отключается и его выбор также сбрасывается (на "Выбор модели"). Марки извлекаются как ресурс, а модели просто жестко запрограммированы.

Делает JSON:

[
{"code": "0", "name": "Select Make"},
{"code": "1", "name": "Acura"},
{"code": "2", "name": "Audi"}
]

services.js:

angular.module('makeServices', ['ngResource']).
factory('Make', function($resource){
    return $resource('makes.json', {}, {
        query: {method:'GET', isArray:true}
    });
});

HTML-файл:

<div ng:controller="MakeModelCtrl">
  <div>Make</div>
  <select id="makeListBox"
      ng-model="make.selected"
      ng-options="make.code as make.name for make in makes"
      ng-change="makeChanged(make.selected)">
  </select>

  <div>Model</div>
  <select id="modelListBox"
     ng-disabled="makeNotSelected"
     ng-model="model.selected"
     ng-options="model.code as model.name for model in models">
  </select>
</div>

controllers.js:

function MakeModelCtrl($scope)
{
    $scope.makeNotSelected = true;
    $scope.make = {selected: "0"};
    $scope.makes = Make.query({}, function (makes) {
         $scope.make = {selected: makes[0].code};
    });

    $scope.makeChanged = function(selectedMakeCode) {
        $scope.makeNotSelected = !selectedMakeCode;
        if ($scope.makeNotSelected)
        {
            $scope.model = {selected: "0"};
        }
    };

    $scope.models = [
      {code:"0", name:"Select Model"},
      {code:"1", name:"Model1"},
      {code:"2", name:"Model2"}
    ];
    $scope.model = {selected: "0"};
}

Почему-то AngularJS позволяет мне запутаться. Их документация довольно ужасна по этому поводу. Более хорошие примеры вариаций будут приветствоваться.

Во всяком случае, у меня есть небольшое отклонение от ответа Бена Леша.

Мои коллекции данных выглядят так:

items =
[
   { key:"AD",value:"Andorra" }
,  { key:"AI",value:"Anguilla" }
,  { key:"AO",value:"Angola" }
 ...etc..
]

Сейчас

<select ng-model="countries" ng-options="item.key as item.value for item in items"></select>

по-прежнему приводит к тому, что значение опций будет индексом (0, 1, 2 и т. д.).

Добавление трека по исправлено для меня:

<select ng-model="blah" ng-options="item.value for item in items track by item.key"></select>

Я считаю, что чаще всего вы хотите добавить массив объектов в список выбора, поэтому я запомню этот!

Имейте в виду, что из AngularJS 1.4 вы больше не можете использовать ng-options, но вам нужно использовать ng-repeat на ваш вариант тега:

<select name="test">
   <option ng-repeat="item in items" value="{{item.key}}">{{item.value}}</option>
</select>

На этот вопрос уже дан ответ (кстати, действительно хороший и исчерпывающий ответ, предоставленный Беном), но я хотел бы добавить еще один элемент для полноты, который также может быть очень удобным.

В примере, предложенном Беном:

<select ng-model="blah" ng-options="item.ID as item.Title for item in items"></select>

была использована следующая форма ngOptions: select as label for value in array,

Метка - это выражение, результатом которого будет метка для <option> элемент. В этом случае вы можете выполнить определенные конкатенации строк, чтобы иметь более сложные метки опций.

Примеры:

  • ng-options="item.ID as item.Title + ' - ' + item.ID for item in items" дает вам ярлыки, как Title - ID
  • ng-options="item.ID as item.Title + ' (' + item.Title.length + ')' for item in items" дает вам ярлыки, как Title (X), где X длина строки заголовка.

Вы также можете использовать фильтры, например,

  • ng-options="item.ID as item.Title + ' (' + (item.Title | uppercase) + ')' for item in items" дает вам ярлыки, как Title (TITLE)где значение Title свойства Title и TITLE - это одно и то же значение, но оно преобразуется в прописные буквы.
  • ng-options="item.ID as item.Title + ' (' + (item.SomeDate | date) + ')' for item in items" дает вам ярлыки, как Title (27 Sep 2015), если ваша модель имеет свойство SomeDate

В CoffeeScript:

#directive
app.directive('select2', ->
    templateUrl: 'partials/select.html'
    restrict: 'E'
    transclude: 1
    replace: 1
    scope:
        options: '='
        model: '='
    link: (scope, el, atr)->
        el.bind 'change', ->
            console.log this.value
            scope.model = parseInt(this.value)
            console.log scope
            scope.$apply()
)
<!-- HTML partial -->
<select>
  <option ng-repeat='o in options'
          value='{{$index}}' ng-bind='o'></option>
</select>

<!-- HTML usage -->
<select2 options='mnuOffline' model='offlinePage.toggle' ></select2>

<!-- Conclusion -->
<p>Sometimes it's much easier to create your own directive...</p>

Если вам нужен собственный заголовок для каждого параметра, ng-options не применимо Вместо этого используйте ng-repeat с вариантами:

<select ng-model="myVariable">
  <option ng-repeat="item in items"
          value="{{item.ID}}"
          title="Custom title: {{item.Title}} [{{item.ID}}]">
       {{item.Title}}
  </option>
</select>

Я надеюсь, что следующее будет работать для вас.

<select class="form-control"
        ng-model="selectedOption"
        ng-options="option.name + ' (' + (option.price | currency:'USD$') + ')' for option in options">
</select>

Это может быть полезно. Привязки не всегда работают.

<select id="product" class="form-control" name="product" required
        ng-model="issue.productId"
        ng-change="getProductVersions()"
        ng-options="p.id as p.shortName for p in products"></select>

Например, вы заполняете исходную модель списка опций из службы REST. Выбранное значение было известно до заполнения списка, и оно было установлено. После выполнения запроса REST с помощью $http, опция list будет выполнена.

Но выбранная опция не установлена. По неизвестным причинам AngularJS в теневом $digest при выполнении не привязывает выбранный, как должно быть. Я должен использовать JQuery, чтобы установить выбранное. Это важно! AngularJS в тени добавляет префикс к значению атрибута "значение" для сгенерированных опциями ng-repeat. Для int это "номер:".

$scope.issue.productId = productId;
function activate() {
    $http.get('/product/list')
       .then(function (response) {
           $scope.products = response.data;

           if (productId) {
               console.log("" + $("#product option").length);//for clarity
               $timeout(function () {
                   console.log("" + $("#product option").length);//for clarity
                   $('#product').val('number:'+productId);

               }, 200);
           }
       });
}
Другие вопросы по тегам