AngularJS - привязать ng-модель к переменной, имя которой хранится внутри другой переменной

Я пытаюсь связать значение поля ввода с переменной. Я не знаю имя этой переменной априори; он сохраняется в другой переменной.

Это html:

<body ng-controller="stageController">
    <form name="myForm" novalidate="">
        <input type="text" name="myText" ng-model="model" />
    </form>
</body>

и это контроллер:

function stageController($scope) {
    $scope.model = 'realModel'; // contains the name of the variable that i would bind to the field 
    $scope.realModel = 'initial value of the field';
}

Я сделал также fiddle.

Это не работает, поскольку в настоящее время привязка находится между полем ввода и переменной model. Вместо этого я бы привязал поле ввода к переменной, имя которой хранится внутри переменной $scope.model (в данном случае realModel).

Возможно ли это? Как?

Ответы

Ответ 1

Да, возможно. Я не понимаю, почему вы хотите это сделать, но я могу показать вам, как это сделать. Я не мог начать скрипку, но я скопировал ее в plnkr: http://plnkr.co/edit/o1gFf1lMq4Pg5iVoVyUN?p=preview

Вы создаете директиву, которая преобразует исходный шаблон в новый с помощью компиляции. Новая директива:

directive('ngBindModel',function($compile){
    return{
        compile:function(tEl,tAtr){
          tEl[0].removeAttribute('ng-bind-model')
            return function(scope){
              tEl[0].setAttribute('ng-model',scope.$eval(tAtr.ngBindModel))
              $compile(tEl[0])(scope)
                console.info('new compiled element:',tEl[0])
            }
        }
    }
})

Обновлен html (изменение с ng-model на ng-bind-model, новая директива)

<input type="text" name="myText" ng-bind-model="model"  />

Ответ 2

Простейшая альтернатива - при условии, что можно немного изменить модель - HTML:

<body ng-controller="stageController">
    <form name="myForm" novalidate="">
        <input type="text" name="myText" ng-model="vars[model]" />
    </form>
</body>

Модель:

function stageController($scope) {
    $scope.model = 'realModel'; // contains the name of the variable that i would bind   to the field 
    $scope.vars = {};    // variables container
    $scope.vars.realModel = 'initial value of the field';
}

Ответ 3

Я попытался использовать предыдущий ответ внутри ng-repeat, и это не сработало. Он использует функцию compile, что означает, что все директивы использовали последний переданный в значении. Если вы используете функцию ссылки, она работает как ожидалось, т.е.

.directive('ngBindModel',function($compile){
      return{
        link:function(scope,element,attr){
          element[0].removeAttribute('ng-bind-model');
          element[0].setAttribute('ng-model',scope.$eval(attr.ngBindModel));
          $compile(element[0])(scope);
        }
      };
    })

Ответ 4

Ответ (в настоящее время выигранный) пользователем2273266 на самом деле тонко неверен. Хотя он будет работать, если вы используете только одну директиву один раз, он фактически путает элементы элемента шаблона и экземпляра объекта и будет помещать фамилию, которую он находит на ВСЕХ элементах, которые он отображает в цикле, например.

directive('custBindModel',function($compile){
    return{
        compile:function(tEl){
            tEl[0].removeAttribute('cust-bind-model');
            return function(scope, iEl, iAtr){
                iEl[0].setAttribute('ng-model',scope.$eval(iAtr.custBindModel));
                $compile(iEl[0])(scope);
                console.info('new compiled element:',tEl[0]);
            }
        }
    }
})

Эта версия исправляет проблему, разделяя операции над шаблоном и экземпляром, поэтому вызов после ссылки изменяет только экземпляр, а не шаблон.

Также изменился префикс 'ng', который зарезервирован.

Ответ 5

Я относительно новичок в Angularjs. Я знаю, что вы запрашиваете в Javascript, используя окно. Я не уверен в Angular. Я изменил код для достижения практически возможного решения:

 $scope.model = {'var':'realModel','value':'initial value of the field'};

Попробуйте fiddle:

Ответ 6

Что вам здесь не хватает, это директива ng-app, нет необходимости использовать явные директивы для ng-модели.

Это работает:

<body ng-app="myApp" ng-controller="stageController">
    <form name="myForm" novalidate="">
        <input type="text" name="myText" ng-model="realModel" />
    </form>
<script>
var app = angular.module('myApp', []);
app.controller('stageController', function($scope) {
    $scope.model = 'realModel'; 
    $scope.realModel = 'initial value of the field';
})
</script>
</body>