Использование выражений в ngModel в Angular.js

Предоставление кода внутри моего контроллера:

$scope.entity = {
  firstName: 'Jack',
  lastName: 'Bauer',
  location: {
    city: 'New York'
  }
};
$scope.path = 'location.city';

Как динамически привязать ngModel к свойству entity, указанному path?

Я пробовал что-то вроде этого, но безрезультатно:

<input ng-model="'entity.' + path">

person Slava Fomin II    schedule 15.10.2015    source источник


Ответы (4)


Слава, я не уверен, что это хорошая идея для начала. Но в любом случае вам нужно сообщить о своей модели getterSetter, добавив это свойство к вашему входу ng-model-options="{ getterSetter: true }. Затем вам нужна функция в вашем контроллере, которая создает getterSetter из жала.

<input type="text" ng-model="propertify('entity.' + path)" ng-model-options="{ getterSetter: true }">

Вот как будет выглядеть получившийся шаблон.

К счастью, в angular есть сервис $parse, который делает это намного проще. поэтому что-то подобное должно быть в вашем контроллере или, что еще лучше, во внедренной службе.

  $scope.propertify = function (string) {
      var p = $parse(string);
      var s = p.assign;
      return function(newVal) {
          if (newVal) {
              s($scope,newVal);
          }
          return p($scope);
      } ;
  };

Это вернет функцию получения-установки, которая сделает это за вас. увидеть его в действии в этом фрагменте

person Sander Elias    schedule 16.10.2015
comment
Сандер, ты настоящий Angular-ниндзя, большое тебе спасибо! знак равно - person Slava Fomin II; 16.10.2015
comment
Я все еще получаю неназначаемую ошибку с этим ... но ваш plunkr работает нормально ???? - person ProblemsOfSumit; 08.04.2016
comment
У меня была не та угловая версия ???? - все отлично работает, спасибо! - person ProblemsOfSumit; 08.04.2016
comment
одна вещь, которую я бы сделал по-другому, - это использовать if(angular.isDefined(newVal)) {}, чтобы также присваивались пустые значения, например false или "" - person ProblemsOfSumit; 08.04.2016
comment
Отличное решение! К сожалению, он не распознает выражения массива, такие как data.model.step[0].theText, data.model.step[1].theText. Он автоматически преобразует числа 0, 1, 2 в ключи объекта вместо того, чтобы делать их массивом. - person supersan; 31.05.2016

Обновлять

Это не работает должным образом, значение отображается правильно, но не может быть изменено. Правильное решение предоставлено Сандером здесь.


Неверное решение

Вау, случайно решил:

<input type="text" ng-model="$eval('entity.' + path)">

А вот и планк.

Я надеюсь, что это поможет кому-то.

person Slava Fomin II    schedule 15.10.2015

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

<input ng-model="entity[locationKey][cityKey]"/>

Контроллер:

$scope.locationKey = 'location';
$scope.cityKey = 'city';

См. скрипт js

person Michael P. Bazos    schedule 15.10.2015
comment
Спасибо, но так не пойдет, я храню полный путь в одной переменной, в этом суть проблемы. - person Slava Fomin II; 15.10.2015

После прочтения и использования ответа Сандера Элиаса я использовал это, но столкнулся с другой проблемой.

При объединении его результата с ng-required="true" в <input> вы не могли очистить поле, потому что, когда поле было бы пустым, newVal передается как undefined.

Проведя дополнительные исследования, я обнаружил проблему на GitHub, которая решает и решает эту проблему.

Вот как выглядит объединенный ответ Сандера и GitHub:

$scope.propertify = function (string) {
    var property = $parse(string);
    var propAssign = property.assign;
    return function (newVal) {
        if (arguments.length) {
            newVal = angular.isDefined(newVal)?  newVal : '';
            propAssign($scope, newVal);
        }
        return property($scope);
    };
};

argument.length отражает количество значений, которые передаются геттеру/сеттеру, и будет 0 при получении и 1 при наборе.

Кроме того, я добавил angular.isDefined() как Sumit, предложенный в комментарии, чтобы также сохранить false и пустые ("") значения.

Вот обновленный планкер

person Jannis Nexor Ianus Betz    schedule 02.03.2017