2013-03-08 2 views
1

Я хочу использовать twitter Bootstrap с моим приложением, работающим на AngularJS. Я начал с макета сетки с помощью Леса строительные http://twitter.github.com/bootstrap/scaffolding.html#gridSystem и бегите в следующей задаче:Twitter Bootstrap Леса с AngularJS

В соответствии с документацией и примерами на Bootstrap, макет Грид следовать этой структуры:

<div class="row"> 
    <div class="span4">...</div> 
    <div class="span8">...</div> 
</div> 
<div class="row"> 
    <div class="span4">...</div> 
    <div class="span8">...</div> 
</div> 

...

Значение этих тегов с классами 'span' (столбцы) должно быть дочерними элементами тегов с классами 'row' (rows).

В моем приложении у меня есть простой массив объектов - проекты, которые я хочу показать как 3 проекта в каждой строке. Offcourse Я не знаю, сколько проектов я должен был отобразить. Как я понимаю, для такой структуры требуется два вложенных цикла: один для строк и один для столбцов, который отлично работает, если моя модель представляет собой двумерный массив, но я не хочу менять свою модель (проекты), чтобы она соответствовала вид. То, что я закончил делать, это использовать фильтр, чтобы изменить модель на два размера массива, а затем использовать вложенные ngRepeat для создания столбцов: http://jsfiddle.net/oburakevych/h4puc/11/

Кажется, работает, как ожидалось, но я получаю ошибки в консоли отладки:

Error: 10 $digest() iterations reached. Aborting! 

в моем понимании вложенной нг повторы в дайджесте запуск переваривать на внешние нг-повторить? Может ли кто-нибудь предложить правильный способ реализации этого?

ответ

3

Проблема заключается в том, что при использовании ng-repeat Angular создает часы для выражения списка, которое представляет собой комбинацию вашего массива проектов и фильтра. Когда Angular запускает дайджест, он продолжает называть эти часы, пока значение выражения больше не изменится. И так как ваш фильтр всегда создает новый массив, значение изменяется каждый раз, когда он вызывает вызов, а Угловая застревает в бесконечном цикле. Так что ваш код в основном так же, как это сделать:

$scope.myList = []; 
$scope.$watch('myList', function() { 
    $scope.myList = []; 
}); 

С часами на объем, вы можете сказать, Угловое сравнивать по значению вместо ссылки, чтобы избежать бесконечного переваривать проблемы, как это:

$scope.myList = []; 
$scope.$watch('myList', function() { 
    $scope.myList = []; 
}, true); // Passing true as the last argument triggers comparison by value instead 

Но это невозможно в вашем случае. Таким образом, ваш лучший выбор это только разделить массив проектов на более мелкие массивы, когда это необходимо, что-то вроде этого:

<!doctype html> 
<html ng-app="myApp"> 
<head> 
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> 
    <script src="http://code.angularjs.org/1.0.5/angular.min.js"></script> 
    <script> 
    angular.module('myApp', []).controller('Ctrl', function($scope) { 
     $scope.projects = [ 
      {name: 'My Project 1'}, 
      {name: 'My Project 2'}, 
      {name: 'My Project 3'}, 
      {name: 'My Project 4'}, 
      {name: 'My Project 5'}, 
      {name: 'My Project 6'} 
     ]; 

     var splitIntoRows = function(array, columns) { 
      if (array.length <= columns) { 
       return [array]; 
      } 

      var rowsNum = Math.ceil(array.length/columns); 

      var rowsArray = new Array(rowsNum); 

      for (var i = 0; i < rowsNum; i++) { 
       var columnsArray = new Array(columns); 
       for (j = 0; j < columns; j++) { 
        var index = i * columns + j; 

        if (index < array.length) { 
         columnsArray[j] = array[index]; 
        } else { 
         break; 
        } 
       } 

       rowsArray[i] = columnsArray; 
      } 

      return rowsArray; 
     } 

     $scope.$watch('projects', function() { 
      $scope.projectRows = splitIntoRows($scope.projects, 3); 
     }); 
    }); 
    </script> 
</head> 
<body ng-controller="Ctrl"> 
    <ul class="row" ng-repeat="projectRow in projectRows"> 
     <li class="span4" ng-repeat="project in projectRow"> 
      {{project.name}} 
     </li> 
    </ul> 
</body> 
</html> 

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

+0

Это прекрасно работает, спасибо! –

Смежные вопросы