wake-up-neo.net

Der gewählte Wert von ng-options kann nicht eingestellt werden

Ich versuche, eine Dropdown-Liste mit Auswahloptionen aufzufüllen und einen ausgewählten Standardwert mithilfe von ng-model und ng-options festzulegen.

Ich habe den folgenden Code in meiner Ansicht:

<select ng-model="thisTour.site" ng-options="site.name for site in siteList"></select>

Und in meinem Controller:

    $scope.siteList = [
        { id: 1, name: 'cycling'},
        { id: 2, name: 'walking'},
        { id: 3, name: 'holidays'}
    ]

    $scope.thisTour.site = { id: 2, name: 'walking'};

Die Liste wird mit den korrekten 3 Optionen des siteList-Objekts aufgefüllt, wählt jedoch nicht standardmäßig walking aus, wie ich es erwarten würde. Warum nicht?

Wenn ich das jetzt ändere:

$scope.thisTour.site = { id: 2, name: 'walking'};

Zu diesem:

$scope.thisTour.site = $scope.siteList[1];

Jetzt gehts. Warum? Ist es nicht dasselbe?

14
Inigo

Das liegt daran, dass Winkel nach Objektgleichheit sucht, um es an Ihre Syntax zu binden, und $scope.siteList[1] ist in Ihrem Fall nicht gleich { id: 2, name: 'walking'}; (2 Objekte sind nur dann gleich, wenn sie auf dieselbe Referenz zeigen). Sie können dies auf verschiedene Weise umgehen. Eine einfache Möglichkeit besteht darin, die track by-Syntax mit ng-options zu verwenden, um die Spur durch id anzugeben. Dadurch können die Optionen von ng-option von der angegebenen Eigenschaft des gebundenen Objekts und nicht von der Objektreferenz verfolgt werden selbst.

<select ng-model="thisTour.site" 
    ng-options="site.name for site in siteList track by site.id"></select>

Sie können die Syntax auch verwenden, um das ng-model so einzustellen, dass nur die ID mit select als Teil in der Syntax angegeben wird: -

Beispiel:-

ng-options="site.id as site.name for site in siteList"

und Modell wäre nur: -

 $scope.thisTour.site = 2;

angular.module('app', []).controller('ctrl', function($scope){
  $scope.thisTour = {};
 $scope.siteList = [
        { id: 1, name: 'cycling'},
        { id: 2, name: 'walking'},
        { id: 3, name: 'holidays'}
    ]

    $scope.thisTour.site = { id: 2, name: 'walking'};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <select ng-model="thisTour.site" ng-options="site.name for site in siteList track by site.id"></select>
  {{thisTour.site}}
  </div>

Aus Dokumentation

trackexpr: - Wird beim Arbeiten mit einem Array von Objekten verwendet. Das Ergebnis dieses Ausdrucks wird zur Identifizierung der Objekte im Array verwendet. Der Trackexpr bezieht sich höchstwahrscheinlich auf die Wertvariable (z. B. value.propertyName). Damit bleibt die Auswahl erhalten, auch wenn die Optionen neu erstellt werden (z. B. vom Server neu geladen).

Auch erwähnenswert:

Verwenden Sie select as und track by nicht in demselben Ausdruck. Sie sind nicht dafür konzipiert, zusammenzuarbeiten.

44
PSL

Dies ist nicht dasselbe, da Objekte in Javascript durch Verweis übergeben werden.

Wenn Sie das erste Beispiel nehmen:

$scope.siteList = [
    { id: 1, name: 'cycling'},
    { id: 2, name: 'walking'},
    { id: 3, name: 'holidays'}
]

$scope.thisTour.site = { id: 2, name: 'walking'};

Dann machst du das:

$scope.thisTour.site.id = 3;
console.log($scope.siteList[1].id) // 2

Mit anderen Worten, während Ihre beiden Objekte in value gleich sind, sind sie nicht dasselbe Objekt. Die ngOptions-Direktive sieht dies und würde thisTour.site auf einen leeren Wert setzen, da dies keine der zulässigen Optionen ist.

Google "Weiterleitung durch Verweis in Javascript", um mehr zu erfahren.

3
Ed Hinchliffe

Da Sie das gesamte Objekt in Ihrer Auswahl verwenden, wird bei einem Vergleich von Angular festgestellt, ob die Objekte gleich sind, um die Auswahl zu bestätigen. Ich glaube, es gibt eine Möglichkeit, die Funktionalität dahingehend zu ändern, wie Angular seine Vergleiche durchführt, aber ich gehe einfach durch die Auswahl und mache meine eigenen Vergleiche ähnlich der folgenden:

$scope.siteList = [
        { id: 1, name: 'cycling'},
        { id: 2, name: 'walking'},
        { id: 3, name: 'holidays'}
    ]
angular.forEach($scope.siteList, function(site, index) {
    if (site.id == 2) {
        $scope.thisTour.site = site;
    }
});

Dadurch wird das eigentliche Objekt auf Ihre Variable gesetzt, sodass es im Auswahlbereich festgelegt werden kann.

1
Matthew Green

Verwenden Sie diese Anweisung, um die Anweisung ng-init auszuführen.

<div ng-init="thisTour.site = siteList[position]">
    <select ng-model="thisTour.site" ng-options="site.name for site in  siteList track by site.id"></select>
</div>
0
Arul Ramalingam