Dynamicznie przypisuj model ng


82

Próbuję wygenerować zestaw pól wyboru z tablicy obiektów. Chcę, aby pola wyboru dynamicznie mapowały swój model ng do właściwości nowego obiektu, który zostanie przesłany do tablicy.

Miałem na myśli coś takiego

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

To nie działa, jak widać na tym JSFiddle:

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

Czy ktoś może pomóc?

Odpowiedzi:


146

To powinno dać pożądane rezultaty:

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

Oto działający plik: http://plnkr.co/edit/ALHQtkjiUDzZVtTfLIOR?p=preview


1
hmm właściwie to dosłownie dało mi '<input ng-model = "newObject [item.name]">', czy czegoś mi brakuje?
George Ananda Eman

Hmm, dziwne, właśnie dodałem przykład live (plunker, ponieważ z jakiegoś powodu jsFiddle nie działa dzisiaj po mojej stronie).
pkozlowski.opensource

Ach tak, przywykłem do myślenia w php i spodziewałem się, że znacznik zmieni się na nazwę, zadziałało. dzięki!
George Ananda Eman

2
Genialne, dokładnie to, czego szukałem. Uwielbiam Angular!
SharkofMirkwood

1
Świetnie sprawdza się również w Angular 2. Ale czy jest też rozwiązanie dla obiektów wielowymiarowych? W twoim przykładzie, jeśli item.namepowinien czasami wskazywać, newObject['x']a czasami wskazywać newObject['x']['y'].
Martin Schneider,

23

EDYCJA Jak słusznie zauważono w komentarzach, używanie tego ze zmianą ng wymaga wcześniejszego obecności „fikcyjnego” modelu ng. Należy jednak zauważyć, że najwyraźniej przy 1.3 ramy zapewniają wymagane opcje. Sprawdź https://stackoverflow.com/a/28365515/3497830 poniżej! /EDYTOWAĆ

Na wypadek, gdybyś tak jak ja, potykał się o prosty przypadek, mając bardziej złożone zadanie, oto rozwiązanie, które wymyśliłem dla dynamicznego wiązania dowolnych wyrażeń do ng-model: http://plnkr.co/edit/ccdJTm0zBnqjntEQfAfx?p = podgląd

Metoda: stworzyłem dyrektywę dynamicModel, która przyjmuje standardowe wyrażenie kątowe, ocenia je i łączy wynik z zakresem za pośrednictwem ng-model i $ compile.

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);
            });
        }
    };
}]);

Użycie jest po prostu dynamic-model = "angularExpression", gdzie angularExpression daje w wyniku ciąg używany jako wyrażenie dla ng-model.

Mam nadzieję, że zaoszczędzi to komuś bólu głowy związanego z koniecznością wymyślenia tego rozwiązania.

Pozdrawiam, Justus


3
Jesteś ratownikiem. Prawie rozpaczałem, zanim znalazłem ten post.
Nelo Mitranim

Czy możesz być bardziej konkretnym Brianem? Czego próbowałeś i co się stało?
Justus Wingert

To prawdziwa perełka rozwiązania. Wydostałeś mnie z bardzo przyklejonego problemu - dzięki!
Mikebert4

1
ng-change nie działa z tym. Jeśli spojrzysz na źródło kątowe, dyrektywa ngChange ma ngModel jako wymaganą dyrektywę. Szybkie wyszukiwanie pokazuje, że tylko ngChange i ngList mają ten problem. Wydaje się, że wszystkie inne dyrektywy mają ngModel jako opcjonalny kontroler. Obejrzałem ten problem, dodając ng-model = "dummyValue" do dowolnego elementu przy użyciu dyrektywy dynamic-model. Od czasu zmiany w wywołaniach modelu dynamicznego $ compile, ngChange i wszystkie inne dyrektywy używające wartości ng-model są poprawnie aktualizowane.
EverPresent

1
Jest to bardziej niezawodne rozwiązanie, gdy nie musisz patrzeć, jak zmienia się wartość modelu dynamicznego - stackoverflow.com/a/32096328/887092
Todd

6

W Angular 1.3 możesz użyć ng-model-optionsdyrektywy, aby dynamicznie przypisać model lub powiązać z wyrażeniem.

Oto 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 }">

Więcej informacji ngModelOptionstutaj: https://docs.angularjs.org/api/ng/directive/ngModelOptions


Wybacz mi, jeśli czegoś mi brakuje, ale nic w twojej wstawce nie wydaje się zawierać dynamicznego przypisania modelu. I nic w ngModelOptions oczywiście by tego nie wspierało. Czy mógłbyś to wyjaśnić? Ponieważ byłoby bardzo przydatne, gdyby faktycznie działało w ten sposób ...
XML

@XMLilley "getterSetter: wartość logiczna, która określa, czy należy traktować funkcje powiązane z ngModel jako metody pobierające / ustawiające."
Chris Bolton

Dziękuję Rob, że zwróciłeś mi na to uwagę, zaktualizowałem moją odpowiedź i połączyłem z Twoją.
Justus Wingert,

1

To jest moje podejście do obsługi głębszych wyrażeń, np. „Model.level1.level2.value”

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

gdzie item.modelPath = 'level1.level2' a Utility (model, 'level1.level2') to funkcja narzędziowa, która zwraca model.level1.level2


Czy możesz wyjaśnić, jak to działa? Co zwraca Utility.safePath, aby można było następnie użyć .value?
Devon Holcombe

Utility.safePath zwraca wartość zagnieżdżonej zmiennej określonej przez ciąg ścieżki. np. level1.level2 odnosi się do 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>

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.