Не могу ли я использовать один из элементов моей коллекции областей в качестве переключателя по умолчанию?

#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]);