Angular ng-repeat는 3 개 또는 4 개의 열마다 부트 스트랩 행을 추가합니다.


111

3 열마다 부트 스트랩 행 클래스를 주입하는 올바른 패턴을 찾고 있습니다. cols에는 고정 높이가 없기 때문에 필요합니다 (고정하고 싶지 않습니다). 그래서 내 디자인이 깨집니다!

내 코드는 다음과 같습니다.

<div ng-repeat="product in products">
    <div ng-if="$index % 3 == 0" class="row">
        <div class="col-sm-4" >
            ...
        </div>
    </div>
</div>

그러나 각 행에 하나의 제품 만 표시됩니다. 최종 결과로 원하는 것은 다음과 같습니다.

<div class="row">
    <div class="col-sm4"> ... </div>
    <div class="col-sm4"> ... </div>
    <div class="col-sm4"> ... </div>
</div>
<div class="row">
    <div class="col-sm4"> ... </div>
    <div class="col-sm4"> ... </div>
    <div class="col-sm4"> ... </div>
</div>

ng-repeat 패턴으로 만이 작업을 수행 할 수 있습니까 (지시문 또는 컨트롤러 없음)? 워드 프로세서 와 겨 반복 엔드 반복 시작 겨 소개합니다하지만 난이 사용 사례입니다 사용하는 방법을 알아낼 수 없습니다! 나는 이것이 우리가 부트 스트랩 템플릿에서 자주 사용하는 것이라고 느낍니다! ? 감사


디자인에 맞는 방식으로 데이터를 모델링해야한다고 생각합니다. 행과 열을 표현하는 다차원 배열 또는 객체 여야합니다. 그런 다음 행을 반복하고 조건부 클래스 "ng-class"지시문과 내부 행을 사용해야합니다. 그런 다음 열을 반복해야합니다.
antanas_sepikas 2014

흥미롭고 확실히 작동하는 솔루션이지만 3 개가 아닌 4 개의 제품을 한 행에 표시하고 싶은 날, 데이터 구조를 수정해야합니다. 순수 디스플레이 기능의 "범위"에
머무르는 것이 좋습니다

나는 Ariel 답변에서와 같이 청크에서 반복적으로 반복해야합니다 . 이 게시물 stackoverflow.com/questions/18564888/… 유용 할 수도 있습니다 .
antanas_sepikas 2014

저는 이것이 정확히 당신이 찾고있는 것이라고 생각합니다 : stackoverflow.com/a/30426750/1943442
user1943442

답변:


164

가장 많이 득표 한 답변은 효과적이지만 제가 각도 방식이라고 생각하는 것이 아니며이 상황을 처리하기위한 부트 스트랩 자체 클래스를 사용하지도 않습니다. @claies가 언급했듯이 .clearfix클래스는 이러한 상황을위한 것입니다. 제 생각에 가장 깨끗한 구현은 다음과 같습니다.

<div class="row">
    <div ng-repeat="product in products">
        <div class="clearfix" ng-if="$index % 3 == 0"></div>
        <div class="col-sm-4">
            <h2>{{product.title}}</h2>
        </div>
    </div>
</div>

이 구조는 제품 배열의 복잡한 인덱싱을 방지하고 깨끗한 점 표기법을 허용하며 의도 된 목적을 위해 clearfix 클래스를 사용합니다.


6
이것은 좋은 생각이지만 flexbox를 사용하는 데 관심이 있다면 각 상자 / div의 높이를 같게하기 위해 행 내부의 div가 아닌 행에 이것을 사용해야합니다. Clearfix는 훌륭하지만 모든 것을 정렬하는 데 도움이되지 않습니다.
코드 컨테이너

3
이것이 제가 선호하는 대답입니다. 매우 깨끗하고 쉽습니다.
하인릭

1
내 구현에도 잘 작동합니다! :)
Will Strohl

1
훌륭합니다 ... 이것은 승인 된 답변으로 투표되어야합니다!
Velu

3
이 완벽한 해답
딥우

148

조금 늦었지만 여전히 누군가를 도울 수 있습니다. 나는 이렇게했다 :

<div ng-repeat="product in products" ng-if="$index % 3 == 0" class="row">
    <div class="col-xs-4">{{products[$index]}}</div>
    <div class="col-xs-4" ng-if="products.length > ($index + 1)">{{products[$index + 1]}}</div>
    <div class="col-xs-4" ng-if="products.length > ($index + 2)">{{products[$index + 2]}}</div>
</div>

jsfiddle


3
실제로 많은 도움이되었습니다 !! 감사.
SupimpaAllTheWay

구현하기 정말 쉽습니다! 감사!
Manas Bajaj 2015 년

나를 많이 도왔다. 감사!
Ahmad Ajmi 2015-06-11

17
훌륭한 솔루션이지만 $ index + 1 및 $ index +2가 배열 경계를 넘 었는지 여부는 확인하지 않습니다. 마지막 두 div의는 필요 ng-if="$index+1 < products.length"ng-if="$index+2 < products.length"
무스타파 Ozturk에게

키, 값 쌍에 대해이 작업을 수행 할 수 있습니까? 다음 키를 받고 있습니까? $ index + 1을받는 대신
bpbhat77

25

이 솔루션은 이미 여기에있는 솔루션 보다 훨씬 간단하며 다양한 장치 너비에 대해 다른 열 너비를 허용합니다.

<div class="row">
    <div ng-repeat="image in images">
        <div class="col-xs-6 col-sm-4 col-md-3 col-lg-2">
            ... your content here ...
        </div>
        <div class="clearfix visible-lg" ng-if="($index + 1) % 6 == 0"></div>
        <div class="clearfix visible-md" ng-if="($index + 1) % 4 == 0"></div>
        <div class="clearfix visible-sm" ng-if="($index + 1) % 3 == 0"></div>
        <div class="clearfix visible-xs" ng-if="($index + 1) % 2 == 0"></div>
    </div>
</div>

점을 유의 % 6부분이 결과 열 수를 동일하게되어있다. 따라서 열 요소에 클래스가있는 경우col-lg-2 가있는 경우 6 개의 열이 있으므로 ... % 6.

이 기술 (제외 ng-if)은 실제로 여기에 문서화되어 있습니다. Bootstrap docs


1
제 생각에는 이것이 최선의 해결책입니다.
user216661

부트 스트랩을 처음 사용하는 경우 행을 정의 할 필요가 없다는 사실을 간과하기 쉽습니다. 이것은 완벽하게 작동했으며 Duncan 솔루션의 약간 더 완전한 버전입니다.
phosplait

이것이 바로 제가 찾던 것입니다.
Hinrich

@phosplait Duncan에 비해 이것의 장점은 무엇입니까?
Jeppe

17

달성하고자하는 것이 유용 할 수 있지만, 훨씬 더 간단하게 간과 할 수있는 또 다른 옵션이 있습니다.

맞습니다. 높이가 고정되지 않은 열이있을 때 Bootstrap 테이블이 이상하게 작동합니다. 그러나이 문제를 해결하고 반응 형 재설정을 수행하기 위해 만들어진 부트 스트랩 클래스가 있습니다.

<div class="clearfix"></div>플로트가 재설정되고 열이 올바른 위치로 돌아갈 수 있도록 각 새 행의 시작 전에 빈 공간을 만듭니다 .

여기에 bootply가 있습니다.


이것은 각 .row가 부트 스트랩에 대해 갖는 마이너스 15px의 여백을 해결하지 못합니다.
Logus

이것은 flex열을 같은 높이로 만들기 위해 작동합니까 ?
Alisson 2016-08-09

16

제안 해주셔서 감사합니다.

완전한 설명을 위해 가자 :

  • 기본적으로 AngularJS http get 쿼리는 객체를 반환합니다.

  • 따라서 @Ariel Array.prototype.chunk 함수를 사용하려면 먼저 객체를 배열로 변환해야합니다.

  • 그런 다음 컨트롤러 에서 청크 기능을 사용하려면 ng-repeat에 직접 사용하면 infdig 오류가 발생 합니다. 최종 컨트롤러는 다음과 같습니다.

    // Initialize products to empty list
    $scope.products = [];
    
    // Load products from config file
    $resource("/json/shoppinglist.json").get(function (data_object)
    {
        // Transform object into array
        var data_array =[];
        for( var i in data_object ) {
            if (typeof data_object[i] === 'object' && data_object[i].hasOwnProperty("name")){
                data_array.push(data_object[i]);
            }
        }
        // Chunk Array and apply scope
        $scope.products = data_array.chunk(3);
    });

그리고 HTML은 다음과 같습니다.

<div class="row" ng-repeat="productrow in products">

    <div class="col-sm-4" ng-repeat="product in productrow">

반면에 JSON 파일에서 {} 객체 대신 배열 []을 직접 반환하기로 결정했습니다. 이렇게하면 컨트롤러는 다음과 같이됩니다 (특정 구문 isArray : true ).

    // Initialize products to empty list 
    $scope.products = [];

    // Load products from config file
    $resource("/json/shoppinglist.json").query({method:'GET', isArray:true}, function (data_array)
    {
        $scope.products = data_array.chunk(3);
    });

HTML은 위와 동일합니다.

최적화

서스펜스의 마지막 질문은 청크 함수를 사용하여 자바 스크립트 배열을 확장하지 않고 100 % AngularJS로 만드는 방법입니다. . 궁금해 ;)

ANDREW의 솔루션

@Andrew 덕분에 이제 우리는 3 개 (또는 숫자에 관계없이) 요소마다 부트 스트랩 clearfix 클래스를 추가하면 다른 블록의 높이에서 표시 문제가 수정된다는 것을 알게되었습니다.

따라서 HTML은 다음과 같습니다.

<div class="row">

    <div ng-repeat="product in products">

        <div ng-if="$index % 3 == 0" class="clearfix"></div>

        <div class="col-sm-4"> My product descrition with {{product.property}}

그리고 컨트롤러는 제거 된 덩어리 기능으로 매우 부드럽습니다 .

// Initialize products to empty list 
        $scope.products = [];

        // Load products from config file
        $resource("/json/shoppinglist.json").query({method:'GET', isArray:true}, function (data_array)
        {
            //$scope.products = data_array.chunk(3);
            $scope.products = data_array;
        });

7

지시 없이도 할 수 있지만 최선의 방법인지 모르겠습니다. 이렇게하려면 테이블에 표시하려는 데이터에서 배열 배열을 만들고 그 후에 2ng-repeat를 사용하여 배열을 반복해야합니다.

디스플레이 용 배열을 만들려면 제품과 같이이 함수를 사용하십시오 .chunk (3)

Array.prototype.chunk = function(chunkSize) {
    var array=this;
    return [].concat.apply([],
        array.map(function(elem,i) {
            return i%chunkSize ? [] : [array.slice(i,i+chunkSize)];
        })
    );
}

그런 다음 2ng-repeat를 사용하여 이와 같은 작업을 수행하십시오.

<div class="row" ng-repeat="row in products.chunk(3)">
  <div class="col-sm4" ng-repeat="item in row">
    {{item}}
  </div>
</div>

7

Alpar 솔루션을 기반으로 애니메이션 된 ng-repeat가있는 템플릿 만 사용합니다. 전체 및 부분적으로 비어있는 행 모두에서 작동합니다.

<div data-ng-app="" data-ng-init="products='soda','beer','water','milk','wine']" class="container">
    <div ng-repeat="product in products" ng-if="$index % 3 == 0" class="row">
        <div class="col-xs-4" 
            ng-repeat="product in products.slice($index, ($index+3 > products.length ? 
            products.length : $index+3))"> {{product}}</div>
    </div>
</div>

JSFiddle


5

방금 템플릿에서만 작동하는 솔루션을 만들었습니다. 해결책은

    <span ng-repeat="gettingParentIndex in products">
        <div class="row" ng-if="$index<products.length/2+1">    <!-- 2 columns -->
            <span ng-repeat="product in products">
                <div class="col-sm-6" ng-if="$index>=2*$parent.$index && $index <= 2*($parent.$index+1)-1"> <!-- 2 columns -->
                    {{product.foo}}
                </div>
            </span>
        </div>
    </span>

포인트는 데이터를 두 번 사용하고 하나는 외부 루프 용입니다. 추가 범위 태그는 그대로 유지되지만 트레이드 오프 방식에 따라 다릅니다.

3 열 레이아웃이면 다음과 같을 것입니다.

    <span ng-repeat="gettingParentIndex in products">
        <div class="row" ng-if="$index<products.length/3+1">    <!-- 3 columns -->
            <span ng-repeat="product in products">
                <div class="col-sm-4" ng-if="$index>=3*$parent.$index && $index <= 3*($parent.$index+1)-1"> <!-- 3 columns -->
                    {{product.foo}}
                </div>
            </span>
        </div>
    </span>

솔직히 원했어

$index<Math.ceil(products.length/3)

작동하지 않았지만.


이 솔루션을 사용하여 각 행에 2 개의 요소를 구현했습니다. 예를 들어, 목록에 5 개의 요소가 있으므로 i가 가져야하는 출력은 처음 2 개 행에 2 개 요소 / 열이 있고 마지막 행에 1 개 열이있는 3 개 행입니다. 문제는 마지막 2 개 행이 비어있는 상태로 여기에 5 개 행이 있다는 것입니다. 이 문제를 해결하는 방법이 궁금하십니까? 감사합니다
Maverick Riz

@MaverickAzy 시도해 주셔서 감사합니다. 해당 요소의 높이가 다르면 제대로 작동하지 않는 문제가 있다는 것을 알고 있습니다.
wataru

요소의 높이는 실제로 동일합니다. 문제는 3 개의 행만 가져와야하지만 마지막 2 개의 빈 행으로 5 개의 행을 가져야한다는 것입니다. products.length가 5이면 5 / 2 + 1 =? 이 논리는 클래스 행의 2 행에서 명확하지 않습니다.
Maverick Riz

@MaverickAzy 빈 행은있는 그대로 생성되어야합니다. 레이아웃이 엉망입니까?
wataru

아니요, 레이아웃을 엉망으로 만들지 않습니다. 유일한 관심은 빈 행에 관한 것입니다. 도와 주시면 정말 감사합니다. 감사합니다
Maverick Riz

5

@Duncan 답변 에 대한 또 다른 약간의 개선 사항 과 clearfix 요소를 기반으로 한 다른 답변입니다. 콘텐츠를 클릭 할 수있게하려면 z-index> 0 이 필요 하거나 clearfix가 콘텐츠를 겹치고 클릭을 처리합니다.

다음은 작동하지 않는 예입니다 (커서 포인터를 볼 수없고 클릭해도 아무 작업도 수행되지 않음).

<div class="row">
    <div ng-repeat="product in products">
        <div class="clearfix" ng-if="$index % 3 == 0"></div>
        <div class="col-sm-4" style="cursor: pointer" ng-click="doSomething()">
            <h2>{{product.title}}</h2>
        </div>
    </div>
</div>

이것이 고정 된 반면 :

<div class="row">
    <div ng-repeat-start="product in products" class="clearfix" ng-if="$index % 3 == 0"></div>
    <div ng-repeat-end class="col-sm-4" style="cursor: pointer; z-index: 1" ng-click="doSomething()">
            <h2>{{product.title}}</h2>
    </div>
</div>

z-index: 1콘텐츠가 clearfix 위로 올라가도록 추가 했으며 z-index가 작동하지 않기 때문에 대신 ng-repeat-startand ng-repeat-end(AngularJS 1.2에서 사용 가능)를 사용하여 컨테이너 div를 제거 했습니다.

도움이 되었기를 바랍니다!

최신 정보

플 런커 : http://plnkr.co/edit/4w5wZj


이것은 flex열을 같은 높이로 만들기 위해 행에서 작동합니까 ?
Alisson

질문을 이해했는지 잘 모르겠습니다. 이 코드가 수행하는 작업을 보여주는 빠른 플 런커 입니다 : plnkr.co/edit/4w5wZj?p=preview . 즉, clearfix는 제목의 두 번째 줄을 올바르게 정렬합니다. 모두 동일한 지점에서 시작 하지만 여전히 동일한 높이를 갖지 않습니다 (배경색 덕분에 볼 수 있음). clearfix 클래스를 삭제하여 기본 동작이 무엇인지 확인하십시오. 나는 flexbox를 한두 번만 사용 했지만 CSS 속성이 많고 검색하는 것을 찾을 수 있다고 확신합니다.
McGiogen

부트 스트랩은 동일한 행의 모든 ​​열을 만들어 가장 높은 열의 동일한 높이를 얻는 방법에 대한 예제 를 제공 합니다 . 나는 이것을 사용해야했다. 문제는 12 개 이상의 열이있을 때 새 줄로 줄 바꿈 할 수있는 기능이 없어서 수동으로 새 행을 만들어야한다는 것입니다. 조금 더 조사한 후에 해결책을 얻고 여기에 답변으로 게시 할 수 있었지만 이것이 최선인지는 모르겠습니다. 어쨌든 감사합니다. 귀하의 답변이 도움이되었습니다!
Alisson 2016-08-10

이 예제를 처음 본 것은 정말 유용합니다! 기꺼이 도와 드리겠습니다.
McGiogen

4

나는 ng-class를 사용하여 이것을 해결했습니다.

<div ng-repeat="item in items">
    <div ng-class="{ 'row': ($index + 1) % 4 == 0 }">
        <div class="col-md-3">
            {{item.name}}
        </div>
    </div>
</div>

2

클래스를 적용하는 가장 좋은 방법은 ng-class를 사용하는 것이며, 어떤 조건에 따라 클래스를 적용하는 데 사용할 수 있습니다.

<div ng-repeat="product in products">
   <div ng-class="getRowClass($index)">
       <div class="col-sm-4" >
           <!-- your code -->
       </div>
   </div>

그런 다음 컨트롤러에서

$scope.getRowClass = function(index){
    if(index%3 == 0){
     return "row";
    }
}

2

여기에 많은 답변과 제안을 결합한 후 이것이 저의 최종 답변입니다.는 잘 작동 flex하여 동일한 높이의 열을 만들고 마지막 색인도 확인하며 내부 HTML을 반복 할 필요가 없습니다. 사용하지 않습니다 clearfix.

<div ng-repeat="prod in productsFiltered=(products | filter:myInputFilter)" ng-if="$index % 3 == 0" class="row row-eq-height">
    <div ng-repeat="i in [0, 1, 2]" ng-init="product = productsFiltered[$parent.$parent.$index + i]"  ng-if="$parent.$index + i < productsFiltered.length" class="col-xs-4">
        <div class="col-xs-12">{{ product.name }}</div>
    </div>
</div>

다음과 같이 출력됩니다.

<div class="row row-eq-height">
    <div class="col-xs-4">
        <div class="col-xs-12">
            Product Name
        </div>
    </div>
    <div class="col-xs-4">
        <div class="col-xs-12">
            Product Name
        </div>
    </div>
    <div class="col-xs-4">
        <div class="col-xs-12">
            Product Name
        </div>
    </div>
</div>
<div class="row row-eq-height">
    <div class="col-xs-4">
        <div class="col-xs-12">
            Product Name
        </div>
    </div>
    <div class="col-xs-4">
        <div class="col-xs-12">
            Product Name
        </div>
    </div>
    <div class="col-xs-4">
        <div class="col-xs-12">
            Product Name
        </div>
    </div>
</div>

1

@alpar의 솔루션에서 약간의 수정

<div data-ng-app="" data-ng-init="products=['A','B','C','D','E','F', 'G','H','I','J','K','L']" class="container">
    <div ng-repeat="product in products" ng-if="$index % 6 == 0" class="row">
        <div class="col-xs-2" ng-repeat="idx in [0,1,2,3,4,5]">
        {{products[idx+$parent.$index]}} <!-- When this HTML is Big it's useful approach -->
        </div>
    </div>
</div>

jsfiddle


0

이것은 나를 위해 일했으며 접합이나 아무것도 필요하지 않았습니다.

HTML

<div class="row" ng-repeat="row in rows() track by $index">
    <div class="col-md-3" ng-repeat="item in items" ng-if="indexInRange($index,$parent.$index)"></div>
</div>

자바 스크립트

var columnsPerRow = 4;
$scope.rows = function() {
  return new Array(columnsPerRow);
};
$scope.indexInRange = function(columnIndex,rowIndex) {
  return columnIndex >= (rowIndex * columnsPerRow) && columnIndex < (rowIndex * columnsPerRow) + columnsPerRow;
};

0

Born Solutions 최고의 솔루션, 요구 사항을 충족하는 데 약간의 시간이 필요합니다. 다른 반응 형 솔루션을 사용하고 약간 변경했습니다.

<div ng-repeat="post in posts">
    <div class="vechicle-single col-lg-4 col-md-6 col-sm-12 col-xs-12">
    </div>
    <div class="clearfix visible-lg" ng-if="($index + 1) % 3 == 0"></div>
    <div class="clearfix visible-md" ng-if="($index + 1) % 2 == 0"></div>
    <div class="clearfix visible-sm" ng-if="($index + 1) % 1 == 0"></div>
    <div class="clearfix visible-xs" ng-if="($index + 1) % 1 == 0"></div>
</div>

0

Alpar의 답변을 바탕으로 단일 항목 목록을 여러 컨테이너 (행, 열, 버킷 등)로 분할하는보다 일반적인 방법은 다음과 같습니다.

<div class="row" ng-repeat="row in [0,1,2]">
  <div class="col" ng-repeat="item in $ctrl.items" ng-if="$index % 3 == row">
    <span>{{item.name}}</span>
  </div>
</div> 

10 개 항목 목록에 대해 다음을 생성합니다.

<div class="row">
  <div class="col"><span>Item 1</span></div>
  <div class="col"><span>Item 4</span></div>
  <div class="col"><span>Item 7</span></div>
  <div class="col"><span>Item 10</span></div>
</div> 
<div class="row">
  <div class="col"><span>Item 2</span></div>
  <div class="col"><span>Item 5</span></div>
  <div class="col"><span>Item 8</span></div>
</div> 
<div class="row">
  <div class="col"><span>Item 3</span></div>
  <div class="col"><span>Item 6</span></div>
  <div class="col"><span>Item 9</span></div>
</div> 

컨테이너 수는 컨트롤러 함수로 빠르게 코딩 할 수 있습니다.

JS (ES6)

$scope.rowList = function(rows) {
  return Array(rows).fill().map((x,i)=>i);
}
$scope.rows = 2;

HTML

<div class="row" ng-repeat="row in rowList(rows)">
  <div ng-repeat="item in $ctrl.items" ng-if="$index % rows == row">
    ...

이 접근 방식은 <span>{{item.name}}</span>소스 템플릿에서 항목 마크 업 ( 이 경우)을 복제하는 것을 방지 합니다. 단순한 범위에 대한 큰 승리는 아니지만 더 복잡한 DOM 구조 (내가 보유한)의 경우 템플릿을 DRY로 유지하는 데 도움이됩니다.


0

2019 업데이트-부트 스트랩 4

부트 스트랩 3 중고 플로트 때문에 필요한 clearfix 재설정을 마다 N (3, 4) 열 ( .col-*하여).row 고르지 않게 래핑되는 것을 방지하기 위해의 .

이제 Bootstrap 4에서 flexbox를 사용 하므로 더 이상 별도의 .row태그로 열을 래핑 하거나 추가 div를 삽입하여 열이 n 마다 래핑되도록 할 필요가 없습니다. 열 .

단일 컨테이너 에서 모든 열을 간단히 반복 할 수 있습니다 .row.

예를 들어 각 시각적 행의 3 개 열은 다음과 같습니다.

<div class="row">
     <div class="col-4">...</div>
     <div class="col-4">...</div>
     <div class="col-4">...</div>
     <div class="col-4">...</div>
     <div class="col-4">...</div>
     <div class="col-4">...</div>
     <div class="col-4">...</div>
     (...repeat for number of items)
</div>

따라서 Bootstrap의 경우 ng-repeat는 간단합니다.

  <div class="row">
      <div class="col-4" ng-repeat="item in items">
          ... {{ item }}
      </div>
  </div>

데모 : https://www.codeply.com/go/Z3IjLRsJXX


0

저는 부 스트랩 만 사용했습니다. 행과 열의 위치에 매우주의해야합니다. 여기 제 예가 있습니다.

<section>
<div class="container">
        <div ng-app="myApp">
        
                <div ng-controller="SubregionController">
                    <div class="row text-center">
                        <div class="col-md-4" ng-repeat="post in posts">
                            <div >
                                <div>{{post.title}}</div>
                            </div>
                        </div>
                    
                    </div>
                </div>        
        </div>
    </div>
</div> 

</section>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.