Làm việc với select bằng cách sử dụng các tùy chọn ng của AngularJS


442

Tôi đã đọc về nó trong các bài viết khác, nhưng tôi không thể tìm ra nó.

Tôi có một mảng,

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

Tôi muốn kết xuất nó dưới dạng:

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

Và tôi cũng muốn chọn tùy chọn có ID = 000002.

Tôi đã đọc chọn và thử, nhưng tôi không thể tìm ra.


Tôi thực sự khuyên bạn nên sử dụng Select2 , vì nó sẽ xử lý việc này cho bạn. Thậm chí còn có một chỉ thị cho AngularJS .
hewstone


Trên thực tế có một giải pháp AngularJS thuần túy được phát triển bởi QuantumUI . Bạn có thể tìm thấy nhiều ví dụ và tài liệu tại http://quantumui.org/ .
Ramon Drunce 9/03/2015

Câu trả lời:


799

Một điều cần lưu ý là ngModel là bắt buộc để ngOptions hoạt động ... lưu ý ng-model="blah"câu nói "đặt $ scope.blah thành giá trị được chọn".

Thử cái này:

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

Đây là nhiều hơn từ tài liệu của AngularJS (nếu bạn chưa thấy nó):

cho các nguồn dữ liệu mảng:

  • nhãn cho giá trị trong mảng
  • chọn làm nhãn cho giá trị trong mảng
  • nhóm nhãn theo nhóm cho giá trị trong mảng = chọn làm nhóm nhãn theo nhóm cho giá trị trong mảng

cho các nguồn dữ liệu đối tượng:

  • nhãn cho (khóa, giá trị) trong đối tượng
  • chọn làm nhãn cho (khóa, giá trị) trong đối tượng
  • nhóm nhãn theo nhóm cho (khóa, giá trị) trong đối tượng
  • chọn làm nhóm nhãn theo nhóm cho (khóa, giá trị) trong đối tượng

Đối với một số làm rõ về các giá trị thẻ tùy chọn trong AngularJS:

Khi bạn sử dụng ng-options, các giá trị của thẻ tùy chọn được viết bởi ng-tùy chọn sẽ luôn là chỉ mục của mục mảng mà thẻ tùy chọn liên quan đến . Điều này là do AngularJS thực sự cho phép bạn chọn toàn bộ các đối tượng với các điều khiển chọn và không chỉ các kiểu nguyên thủy. Ví dụ:

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>

Ở trên sẽ cho phép bạn chọn toàn bộ một đối tượng $scope.selectedItemtrực tiếp. Vấn đề là, với AngularJS, bạn không cần phải lo lắng về những gì trong thẻ tùy chọn của mình. Hãy để AngularJS xử lý việc đó; bạn chỉ nên quan tâm đến những gì trong mô hình của bạn trong phạm vi của bạn.

Dưới đây là một plunker thể hiện hành vi trên và hiển thị HTML được viết ra


Xử lý tùy chọn mặc định:

Có một vài điều tôi đã không đề cập ở trên liên quan đến tùy chọn mặc định.

Chọn tùy chọn đầu tiên và loại bỏ tùy chọn trống:

Bạn có thể làm điều này bằng cách thêm một đơn giản ng-initđặt mô hình (từ ng-model) thành phần tử đầu tiên trong các mục mà bạn lặp lại trong ng-options:

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

Lưu ý: Điều này có thể trở nên hơi điên rồ nếu footình cờ được khởi tạo đúng cách thành một cái gì đó "giả". Trong trường hợp đó, rất có thể bạn sẽ muốn xử lý việc khởi tạo footrong bộ điều khiển của mình.

Tùy chỉnh tùy chọn mặc định:

Đây là một chút khác nhau; ở đây tất cả những gì bạn cần làm là thêm một thẻ tùy chọn làm con bạn chọn, với thuộc tính giá trị trống, sau đó tùy chỉnh văn bản bên trong của nó:

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

Lưu ý: Trong trường hợp này, tùy chọn "trống" sẽ ở đó ngay cả sau khi bạn chọn một tùy chọn khác. Đây không phải là trường hợp cho hành vi mặc định của các lựa chọn trong AngularJS.

Tùy chọn mặc định tùy chỉnh ẩn sau khi lựa chọn được thực hiện:

Nếu bạn muốn tùy chọn mặc định tùy chỉnh của mình biến mất sau khi bạn chọn một giá trị, bạn có thể thêm thuộc tính ng-hide vào tùy chọn mặc định của mình:

<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
Hóa ra đó là các chỉ số của các giá trị, đây là cách góc có thể cho phép bạn sử dụng các đối tượng làm giá trị của hộp chọn của bạn. Angular đang làm rất nhiều thứ cho bạn đằng sau hậu trường với các hộp chọn và bạn không cần phải lo lắng về thuộc tính giá trị trong các tùy chọn của mình.
Ben Lesh

1
Tài liệu dưới "chọn" trên trang web của họ: docs.angularjs.org/api/ng.directive:select
Ben Lesh

25
"... ngModel là bắt buộc để ngOptions hoạt động ..." là mấu chốt của vấn đề đối với tôi. Câu trả lời tốt.
tristanm

1
Có thể tránh tùy chọn trống đầu tiên ( <option value="?" selected="selected"></option>) không?
swenedo

4
Tôi đang cố gắng sử dụng trường hợp cuối cùng ( Một tùy chọn mặc định tùy chỉnh ẩn sau khi lựa chọn được thực hiện ) nhưng tôi đã tìm thấy một số vấn đề. Thay vì ng-if="foo"tôi phải sử dụng ng-if=!foođể ẩn tùy chọn trống mặc định khi tùy chọn khác được chọn. Ngoài ra, tùy chọn trống mặc định xuất hiện luôn ở cuối danh sách kết hợp. Làm thế nào tôi có thể đặt nó ở đầu danh sách kết hợp?
Fran Herrero

90

Tôi đang học AngularJS và cũng đang vật lộn với lựa chọn. Tôi biết câu hỏi này đã được trả lời, tuy nhiên tôi muốn chia sẻ thêm một số mã.

Trong thử nghiệm của tôi, tôi có hai hộp danh sách: xe hơi và mô hình xe hơi. Danh sách mô hình bị vô hiệu hóa cho đến khi một số thực hiện được chọn. Nếu lựa chọn trong hộp danh sách được đặt lại sau (được đặt thành 'Chọn Tạo') thì hộp danh sách mô hình sẽ bị vô hiệu hóa trở lại VÀ lựa chọn của nó cũng được đặt lại (thành 'Chọn Kiểu'). Làm cho được lấy như một tài nguyên trong khi các mô hình chỉ được mã hóa cứng.

Làm cho 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}
    });
});

Tệp 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>

controls.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
Kính gửi người dùng ngẫu nhiên. Mặc dù câu hỏi này và câu trả lời của nó khá đơn giản và không phức tạp, nhưng tổ chức mã của bạn vào các vị trí thích hợp và tương ứng của nó (bộ điều khiển, dịch vụ, mẫu, dữ liệu) cho thấy sự thanh lịch của AngularJS ở dạng đơn giản và mặc định nhất. Ví dụ tuyệt vời.
Atticus

1
Đây không phải là cách nó được sử dụng. ng-modelnên trỏ đến một biến khác trên phạm vi của bạn, không liên quan đến make. Xem ví dụ trong docs.angularjs.org/api/ng/directive/ngOptions
Dmitri Zaitsev

@DmitriZaitsev Tôi nghĩ bạn đã sai, chỉ vì ví dụ về tài liệu góc cạnh cho thấy nó theo cách bạn mô tả không có nghĩa đó là cách duy nhất. Hãy cho chúng tôi thấy lý do tại sao bạn nghĩ rằng nó không nên được sử dụng theo cách này hơn là tạo ra một ví dụ tuyệt vời cho người mới.
JRT

39

Vì một số lý do, AngularJS cho phép tôi bối rối. Tài liệu của họ là khá khủng khiếp về điều này. Nhiều ví dụ tốt về các biến thể sẽ được chào đón.

Dù sao, tôi có một chút thay đổi trong câu trả lời của Ben Lesh.

Bộ sưu tập dữ liệu của tôi trông như thế này:

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

Hiện nay

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

vẫn dẫn đến giá trị tùy chọn là chỉ mục (0, 1, 2, v.v.).

Thêm Track By đã sửa nó cho tôi:

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

Tôi nghĩ rằng điều đó xảy ra thường xuyên hơn khi bạn muốn thêm một mảng các đối tượng vào một danh sách chọn, vì vậy tôi sẽ ghi nhớ điều này!

Xin lưu ý rằng từ AngularJS 1.4, bạn không thể sử dụng tùy chọn ng nữa, nhưng bạn cần sử dụng ng-repeattrên thẻ tùy chọn của mình:

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

3
Câu trả lời này dường như chính xác là những gì câu hỏi đang yêu cầu. Mọi câu trả lời khác đều cho người đọc đừng lo lắng HTML được tạo ra là gì, nhưng nếu phần tử chọn ở dạng, tôi rất lo lắng. Câu trả lời chính xác!
Keith

3
Cần chỉ ra rằng điều này lưu trữ đối tượng được chọn đầy đủ trong mô hình, không chỉ là khóa. Nếu bạn chỉ muốn khóa trong mô hình, bạn muốn sử dụng phiên bản "item.key as item.value". Điều này làm tôi bối rối trong một thời gian khi tôi bị treo lên về cái HTML trông như thế nào, không phải là dữ liệu mà tôi muốn trong mô hình, mà đối với tôi, điều quan trọng.
mhenry1384

@ mhenry1384 Có bạn đúng, về việc nó lưu trữ toàn bộ đối tượng. Tôi thực sự thích tính năng đó vì nó cho phép bạn truy cập nhiều hơn chỉ ID (nếu bạn cần.). Hoạt động tốt cho tôi khi tôi điền danh sách với bộ sưu tập mongo và tôi cần một số tài sản từ mục đã chọn.
Mattijs

2
Và làm thế nào chúng ta có thể phát hiện những thay đổi với "ng-thay đổi" bên trong option?
Konstantinos Natsios

2
Về Cập nhật, điều này có vẻ không đúng. tùy chọn ng vẫn hoạt động tốt trong 1.5. Nó cũng vẫn được hiển thị trong tài liệu. docs.angularjs.org/api/ng/directive/select
Jeremy A. West

15

Câu hỏi đã được trả lời (BTW, câu trả lời thực sự hay và toàn diện do Ben cung cấp), nhưng tôi muốn thêm một yếu tố khác cho đầy đủ, có thể cũng rất tiện dụng.

Trong ví dụ được đề xuất bởi Ben:

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

hình thức ngOptions sau đây đã được sử dụng : select as label for value in array.

Nhãn là một biểu thức, kết quả sẽ là nhãn cho <option>phần tử. Trong trường hợp đó, bạn có thể thực hiện nối chuỗi nhất định, để có nhãn tùy chọn phức tạp hơn.

Ví dụ:

  • ng-options="item.ID as item.Title + ' - ' + item.ID for item in items" cung cấp cho bạn nhãn như Title - ID
  • ng-options="item.ID as item.Title + ' (' + item.Title.length + ')' for item in items"cung cấp cho bạn các nhãn như Title (X), Xđộ dài của chuỗi Tiêu đề.

Bạn cũng có thể sử dụng các bộ lọc, ví dụ:

  • ng-options="item.ID as item.Title + ' (' + (item.Title | uppercase) + ')' for item in items"cung cấp cho bạn các nhãn như Title (TITLE), trong đó giá trị Tiêu đề của thuộc tính Tiêu đề và TITLE là cùng một giá trị nhưng được chuyển đổi thành các ký tự viết hoa.
  • ng-options="item.ID as item.Title + ' (' + (item.SomeDate | date) + ')' for item in items"cung cấp cho bạn nhãn như Title (27 Sep 2015), nếu mô hình của bạn có một tài sảnSomeDate

7

Trong 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
Đừng quên của bạn radixcho parseInt: http://davidwalsh.name/parseint-radix
GFoley83

6

Nếu bạn cần một tiêu đề tùy chỉnh cho mỗi tùy chọn, ng-optionskhông thể áp dụng. Thay vào đó sử dụng ng-repeatvới các tùy chọn:

<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

Tôi hy vọng sau đây sẽ làm việc cho bạn.

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

1

Nó có thể hữu ích. Ràng buộc không phải lúc nào cũng hoạt động.

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

Ví dụ: bạn điền mô hình nguồn danh sách tùy chọn từ dịch vụ REST. Một giá trị được chọn đã được biết trước khi điền vào danh sách và nó đã được đặt. Sau khi thực hiện yêu cầu REST với $ http, tùy chọn danh sách được thực hiện.

Nhưng tùy chọn đã chọn không được đặt. Vì lý do không rõ AngularJS trong thực thi Shadow $ digest không ràng buộc được chọn như mong muốn. Tôi phải sử dụng jQuery để thiết lập lựa chọn. Nó quan trọng! AngularJS, trong bóng tối, thêm tiền tố vào giá trị của "giá trị" attr để tạo bởi các tùy chọn ng-repeat. Đối với int nó là "số:".

$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);
           }
       });
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.