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.