2012-06-15 2 views
28

Как использовать AngularJS ng-repeat для отображения следующего HTML (Twitter Bootstrap Scaffolding)? По сути, каждый третий рекорд мне нужно закрыть </div>, распечатайте <hr>, а затем открыть другой <div class="span4">Как бы использовать AngularJS ng-repeat с подставкой Twitter Bootstrap?

<div class="row"> 
     <div class="span4"> 
     <h3> 
      Project A 
     </h3> 
     </div> 
     <div class="span4"> 
     <h3> 
      Project B 
     </h3> 
     </div> 
     <div class="span4"> 
     <h3> 
      Project C 
     </h3> 
     </div> 
    </div> 

    <hr> 

    <div class="row"> 
     <div class="span4"> 
     <h3> 
      Project D 
     </h3> 
     </div> 
     <div class="span4"> 
     <h3> 
      Lab Title 
     </h3> 
     </div> 
     <div class="span4"> 
     <h3> 
      Project E 
     </h3> 
     </div> 
    </div> 

Я создал скрипку для кода демоса.
http://jsfiddle.net/ADukg/261/

ответ

15

Более изящный способ использовать модель представления, чтобы обеспечить Chunked коллекцию, а затем пусть вид обрабатывать его как

<div ng-controller="Controller"> 
    Projects <input ng-model="projects"></input> 
    <hr/> 
    <div ng-repeat="row in rows"> 
     <div ng-repeat="project in row"> 
      Projects {{project}} 
     </div> 
     <hr/> 
    </div> 
</div>​ 

и CoffeeScript довольно просто

# Break up an array into even sized chunks. 
chunk = (a,s)-> 
    if a.length == 0 
     [] 
    else    
     (a[i..i+s-1] for i in [0..a.length - 1 ] by s) 

@Controller = ($scope)-> 
    $scope.projects = "ABCDEF" 

    $scope.$watch "projects", ->  
     $scope.rows = chunk $scope.projects.split(""), 3 

angular.bootstrap(document, []); 

http://jsfiddle.net/ADukg/370/

38

Вот способ:

<div ng-controller="MyCtrl"> 
    <div ng-repeat="project in projects"> 
    <span ng-if="$index % 3 == 0"> 
     <hr /> 
     <div class="row"> 
     <h3 class="span4" ng-if="projects[$index+0]">{{projects[$index+0]}}</h3> 
     <h3 class="span4" ng-if="projects[$index+1]">{{projects[$index+1]}}</h3> 
     <h3 class="span4" ng-if="projects[$index+2]">{{projects[$index+2]}}</h3> 
     </div> 
    </span> 
    </div> 
</div> 

Этот способ также будет работать, если у вас есть, например, 7 элементов данных: на 3 последних данных, он будет показывать только пункт 7, а не пытаться показать nonexistant пункт 8 и 9.

http://jsfiddle.net/4LhN9/68/

EDIT: Обновлено использовать нг-если & угловой 1. 2,12

+0

Это на самом деле довольно умное решение.Но как бы вы справились с тем случаем, когда длина набора данных не делится на 3? Например, скажем, что вы показывали изображения ... $ index + 0 в последней строке указывает на URL-адрес img, но +1 и +2 пустые. –

+0

Выяснил это. Просто сделайте ng-show = "! (($ Index + x)> (art.length-1))" на img, где x равно 0, 1, 2 соответственно. Угловой настолько гладкий. –

+0

Это великолепно. @andy добавьте идею ng-show rob's, здесь и к вашей скрипке! –

16

Переезд от the more easy answer. Мне не нравится исходное решение из-за пустых элементов dom, которые он производит. Это для 3 divs за строку.

<div ng-controller="ModulesCtrl"> 
    <div class="row" ng-repeat="i in fields.range()"> 
     <div class="span4" ng-repeat="field in fields.slice(i,i+3)"> 
      <h2>{{field}}</h2> 
     </div> 
    </div> 
</div> 

В функции FieldsCtrl ($ сфера):

$scope.fields.range = function() { 
    var range = []; 
    for(var i = 0; i < $scope.fields.length; i = i + 3) 
     range.push(i); 
    return range; 
} 

Если вы знаете fields.length вы можете вместо fields.range() используйте [0,3,6,9] и т.д.

+0

Это сработало для меня! –

2

Чтобы сохранить вид логику из контроллера и имеет более многоразовое решение, вы можете создать собственный фильтр, который разбивает массив на группы строк:

angular.module('app').filter('group', function() { 
    /** 
    * splits an array into groups of the given size 
    * e.g. ([1, 2, 3, 4, 5], 2) -> [[1, 2], [3, 4], [5]] 
    */ 
    return function(array, groupSize) { 
     return _.groupBy(array, function(val, index) { 
      return Math.floor(index/groupSize); 
     }); 
    }; 
}); 

А в представлении:

<div class="row" ng-repeat="group in projects | group:3"> 
    <div class="span4" ng-repeat="project in group"> 
     {{project}} 
    </div> 
</div> 

Для включения в час вы можете использовать нг-повторить начальную и конечную точки:

<div class="row" ng-repeat-start="group in projects | group:3"> 
    <div class="span4" ng-repeat="project in group"> 
     {{project}} 
    </div> 
</div> 
<hr ng-repeat-end /> 
+0

Мне это нравится в теории. На практике, однако, он выдает исключение '10 $ digest() iterations reach' exception. [См. Эту скрипку.] (Http://jsfiddle.net/eVWw5/5/) – roufamatic

+0

Спасибо roufamatic. Я просмотрел его и обнаружил, что ng-repeat использует $ watchCollection для проверки изменений. Поскольку $ watchCollection делает неглубокое сравнение содержимого массива, а мой фильтр «group» возвращает новый набор массивов каждый раз, когда его вызываемый, угловой считает массив постоянно меняющимся. Работа вокруг состоит в том, чтобы инициализировать сгруппированный массив перед ng-repeat вместо использования фильтра, используя ng-init или в контроллере. Но тогда он теряет элегантность. – WearyMonkey

2

ng-repeat-start and ng-repeat-end end points кажется удобным способом для достижения этой:

Какие приводит к простому коду

<div ng-controller="MyCtrl"> 
    <div ng-repeat-start="project in projects"> 
     <span> 
      <div class="row"> 
       <h3 class="span4">{{project}}</h3> 
      </div 
     </span> 
    </div> 
    <hr ng-repeat-end ng-if="($index + 1) % 3 == 0" /> 
</div> 

См. это jsfiddle

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