Inicjalizacja select za pomocą AngularJS i ng-repeat

133

Staram się, aby pole wyboru zaczęło się od wstępnie wypełnionej opcji przy użyciu ng-repeat z AngularJS 1.1.5. Zamiast tego wybór zawsze zaczyna się od niczego nie zaznaczonego. Ma również pustą opcję, której nie chcę. Myślę, że jest efekt uboczny braku wyboru.

Mogę to uruchomić, używając opcji ng-options zamiast ng-repeat, ale w tym przypadku chcę użyć ng-repeat. Chociaż mój zawężony przykład tego nie pokazuje, chcę również ustawić atrybut tytułu każdej opcji i nie ma sposobu, aby to zrobić za pomocą ng-options, o ile wiem.

Nie sądzę, że jest to związane z powszechnym problemem dziedziczenia zakresu / prototypów w AngularJs. Przynajmniej nie widzę niczego oczywistego podczas inspekcji w Batarangu. Ponadto po wybraniu opcji w menu wyboru za pomocą interfejsu użytkownika model aktualizuje się poprawnie.

Oto kod HTML:

<body ng-app ng-controller="AppCtrl">
    <div>
        Operator is: {{filterCondition.operator}}
    </div>
    <select ng-model="filterCondition.operator">
       <option 
           ng-repeat="operator in operators" 
           value="{{operator.value}}"
       >
           {{operator.displayName}}
       </option>
    </select>
</body>

Oraz JavaScript:

function AppCtrl($scope) {

    $scope.filterCondition={
        operator: 'eq'
    }

    $scope.operators = [
        {value: 'eq', displayName: 'equals'},
        {value: 'neq', displayName: 'not equal'}
     ]
}

JS Fiddle do tego: http://jsfiddle.net/coverbeck/FxM3B/2/

Charles O.
źródło
1
ngOption zostało stworzone, ponieważ nie było na to prostego sposobu z ngRepeat. ngRepeat rozwija się po wybraniu opcji. Czy próbowałeś ustawić ngSelect w swoich opcjach
TheSharpieOne
Tak! NgSelected zadziałało! Opublikuję zaktualizowany działający JsFiddle.
Charles O.
Należy zauważyć, że w AngualrJS 1.2 ten kod działa inaczej - nie tworzy nowego pustego elementu <OPTION>, jednak jest w stanie wybrać tylko pierwszą opcję z listy. Możesz to zobaczyć tutaj
VitalyB

Odpowiedzi:

226

DOBRZE. Jeśli nie chcesz używać poprawnego sposobu ng-options, możesz dodać ng-selectedatrybut z logiką sprawdzania warunków dla optiondyrektywy, aby wybór wstępny działał.

<select ng-model="filterCondition.operator">
    <option ng-selected="{{operator.value == filterCondition.operator}}"
            ng-repeat="operator in operators"
            value="{{operator.value}}">
      {{operator.displayName}}
    </option>
</select>

Working Demo

zs2020
źródło
37
Dam ci kredyt, ponieważ sam to rozgryzłeś i zrobiłeś pełny przykład. Chociaż nie zgadzam się z twoim komentarzem, że ng-options jest „właściwą drogą”. :) Zawsze sam używałem ng-options, ale wymagało to zrobienia czegoś, czego ng-options nie obsługuje, choć jest to małe. A doktor Angular mówi, że możesz również powtarzać ng. Dzięki, Charles
Charles O.
Dzięki, to był łatwy sposób na wyłączenie niektórych opcji.
Dorian,
11
ng-options jest poprawne tylko wtedy, gdy jego zastosowania pasują do twojego. Możesz potrzebować dodatkowych atrybutów / klas w polach opcji / optgroup itp.
mystrdat
6
„we właściwy sposób” czasami nie działa (np. jeśli chcesz przetłumaczyć ciągi znaków wypełniających nazwy opcji)
btk
11
Myślę, że wyrażenie ng-selected musi być bez {{}}: ng-selected = "operator.value == filterCondition.operator"
mvermand
35

W przypadku tagu select, angular udostępnia dyrektywę ng-options. Daje ci konkretną strukturę do konfigurowania opcji i ustawiania wartości domyślnych. Oto zaktualizowane skrzypce używające opcji ng, które działają zgodnie z oczekiwaniami: http://jsfiddle.net/FxM3B/4/

Zaktualizowany HTML (kod pozostaje ten sam)

<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator}}</div>
<select ng-model="filterCondition.operator" ng-options="operator.value as operator.displayName for operator in operators">
</select>
</body>
Jeremy Likness
źródło
3
Cześć Jeremy - próbuję to zrobić bez opcji ng. Tak jak powiedziałem w swoim pytaniu i odpowiadając Shaunowi, chciałbym ustawić atrybut tytułu dla każdej opcji, a nie mogę tego zrobić z ng-options, o ile wiem. Dzięki, Charles
Charles O.
9

Podziękowania dla TheSharpieOne za wskazanie opcji wybranej przez ng. Gdyby to zostało opublikowane jako odpowiedź, a nie jako komentarz, zrobiłbym to poprawną odpowiedź.

Oto działający JSFiddle: http://jsfiddle.net/coverbeck/FxM3B/5/ .

Zaktualizowałem również skrzypce, aby używały atrybutu tytułu, który pominąłem w moim oryginalnym poście, ponieważ to nie było przyczyną problemu (ale jest to powód, dla którego chcę użyć ng-repeat zamiast ng-options) .

HTML:

<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator}}</div>
<select ng-model="filterCondition.operator">
   <option ng-repeat="operator in operators" title="{{operator.title}}" ng-selected="{{operator.value == filterCondition.operator}}" value="{{operator.value}}">{{operator.displayName}}</option>
</select>
</body>

JS:

function AppCtrl($scope) {

    $scope.filterCondition={
        operator: 'eq'
    }

    $scope.operators = [
        {value: 'eq', displayName: 'equals', title: 'The equals operator does blah, blah'},
        {value: 'neq', displayName: 'not equal', title: 'The not equals operator does yada yada'}
     ]
}
Charles O.
źródło
Przepraszamy za komentarz. Nie chciałem robić przykładu i nie byłem w 100% pewien, czy zadziała. To było tylko przeczucie.
TheSharpieOne
9

Fakt, że angular wstrzykuje pusty element opcji do elementu select, polega na tym, że obiekt modelu powiązany z nim domyślnie ma pustą wartość w po zainicjowaniu.

Jeśli chcesz wybrać opcję domyślną, prawdopodobnie możesz ustawić ją w zakresie w kontrolerze

$scope.filterCondition.operator = "your value here";

Jeśli chcesz mieć pusty symbol zastępczy opcji, działa to dla mnie

<select ng-model="filterCondition.operator" ng-options="operator.id as operator.name for operator in operators">
  <option value="">Choose Operator</option>
</select>
Ammadu
źródło
2
To dobrze, ale Angular tworzy pustą opcję. Jak tego uniknąć?
MarceloBarbosa
1

Zgodnie z sugestią, musisz użyć opcji ng-options i niestety uważam, że musisz odwołać się do elementu tablicy jako domyślnego (chyba że tablica jest tablicą ciągów).

http://jsfiddle.net/FxM3B/3/

JavaScript:

function AppCtrl($scope) {


    $scope.operators = [
        {value: 'eq', displayName: 'equals'},
        {value: 'neq', displayName: 'not equal'}
     ]

    $scope.filterCondition={
        operator: $scope.operators[0]
    }
}

HTML:

<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator.value}}</div>
<select ng-model="filterCondition.operator" ng-options="operator.displayName for operator in operators">
</select>
</body>
shaunhusain
źródło
Czy wiesz dlaczego i czy na pewno? Dokumentacja ( docs.angularjs.org/api/ng.directive:select ) mówi, że musisz używać opcji ng-options tylko przy wiązaniu z wartością niebędącą ciągiem. Tak jak powiedziałem, chcę użyć atrybutu tytułu, a nie ma sposobu, aby to zrobić z ng-options. Coś w rodzaju <option title = "Bardzo długi opis tego wyboru" ...> Dzięki.
Charles O.
Uważam, że notatka w dokumentacji jest trochę niejasna i faktycznie oznacza, że ​​musiałbyś użyć łańcucha dla modelu i mieć tablicę ciągów dla opcji. Jeśli nie masz nic przeciwko temu, jakie jest powody używania atrybutu „tytuł”, nie widzę go na W3C w3schools.com/tags/tag_option.asp i nie przypominam sobie, żeby go naprawdę używać. Czy nie mógłbyś po prostu przechowywać opisu w obiektach, a następnie nadal pobierać te dane, ponieważ do tego jest teraz powiązany model?
shaunhusain,
Na stronie W3C, do której utworzyłeś łącze, po kliknięciu łącza Global Attributes zobaczysz, że atrybut tytułu jest obsługiwany przez element opcji. Używam atrybutu title tylko po to, aby wyświetlić tekst "podpowiedzi", więc jeśli najedziesz kursorem na opcję, możesz uzyskać większy opis tego, co oznacza ta opcja. To drobiazg, ale dobrze by było mieć, jeśli to możliwe.
Charles O.
@CharlesO. Chcę robić dokładnie tak jak ty. Ustaw obiekt (wartość niebędąca ciągiem znaków), ale chcę również użyć tytułu na liście opcji. Czy jest na to rozwiązanie. Nie mogę tego znaleźć ...
Wilt
1

Jeśli używasz opcji md-select i ng-powtarzania md z materiału kątowego, możesz dodać ng-model-options="{trackBy: '$value.id'}"do tagu md-select popiół pokazany na tym piórze

Kod:

<md-select ng-model="user" style="min-width: 200px;" ng-model-options="{trackBy: '$value.id'}">
  <md-select-label>{{ user ? user.name : 'Assign to user' }}</md-select-label>
  <md-option ng-value="user" ng-repeat="user in users">{{user.name}}</md-option>
</md-select>

Japheth Ongeri - inkalimeva
źródło