Подтвердить что ты не робот

Ng-repeat не обновляется при обновлении массива

Я обрабатываю данные через цикл ng-repeat. И я бы хотел, чтобы он обновлялся при обновлении массива. Из того, что я читал, это должно происходить автоматически, но это не работает. Итак, что я делаю неправильно?

html:

<tr ng-repeat="data in dataDifferenceArray">
    <td>
      {{data.name}}
    </td>
    <td>
      {{data.startData}}
    </td>
    <td>
      {{data.endData}}
    </td>
    <td>
      {{data.differenceData}}
    </td>
</tr>

Контроллер (эта функция запускается кнопкой с помощью ng-click):

$scope.getDifferences = function () {
  $scope.dataDifferenceArray = [];
  var i;
  for (i = 0; i < 20 ;i++) {
    $scope.dataDifferenceArray.push({
      name : 30,
      startData : 20,
      endData : 2,
      differenceData : 30
    })
  }
}

Console.log показывает, что массив обновлен правильно, однако таблица в моем представлении не изменяется. Я не знаю, что я делаю неправильно.

4b9b3361

Ответ 1

Это потому, что вы изменили ссылку на массив в своем методе getDifferences.

Чтобы избежать этого, мы точка, например, с синтаксисом "контроллер как":

<div ng-controller="myController as c">
    [...]

    <tr ng-repeat="data in c.dataDifferenceArray">
        <td>
          {{data.name}}
        </td>
        <td>
          {{data.startData}}
        </td>
        <td>
          {{data.endData}}
        </td>
        <td>
          {{data.differenceData}}
        </td>
    </tr>
    [...]

Если вы хотите понять, как работают области действия, я бы посоветовал эту статью: https://github.com/angular/angular.js/wiki/Understanding-Scopes#ngRepeat

Другим решением может быть:

$scope.getDifferences = function () {
  $scope.dataDifferenceArray.length = 0; // here ----
  var i;
  for (i = 0; i < 20 ;i++) {
    $scope.dataDifferenceArray.push({
      name : 30,
      startData : 20,
      endData : 2,
      differenceData : 30
    })
  }
}

но в этом решении вам нужно создать массив вне (и только один раз): $scope.dataDifferenceArray = [];

Edit2: Мой ответ был не совсем ясен, попробуйте понять, что происходит в глубине:

Q: Почему у ng-repeat все еще есть ссылка REFERENCE1?

Вы должны помнить, что в вашем шаблоне не только 1 область.

Например: директива ng-repeat создает новые области действия для каждого из повторяющихся элементов, но мы все равно можем получить доступ к родительской области в каждой дочерней области. Angular реализовало это поведение, используя Наследование прототипа: каждая дочерняя область наследует свойства своей родительской области благодаря прототипу.

Вы можете поэкспериментировать с тем, как он работает, проверяя его на дочерние элементы, а затем вводить в консоль: $($0).scope() (он предоставит вам область выбранного элемента, $0 - выбранный элемент (Chrome))., Теперь вы можете видеть, что в $($0).scope().$parent и $($0).scope().__proto__ есть один и тот же объект, это ваша родительская область.

Но есть одна проблема с наследованием прототипа: пусть говорят, что у нас есть A = {}; B = {C: 1}, если A наследует от B, а затем A.C == 1. Но если мы воздействуем на новое значение A.C = 2, мы не изменили B, а только A.

Angular выражения оцениваются с использованием текущей области действия this. Поэтому, если у нас есть что-то вроде ng-click="dataDifferenceArray = []", оно эквивалентно this.dataDifferenceArray = [], а this является областью действия элемента, где ng-click.

Эта проблема решается, если вы используете controller-as, потому что она вводит контроллер в область действия, и вы никогда не будете напрямую влиять на свойство области.

Вернем наш пример: A = {}; B = {C: {D: 1}}, если A наследует от B, а затем A.C.D == 1. И теперь, даже если мы затронем новое значение A.C.D = 2, мы также изменили B.

Ответ 2

даже при правильном обновлении ссылки на массив, у меня была та же проблема, ng-repeat не показывал мои изменения. Наконец, я нашел решение, вызвав $scope. $Apply();

$window.wizard.on("readySubmit", function () {
            var newArray = GenesisFactory.GetPermissionsFromTemplate(GenesisFactory.SecurityModules, true);
            $scope.NewSecurityProfileInstance.Permission.length = 0;
            newArray.forEach(function (entry) {
                $scope.NewSecurityProfileInstance.Permission.push(entry);
            });
            $scope.$apply();
        });

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

Ответ 3

Я ничего не сделал, но добавил эту строку $scope. $apply() "после нажатия элемента, и я закончил.

Ответ 4

На самом деле это похоже на то, что ваш массив будет установлен на пустое внутри функции щелчка. Это будет работать, если вы перемещаете область массивов вне функции.

Пример

// Declared outside
$scope.dataDifferenceArray = [];

// Your function
$scope.getDifferences = function () {
  var i;
  for (i = 0; i < 20 ;i++) {
    $scope.dataDifferenceArray.push({
      name : 30,
      startData : 20,
      endData : 2,
      differenceData : 30
    });
  }
};