Робота з виділенням, використовуючи ng-параметри AngularJS


442

Я читав про це в інших публікаціях, але не зміг це зрозуміти.

У мене є масив,

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

Я прочитав вибір і спробував, але не можу це зрозуміти.


Я настійно рекомендую використовувати Select2 , оскільки це впорається з вами. Існує навіть директива для AngularJS .
hewstone


Насправді існує чисте рішення AngularJS, розроблене QuantumUI . Ви можете знайти більше прикладів та документацій на http://quantumui.org/ .
Ramon Drunce

Відповіді:


799

Варто зазначити одне, що ngModel необхідний для роботи ngOptions ... зауважте, ng-model="blah"що йдеться про "встановити $ range.blah на вибране значення".

Спробуйте це:

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

Ось більше з документації AngularJS (якщо ви її ще не бачили):

для джерел даних масиву:

  • мітка для значення масиву
  • вибрати як мітку для значення масиву
  • label group by group for value in array = вибрати як групу label для групи для значення у масиві

для об'єктів даних:

  • мітка для (ключ, значення) в об'єкті
  • вибрати як мітку для (ключ, значення) в об'єкті
  • група міток по групі для (ключ, значення) в об'єкті
  • вибрати як групу міток по групі для (ключ, значення) в об'єкті

Щоб отримати уточнення щодо значень тегів опцій у AngularJS:

При використанні ng-options, значення опцій тегів виписало нг-варіантами завжди буде індексом елемента масиву додатковий тег відноситься до . Це тому, що AngularJS насправді дозволяє вибирати цілі об’єкти з елементами управління, а не лише примітивними типами. Наприклад:

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 вам не потрібно турбуватися про те, що є у вашому тегу опцій. Нехай 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 сховати до параметра за замовчуванням:

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

3
Виявляється, що це показники значень, саме так кутовий може дозволити вам використовувати об'єкти як значення вибраного поля. Кутовий робить багато речей для вас за кадром із вибраними полями, і ви не повинні турбуватися про атрибут значення у своїх параметрах.
Бен Леш

1
Документація розміщена у розділі "Вибрати" на їхньому сайті: docs.angularjs.org/api/ng.directive:select
Бен Леш

25
"... ngModel потрібен, щоб ngOptions працювала ..." була основою проблеми для мене. Хороша відповідь.
тристан

1
Чи можливо уникнути першої порожньої опції ( <option value="?" selected="selected"></option>)?
понеділок

4
Я намагаюся використовувати останній випадок ( налаштований параметр за замовчуванням, який ховається після здійснення вибору ), але я виявив деякі проблеми. Замість цього ng-if="foo"мені довелося використовувати, ng-if=!fooщоб приховати порожній параметр за замовчуванням, коли вибрано інший варіант. Також порожня опція за замовчуванням завжди відображається внизу списку комбінацій. Як я можу це помістити на початку списку комбінованих?
Fran Herrero

90

Я навчаюсь 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"};
}

27
Шановний випадковий користувач. Хоча це питання та його відповідь досить прості та нескладні, ваша організація коду у належні та відповідні місця (контролер, сервіс, шаблон, дані) демонструє елегантність AngularJS у його найпростішій та за замовчуванням формі. Дивовижний приклад.
Аттікус

1
Це не так, як це мається на увазі використовувати. ng-modelмає вказувати на іншу змінну у вашому обсязі, не пов’язану з make. Дивіться приклад у docs.angularjs.org/api/ng/directive/ngOptions
Дмитро Зайцев

@DmitriZaitsev Я думаю, що ви помиляєтесь, тому що приклад кутових документів показує це так, як ви описали, не означає, що це єдиний спосіб. Покажіть нам, чому ви вважаєте, що його не слід застосовувати таким чином, а не сміття чудовим прикладом для новачків.
JRT

39

Чомусь 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-параметри, але вам потрібно використовувати ng-repeatтег опцій:

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

3
Ця відповідь, здається, саме те, про що задається питання. Кожна інша відповідь спонукає читача не турбуватися про те, що генерується HTML, але якщо елемент вибору у формі, я дуже переживаю. Чудова відповідь!
Кіт

3
Слід зазначити, що це зберігає повний обраний об’єкт у моделі, а не лише ключ. Якщо ви хочете просто ключ в моделі, ви хочете використовувати версію "item.key як item.value". Це на деякий час заплутало мене, коли я був повішений на те, як виглядає HTML, а не на дані, які я хотів у моделі, що є для мене важливим.
mhenry1384

@ mhenry1384 Так, ви праві, про це зберігається весь об’єкт. Мені справді подобається ця функція, оскільки вона дає вам доступ до більш ніж просто ідентифікатора (якщо він потрібен.). Добре працює для мене, коли я заповнюю списки з колекцією монго, і мені потрібна якась властивість з вибраного елемента.
Mattijs

2
І як ми можемо виявити зміни за допомогою "зміни ng" всередині option?
Константинос Націос

2
Щодо оновлення, то це виглядає не так. ng-параметри все ще добре працюють у 1.5. Це ще показано в документації. docs.angularjs.org/api/ng/directive/select
Джеремі А. Захід

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 - те саме значення, але перетворене у великі символи.
  • 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's much easier to create your own directive...</p>

1
Не забувайте radixпро parseInt: http://davidwalsh.name/parseint-radix
GFoley83

6

Якщо вам потрібна спеціальна назва для кожного варіанту, 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>

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 у тіньовому виконанні дайджестів $ не пов'язує вибране як слід. Я повинен використовувати jQuery для встановлення вибраного. Це важливо! AngularJS, в тіні, додає префікс до значення attr "значення", згенерованого параметрами ng-повтору. Для 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);
           }
       });
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.