#angularjs #angularjs-ng-repeat
#angularjs #angularjs-ng-repeat
Вопрос:
Допустим, у меня есть этот контроллер:
myCtrl = function($scope)
{
$scope.shipMethods = [{ "name": "standard",
"id" : 1},
{ "name": "overnight",
"id" : 2},
{ "name": "next day",
"id" : 3}
];
$scope.selectedShipMethod = $scope.shipMethods[0];
//works: $scope.selectedShipMethod = { "name": "standard", "id" : 1};
};
И я получил это, на мой взгляд:
<div ng-app>
<div ng-controller="myCtrl">
<form>
<h1>you selected {{ selectedShipMethod.name }} </h1>
<label class="radio-input" data-ng-repeat="shipMethod in shipMethods">
<b class="title">{{shipMethod.name}}</b>
<input type="radio" name="ship-method" value="{{shipMethod.name}}"
data-ng-model="selectedShipMethod.name" />
</label>
</form>
</div>
Я пытаюсь установить метод selectedShipMethod, когда пользователь выбирает одну из переключателей. Но когда я выбираю вторую или третью переключатели, метка рядом с первой обновляется тем, что находится в selectedShipMethod.name . Но вот загадка ng: если я создам копию первого элемента в моем массиве и инициализирую $scope.selectedShipMethod для этой копии, я НЕ вижу проблемы.
Похоже, здесь нужно понять что-то более глубокое о переключателях в ng-repeat. Фактические данные, с которыми я работаю, будут поступать с веб-сервера, имеют некоторые предполагаемые даты доставки, которые изменятся, поэтому я бы очень хотел использовать элемент массива по умолчанию.
Вот скрипка
Ответ №1:
Когда вы нажимаете переключатель, первый элемент в списке переключателей изменяется, как и соответствующая метка: {{ selectedShipMethod .имя }}.
Чтобы понять, почему это происходит, нам нужно более внимательно посмотреть, к какой модели на самом деле привязан переключатель. В родительском контроллере вы инициализировали метод selectedShipMethod для первого метода ship ($scope .Shipmethod[0]) в родительской области:
// bind the selectedShipMethod to the first ship method
$scope.selectedShipMethod = $scope.ShipMethods[0];
Это важно помнить, потому что selectedShipMethod фактически никогда не меняется — даже при нажатии на другую радиокнопку.
Чтобы понять, почему, более внимательно посмотрите на ng-модель переключателя:
<input type="radio" name="ship-method"
data-ng-model="selectedShipMethod.name" />
Ng-модель, к которой привязан переключатель, на самом деле ‘selectedShipMethod.name «. Обратите внимание, что в середине модели есть «.». Согласно правилам наследования области, ‘selectedShipMethod’ сначала будет разрешен путем поиска объявления переменной в текущей области; если она не найдена в текущей области, она будет искать ее в родительской области и т. Д., Пока она либо не найдет переменную области, либо не остановится на $ rootScope. В этом примере он найдет его в родительской области, которая, если вы помните, привязана к первому методу отправки.
Выбирая другой переключатель, вы фактически изменяете свойство ‘.name’ первого способа доставки! Очевидно, что это не то, чего мы хотим.
Итак, каково решение?
Решение простое — измените привязку так, чтобы selectedShipMethod привязывался к той же модели, которая находится в родительской области:
<input type="radio" name="ship-method" ng-value="shipMethod"
data-ng-model="$parent.selectedShipMethod" />
Это именно то, что мы делаем, когда выполняем ‘$parent.selectedShipMethod’. $parent ссылается на родительскую область, поэтому, согласно правилам наследования области, он найдет и разрешит переменную selectedShipMethod в родительской области.
Возможно, на этом этапе вы спрашиваете себя, действительно ли необходим префикс $parent ? Ответ — да. Поскольку переменная области устанавливается (при нажатии переключателя), вызывается установщик для переменной области. Разрешение наследования области не происходит, если в модели нет ‘.’ и используется установщик — без префикса $parent это создало бы копию переменной области в дочерней области, которая затеняет переменную области в родительской области, эффективно нарушая привязку модели.
Наконец, мы используем ng-value, поскольку shipMethod
это модель из директивы ng-repeat . Когда выбран переключатель, $parent.selectedShipMethod устанавливается в значение selected shipMethod
. Все работает, потому что правильная модель ($parent.selectedShipMethod ) привязывается к правильной области — родительской области.
Я надеюсь, что все это имеет смысл. Вот рабочая скрипка
Комментарии:
1. Это очень тщательный анализ. Спасибо!!
Ответ №2:
Вот так. Вместо того, чтобы устанавливать выбранный объект на первый элемент массива, просто сделайте копию в новый объект.
http://jsfiddle.net/csrow/XFq56/3/
Когда вы устанавливаете
a = b[0];
a и b[0] оба указывают на один и тот же объект. Итак, когда вы устанавливаете ‘a’ с помощью переключателя, вы фактически изменяете объект b [0] .
Ответ №3:
Проблема в вашем коде заключается в обратном связывании. Попробуйте следующий код:
$scope.selectedShipMethod = angular.copy($scope.shipMethods[0]);