Динамічно призначати 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.