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

410

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

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

$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.

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

  • 0
    Я настоятельно рекомендую использовать Select2 , потому что он справится с этим для вас. Есть даже директива для AngularJS .
  • 0
    github.com/angular/angular.js/issues/6564
Показать ещё 1 комментарий
Теги:
ng-options
html-select

10 ответов

721
Лучший ответ

Следует отметить, что 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, значения тегов опций, выписанных параметрами ng, всегда будут индексом элемента массива, связанным с. Это связано с тем, что 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 в своем контроллере.

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

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

<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>
  • 0
    Извините, я создал скрипку для этого и не могу заставить ее работать. jsfiddle.net/andrejkaurin/xFaS6
  • 0
    Это, вероятно, потому что скрипка не работает с Angular. Я использую Plnkr.co для угловых ... Вот рабочий Plunk .
Показать ещё 13 комментариев
90

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

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

Делает 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"};
}
  • 26
    Уважаемый случайный пользователь. Хотя этот вопрос и его ответ довольно просты и несложны, ваша организация кода в его правильных и соответствующих местах (контроллер, служба, шаблон, данные) демонстрирует элегантность AngularJS в его простейшей форме и форме по умолчанию. Потрясающий пример.
  • 1
    Это не так, как это должно быть использовано. ng-model должна указывать на другую переменную в вашей области видимости, не связанную с make . См. Пример в docs.angularjs.org/api/ng/directive/ngOptions
Показать ещё 1 комментарий
35

По какой-то причине 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>
  • 2
    Этот ответ кажется именно тем, о чем спрашивает вопрос. Каждый второй ответ говорит читателю не беспокоиться о том, что генерируется HTML, но если элемент select находится в форме, я очень волнуюсь. Отличный ответ!
  • 3
    Следует отметить, что в модели сохраняется весь выбранный объект, а не только ключ. Если вам нужен только ключ в модели, вы хотите использовать версию "item.key as item.value". Это немного смутило меня, так как я был зациклен на том, как выглядит HTML, а не на данных, которые я хотел получить в модели, что для меня важно.
Показать ещё 4 комментария
15

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

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

<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
7

В 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 much easier to create your own directive...</p>
6

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

5

Если вам нужен пользовательский заголовок для каждой опции, 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>
3

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

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

На самом деле существует чистое решение AngularJS, разработанное QuantumUI.

Вы можете найти больше примеров и документов на http://quantumui.org/.

1

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

<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, опция списка выполнена.

Но выбранная опция не установлена. По неизвестным причинам AngularJS в выполнении теневого $digest не привязывает выбранных так, как должно быть. Я должен использовать jQuery для установки выбранного. Это важно! AngularJS в тени добавляет префикс к значению attr "value" для сгенерированных опциями 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);
           }
       });
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню