Ошибка дублирования углового массива при добавлении новых объектов в массив

0

У меня есть система оповещения, и пользователь должен иметь возможность создавать неограниченное количество предупреждений и добавлять к каждому предупреждению неограниченное количество триггеров.

Например, у пользователя может быть предупреждение под названием "Когда цены меняются на моих автомобилях". Они должны иметь возможность создавать триггер того же типа ("Изменение цены") для каждого из автомобилей, за которыми они хотят следовать.

Далее следует урезанная версия, имеющая дело только с триггерами.

Здесь плункер - просто нажмите Add дважды, и вы увидите проблемы.

JS

// the array of trigger possibilities
$scope.triggerOptions = [
  {id : 0, type: 1, action: "Status Update For Brand"},
  {id : 1, type: 2, action: "Price Changed for "}
];

// the model for the select element
$scope.selected = $scope.triggerOptions[0];

// this array will hold all the triggers created
$scope.triggers = [];

// add some indexes to the new trigger object, then add it to triggers
$scope.addTrigger = function() {
  var newTrigger = $scope.selected;
  var newID = $scope.triggers.length;
  var alertID = 0; // todo: apply alert id
  newTrigger.triggerID = newID;
  newTrigger.alertID = alertID;
  $scope.triggers.push(newTrigger);
};

HTML

<select ng-options = "option.action for option in triggerOptions track by option.id" ng-model = "selected"></select>
<button ng-click="addTrigger()">Add</button>

<div ng-repeat="trigger in triggers track by triggerID" class="alert-tool-action-box">
  <div ng-show="trigger.type==1">
    <div>{{trigger.action}}</div>
  </div>

  <div ng-show="trigger.type==2">
    <div>{{trigger.action}}</div>
  </div>
</div>

вопросы

  • Когда я добавляю более одного триггера, отображается только первый триггер, но я получаю сообщение об ошибке "dupes" (что предполагает, что я добавляю "track by", но я уже это сделал).
  • Когда я добавляю два триггера одного и того же типа в строке, триггерID обновляется до нового триггера для обоих триггеров:

один триггер:

[{"id":0,"type":1,"action":"Status Update For Brand","triggerID":0,"alertID":0}]

два триггера:

[
  {"id":0,"type":1,"action":"Status Update For Brand","triggerID":1,"alertID":0},
  {"id":0,"type":1,"action":"Status Update For Brand","triggerID":1,"alertID":0}
]

Я должен уметь видеть каждый триггер, когда добавляю их, даже если они такие же, как раньше.

  • 0
    TL; DR; track by должен быть уникальным, поэтому triggerID не может содержать дубликаты. Вы всегда можете попробовать и отслеживать по $index .
  • 1
    Или вообще не использовать трек. Но почему у вас два триггера с одинаковым идентификатором? Разве идентификатор не должен однозначно идентифицировать триггер?
Теги:
angularjs-ng-repeat

3 ответа

1
Лучший ответ
  • Вы ng-repeat показываете только один представитель вашего массива, потому что вы отслеживаете с помощью triggerID, которого нет (угловой должен искать его в области $ scope и возвращать undefined каждый раз, когда он его вызывает). Хорошим способом вызова triggerID будет trigger.triggerID. Так:

     <div ng-repeat="trigger in triggers" class="alert-tool-action-box">
      ....
    </div>
    

    или если вы хотите использовать трек:

    <div ng-repeat="trigger in triggers track by trigger.triggerID class="alert-tool-action-box">
      ....
    </div>
    
  • Вторая проблема связана с тем, что javascript передает объект по ссылке, а не по значению. Вы не создаете новый объект. Вы просто передаете то же самое и измените его значение. Это почему у вас есть все объекты, которые обновляются с одним и тем же идентификатором. Таким образом, вы можете использовать angular.copy(), чтобы сделать его другим объектом. Что-то вроде:

     $scope.addTrigger = function() {
       var newTrigger = angular.copy($scope.selected);
       var newID = $scope.triggers.length;
       var alertID = 0; // todo: apply alert id
       newTrigger.triggerID = newID;
       newTrigger.alertID = alertID;
       $scope.triggers.push(newTrigger);
    };
    
  • 0
    О хорошо Я подумал, присваивая selected новой переменной, он создавал новый экземпляр. Спасибо!
  • 0
    Для первичной стоимости да. Не для объекта.
Показать ещё 2 комментария
2

Что касается второй проблемы, вы всегда нажимаете один и тот же объект, так как у вас есть только один экземпляр $ scope. Чтобы решить эту проблему, вам просто нужно клонировать (или копировать) $ scope.selected, например:

var newTrigger = angular.copy($scope.selected);

Надеюсь, поможет!

  • 0
    Это устраняет проблему с установленным триггером, но при этом отображается только один триггер, хотя в объекте триггеров много триггеров. plnkr.co/edit/yn6t8PHN1QRXOzy4uv7q?p=preview
2

Ваш массив объектов не может содержать дубликатов (Ошибка: [ngRepeat: dupes]), теперь эти два объекта равны. Это можно решить с помощью track by, который должен быть уникальным, поэтому triggerID не может использоваться здесь. Вы всегда можете использовать track by $index (предоставляется директивой ng-repeat), если нет уникального свойства.

  • 0
    triggerID установлен в длину массива триггеров, поэтому он не будет уникальным, верно? Я имею в виду каждый раз, когда объект добавляется, это число меняется. Но спасибо за идею $index , я попробую это.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню