Динамічно призначати ng-модель


82

Я намагаюся створити набір прапорців з масиву об'єктів. Я прагну до того, щоб прапорці динамічно зіставляли свою ng-модель із властивістю нового об'єкта, який буде подано в масив.

Я мав на увазі щось подібне

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

Це не працює, як видно на цьому JSFiddle:

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

Хто-небудь може допомогти?

Відповіді:


146

Це має дати бажані результати:

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

Ось робочий планк: http://plnkr.co/edit/ALHQtkjiUDzZVtTfLIOR?p=preview


1
хмм насправді це буквально дало мені '<input ng-model = "newObject [item.name]">', це щось мені не вистачає?
Джордж Ананда Еман

Хм, дивно, щойно додав живий приклад (plunker, оскільки з якихось причин jsFiddle сьогодні не працює на моїй стороні).
pkozlowski.opensource

так, я звик думати на php і очікував, що фактична розмітка зміниться на назву, це спрацювало. Дякую!
Джордж Ананда Еман

2
Блискуче, саме те, що я шукав. Я люблю Angular!
SharkofMirkwood

1
Він також чудово працює в Angular 2. Але чи існує рішення для багатовимірних об'єктів? У вашому прикладі, якщо item.nameіноді слід вказувати на, newObject['x']а іноді на newObject['x']['y'].
Мартін Шнайдер

23

РЕДАГУВАТИ Як правильно зазначено в коментарях, використовуючи це за допомогою ng-change, попередньо повинна бути присутня "фіктивна" ng-модель. Однак слід зазначити, що, мабуть, з 1.3 необхідні варіанти були передбачені рамками. Будь ласка, перевірте https://stackoverflow.com/a/28365515/3497830 нижче! / РЕДАКТУВАТИ

На той випадок, якщо ви схожі на мене, спотикаючись про простий випадок, маючи більш складне завдання, це рішення, яке я придумав для динамічного прив’язки довільних виразів до ng-моделі: http://plnkr.co/edit/ccdJTm0zBnqjntEQfAfx?p = попередній перегляд

Метод: Я створив директиву dynamicModel, яка приймає стандартний кутовий вираз, обчислює його і прив'язує результат до області дії за допомогою ng-моделі та $ 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);
            });
        }
    };
}]);

Використання - це просто dynamic-model = "angularExpression", де в результаті angularExpression виникає рядок, який використовується як вираз для ng-моделі.

Сподіваюсь, це рятує когось головний біль від необхідності придумувати це рішення.

З повагою, Юсту


3
Ти рятівник. Я майже зневірився, перш ніж знайти цю посаду.
Нело Мітранім

Чи можете ви бути конкретнішими Брайаном? Що ви пробували і що сталося?
Джастус Вінгерт

Це конкуруюча перлина рішення. Ви визволили мене з дуже липкої проблеми - дякую!
Mikebert4,

1
ng-change не працює з цим. Якщо заглянути в кутове джерело, директива ngChange має ngModel як необхідну директиву. Швидкий пошук показує, що цю проблему мають лише ngChange та ngList. У всіх інших директивах ngModel є додатковим контролером. Я обійшов цю проблему, додавши ng-model = "dummyValue" до будь-якого елемента, використовуючи директиву динамічної моделі. Оскільки зміна динамічної моделі викликає $ compile, ngChange та будь-які інші директиви, що використовують значення ng-model, оновлюються правильно.
EverPresent

1
Це більш надійне рішення, коли вам не потрібно спостерігати за зміною значення динамічної моделі - stackoverflow.com/a/32096328/887092
Тодд,

6

За допомогою Angular 1.3 ви можете використовувати ng-model-optionsдирективу для динамічного призначення моделі або прив'язки до виразу.

Ось додаток: 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 }">

Більше інформації ngModelOptionsтут: https://docs.angularjs.org/api/ng/directive/ngModelOptions


Вибачте мене, якщо я чогось пропускаю, але, здається, нічого про ваш плагін не включає динамічне призначення моделі. І ніщо про ngModelOptions, очевидно, не підтримало б цього. Не могли б ви пояснити? Тому що було б надзвичайно корисно, якби насправді це працювало таким чином ...
XML

@XMLilley "getterSetter: булеве значення, яке визначає, чи слід розглядати функції, прив'язані до ngModel, як геттери / сетери."
Кріс Болтон,

Дякую Роб, що звернув це на мою увагу, я оновив свою відповідь і зв’язав із Вашою.
Джастус Вінгерт,

1

Це мій підхід для підтримки глибшого виразу, наприклад, 'model.level1.level2.value'

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

де item.modelPath = 'level1.level2' та Utility (модель, 'level1.level2') - це функція утиліти, яка повертає model.level1.level2


Чи можете ви розповісти, як це працює? Що повертає Utility.safePath так, що ви можете потім використовувати .value?
Девон Холкомб

Utility.safePath повертає значення вкладеної змінної, вказане рядком шляху. наприклад level1.level2 відноситься до model.level1.level2.
Каніт Мекриттікрай,

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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.