Angular ng-repeat выражения как переменные

Я пытаюсь сделать что-то вроде этого:

<ul>
    <li ng-repeat="{{myRepeatExpression}}">{{row.name}}</li>
</ul>

Но поскольку логика ng-repeat находится в состоянии компиляции директивы, она рассматривает {{myRepeatExpression}} как обычную строку вместо переменной. Что не работает, очевидно.

Есть ли какое-либо обходное решение для этого?

Ответы

Ответ 1

Вы можете использовать и выражение с помощью ng-repeat, а не значения interpolated. Теперь, чтобы создать динамический повторяемый список, вы можете попробовать:

  • с помощью функции, которая динамически возвращает список в ng-repeat - это потенциально более дорого, так как angular необходимо сначала вызвать функцию, а затем определить, изменилась ли коллекция при выполнении цикла $digest
  • $watch для конкретной переменной в области, вызывающей изменение списка, - потенциально более эффективно, но если ваш динамический список зависит от нескольких переменных, он может стать более подробным и может привести к появлению потенциальных ошибок из забывания, чтобы добавить новый $watch, когда требуется новая переменная

Демо-плунжер

JS:

app.controller('MainCtrl', function($scope) {
  var values1 = [{name:'First'}, {name:'Second'}];
  var values2 = [{name:'Third'}, {name:'Fourth'}, {name:'Fifth'}];

  //1. function way
  $scope.getValues = function(id) {
    if(id === 1) {
      return values1;
    }
    if(id === 2) {
      return values2;
    }
  }

  //2. watch way
  $scope.values = undefined;
  $scope.$watch('id', function(newVal) {
    $scope.values = $scope.getValues(newVal);
  });
});

HTML:

<!-- Here we pass the required value directly to the function -->
<!-- this is not mandatory as you can use other scope variables and/or private variables -->
<ul>
  <li ng-repeat="v in getValues(id)">{{v.name}}</li>
</ul>
<!-- Nothing special here, plain old ng-repeat -->
<ul>
  <li ng-repeat="v in values">{{v.name}}</li>
</ul>

Ответ 2

ng-repeat принимает только синтаксис проприетарного выражения, как в row in rows, но rows может быть функцией или обещанием в вашем контроллере. Однако вам нужно внимательно наблюдать за работой, так как ng-repeat не работает с вещами, которые слишком часто меняются (ошибка с ошибкой не более 10 итераций).

Ответ 3

Вы не можете использовать ng-repeat со строкой/переменной, которая должна представлять выражение напрямую, но вы можете создать директиву, которая интерполирует/анализирует это значение и передает его аргументу ng-repeat и перекомпилирует элемент.

app.directive('ngVarRepeat',function($compile){
  return {
    priority:1001, //must be higher than 1000 (priority of ng-repeat)
    compile:function($elm,$attrs){

      var expression = $attrs.ngVarRepeat;
      $elm.removeAttr('ng-var-repeat'); // remove attribute so we can recompile it later

      return function(scope,elm,attrs){
        $elm.attr('ng-repeat',scope.$eval(expression));
        $compile($elm)(scope);
      }
    }
  }
})

Взгляните на этот плункер: демонстрационный плункер из принятого ответа

Также обратите внимание, что этот подход должен вызывать проблемы во вложенных ng-повторах.