Ng-Modell dynamisch zuweisen


82

Ich versuche, eine Reihe von Kontrollkästchen aus einem Objektarray zu generieren. Ich möchte, dass die Kontrollkästchen ihr ng-Modell dynamisch einer Eigenschaft des neuen Objekts zuordnen, das an das Array gesendet wird.

Was ich vorhatte, ist so etwas wie

<li ng-repeat="item in items">
    <label>{{item.name}}</label>
    <input type="checkbox" ng-model="newObject.{{item.name}}">
</li>

Dies funktioniert nicht, wie auf dieser JSFiddle zu sehen ist:

http://jsfiddle.net/GreenGeorge/NKjXB/2/

Kann jemand helfen?

Antworten:


146

Dies sollte Ihnen die gewünschten Ergebnisse liefern:

<input type="checkbox" ng-model="newObject[item.name]">

Hier ist ein funktionierender Plunk: http://plnkr.co/edit/ALHQtkjiUDzZVtTfLIOR?p=preview


1
hmm eigentlich gab mir das buchstäblich '<input ng-model = "newObject [item.name]">', fehlt mir etwas?
George Ananda Eman

Hmm, seltsam, habe gerade ein Live-Beispiel hinzugefügt (Plunker, da jsFiddle aus irgendeinem Grund heute nicht auf meiner Seite arbeitet).
pkozlowski.opensource

ah ja, ich war es gewohnt, in PHP zu denken und erwartete, dass sich das tatsächliche Markup in den Namen ändern würde, es funktionierte. Vielen Dank!
George Ananda Eman

2
Genial, genau das, wonach ich gesucht habe. Ich liebe Angular!
SharkofMirkwood

1
Es funktioniert auch hervorragend in Angular 2. Aber gibt es auch eine Lösung für mehrdimensionale Objekte? In Ihrem Beispiel sollte if item.namemanchmal auf newObject['x']und manchmal auf zeigen newObject['x']['y'].
Martin Schneider

23

BEARBEITEN Wie in den Kommentaren korrekt angegeben, erfordert die Verwendung dieser Option mit ng-change, dass zuvor ein "Dummy" -ng-Modell vorhanden ist. Es sollte jedoch beachtet werden, dass anscheinend mit 1.3 die erforderlichen Optionen vom Framework bereitgestellt wurden. Bitte überprüfen Sie https://stackoverflow.com/a/28365515/3497830 unten! /BEARBEITEN

Nur für den Fall, dass Sie wie ich über einen einfachen Fall stolpern, während Sie eine komplexere Aufgabe haben, ist dies die Lösung, die ich gefunden habe, um beliebige Ausdrücke dynamisch an ng-model zu binden: http://plnkr.co/edit/ccdJTm0zBnqjntEQfAfx?p = Vorschau

Methode: Ich habe eine Direktive dynamicModel erstellt, die einen Standardwinkelausdruck verwendet, ihn auswertet und das Ergebnis über ng-model und $ compile mit dem Bereich verknüpft.

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.data = {};
  $scope.testvalue = 'data.foo';
  $scope.eval = $scope.$eval;
});

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.data = {};
  $scope.testvalue = 'data.foo';
  $scope.eval = $scope.$eval;
});

app.directive('dynamicModel', ['$compile', function ($compile) {
    return {
        'link': function(scope, element, attrs) {
            scope.$watch(attrs.dynamicModel, function(dynamicModel) {
                if (attrs.ngModel == dynamicModel || !dynamicModel) return;

                element.attr('ng-model', dynamicModel);
                if (dynamicModel == '') {
                    element.removeAttr('ng-model');
                }

                // Unbind all previous event handlers, this is 
                // necessary to remove previously linked models.
                element.unbind();
                $compile(element)(scope);
            });
        }
    };
}]);

Die Verwendung ist einfach dynamic-model = "angularExpression", wobei angularExpression zu einer Zeichenfolge führt, die als Ausdruck für ng-model verwendet wird.

Ich hoffe, das erspart jemandem die Kopfschmerzen, diese Lösung finden zu müssen.

Grüße, Justus


3
Du bist ein Lebensretter. Ich war fast verzweifelt, bevor ich diesen Beitrag fand.
Nelo Mitranim

Können Sie genauer sein, Brian? Was hast du versucht und was ist passiert?
Justus Wingert

Dies ist ein konkurrierendes Juwel einer Lösung. Sie haben mich aus einem sehr heiklen Problem herausgeholt - danke!
Mikebert4

1
ng-change funktioniert damit nicht. Wenn Sie in die Winkelquelle schauen, hat die ngChange-Direktive ngModel als erforderliche Direktive. Eine Schnellsuche zeigt, dass nur ngChange und ngList dieses Problem haben. Alle anderen Anweisungen scheinen ngModel als optionalen Controller zu haben. Ich habe dieses Problem umgangen, indem ich jedem Element mithilfe der Direktive für das dynamische Modell ein ng-model = "dummyValue" hinzugefügt habe. Da eine Änderung des dynamischen Modells $ compile aufruft, werden ngChange und alle anderen Anweisungen, die den Wert ng-model verwenden, korrekt aktualisiert.
EverPresent

1
Dies ist eine robustere Lösung, wenn Sie nicht beobachten müssen, wie sich der Wert des dynamischen Modells ändert - stackoverflow.com/a/32096328/887092
Todd,

6

Mit Angular 1.3 können Sie mithilfe der ng-model-optionsDirektive das Modell dynamisch zuweisen oder an einen Ausdruck binden.

Hier ist ein Plunkr: http://plnkr.co/edit/65EBiySUc1iWCWG6Ov98?p=preview

<input type="text" ng-model="name"><br>
<input type="text" ng-model="user.name" 
ng-model-options="{ getterSetter: true }">

Weitere Informationen finden Sie ngModelOptionshier: https://docs.angularjs.org/api/ng/directive/ngModelOptions


Verzeihen Sie mir, wenn mir etwas fehlt, aber nichts an Ihrem Plunk scheint eine dynamische Modellzuweisung zu beinhalten. Und nichts an ngModelOptions würde das offensichtlich unterstützen. Könnten Sie vielleicht klarstellen? Weil es sehr nützlich wäre, wenn es tatsächlich so funktionieren würde ...
XML

@XMLilley "getterSetter: Boolescher Wert, der bestimmt, ob an ngModel gebundene Funktionen als Getter / Setter behandelt werden sollen oder nicht."
Chris Bolton

Vielen Dank an Rob, dass er mich darauf aufmerksam gemacht hat. Ich habe meine Antwort aktualisiert und mit Ihrer verknüpft.
Justus Wingert

1

Dies ist mein Ansatz, um einen tieferen Ausdruck zu unterstützen, z. B. 'model.level1.level2.value'.

<input class="form-control" ng-model="Utility.safePath(model, item.modelPath).value">

Dabei ist item.modelPath = 'level1.level2' und Utility (Modell, 'level1.level2') die Utility-Funktion, die model.level1.level2 zurückgibt


Können Sie näher erläutern, wie dies funktioniert? Was gibt Utility.safePath zurück, damit Sie dann .value verwenden können?
Devon Holcombe

Utility.safePath gibt den Wert der verschachtelten Variablen zurück, die durch die Pfadzeichenfolge angegeben wird. Beispiel: level1.level2 bezieht sich auf model.level1.level2.
Kanit Mekritthikrai

0

<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>

    <div ng-app="myApp" ng-controller="myCtrl">
        <form name="priceForm" ng-submit="submitPriceForm()">
            <div ng-repeat="x in [].constructor(9) track by $index">
                <label>
                    Person {{$index+1}} <span class="warning-text">*</span>
                </label>
                <input type="number" class="form-control" name="person{{$index+1}}" ng-model="price['person'+($index+1)]" />

            </div>
            <button>Save</button>
        </form>
    </div>

    <script>
        var app = angular.module('myApp', []);
        app.controller('myCtrl', function ($scope) {
            $scope.price = [];
            $scope.submitPriceForm = function () {
                //objects be like $scope.price=[{person1:value},{person2:value}....]
                console.log($scope.price);
            }
        });
    </script>
</body>
</html>

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.