web-dev-qa-db-ja.com

グリッド作成用のangle.js ng-repeat

bootstrap 3とangularjsを使用してグリッドを作成しようとしています。

私が作成しようとしているグリッドはこれで、ng-repeatを使用して繰り返されます。

<div class="row">
 <div class="col-md-4">item</div>
 <div class="col-md-4">item</div>
 <div class="col-md-4">item</div>
</div>

ng-if($index % 3 == 0)を使用して行を追加しようとしましたが、これは正しく機能していないようです。どんな提案でも素晴らしいでしょう!

ありがとうございました!

編集:これは私が働いて終わったコードです:

<div ng-repeat="item in items">
  <div ng-class="row|($index % 3 == 0)">
    <ng-include class="col-sm-4" src="'views/items/item'"></ng-include> 
  </div>
</div>
45
dzm

これは古い答えです!

Angularを書いたときはまだ少しばかりでした。代わりに使用することをお勧めするShivamからのより良い答えがあります。とても良いことです。

元の回答

繰り返しているリストは、コントローラーのリストのリスト(それぞれ3つのアイテム)にいつでも分割できます。リストは次のとおりです。

$scope.split_items = [['item1', 'item2', 'item3'], ['item4', 'item5', 'item6']];

そして、次のように繰り返します。

<div ng-repeat="items in split_items" class="row">
    <div ng-repeat="item in items" class="col-md-4">
        item
    </div>
</div>

より良い方法があるかどうかはわかりません。私はng-ifとng-switchをいじってみましたが、動作させることはできませんでした。

22
Erik Honn

受け入れられた答えは明らかな解決策ですが、プレゼンテーションロジックは、コントローラーやモデルではなく、表示されたままでなければなりません。また、OPのソリューションを機能させることができませんでした。

アイテムのフラットリスト(配列)がある場合にグリッドシステムを作成する2つの方法を次に示します。アイテムリストがアルファベットであるとします。

ここにプランカー

$scope.alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 
                   'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];

方法1:

これは純粋なangularソリューションです。

<div class="row" ng-repeat="letter in alphabet track by $index" ng-if="$index % 4 == 0">
  <div class="col-xs-3 letter-box" 
       ng-repeat="i in [$index, $index + 1, $index + 2, $index + 3]" 
       ng-if="alphabet[i] != null">
    <div>Letter {{i + 1}} is: <b> {{alphabet[i]}}</b></div>
  </div>
</div>

外側のループは、4回の反復ごとに実行され、行を作成します。外側のループを実行するたびに、内側のループが4回繰り返され、列が作成されます。配列に要素があるかどうかに関係なく、内側のループは4回実行されるため、ng-ifは、内側のループが完了する前に配列が終了した場合に、余分な列が作成されないようにします。

方法2:

これははるかに簡単なソリューションですが、 angular-filter ライブラリが必要です。

<div class="row" ng-repeat="letters in alphabet | chunkBy:4">
  <div class="col-xs-3 letter-box" ng-repeat="letter in letters" >
    <div>Letter {{$index + 1}} is: <b> {{letter}}</b></div>
  </div>
</div>

外側のループは、「行」に対応する4文字のグループを作成します

[['A', 'B', 'C', 'D'], ['E', 'F', 'G', 'H'], ... ]

内側のループはグループを反復処理し、列を作成します。

注:方法2では、外部ループの反復ごとにフィルターの評価が必要になる可能性があるため、方法2は巨大なデータセットに対してあまりうまくスケーリングできない場合があります。

72
CodeExpress

コントローラ内で配列をNのサブ配列に単純にチャンクできます。サンプルコード:

var array = ['A','B','C','D','E','F','G','H'];

var chunk = function(arr, size) {
   var newArr = [];
      for (var i=0; i<arr.length; i+=size) {
          newArr.Push(arr.slice(i, i+size));
      }
   return newArr;
};

$scope.array = chunk(array, 2);

これで、*。htmlファイルにng-repeatからarrayまで

<div class="row" ng-repeat="chunk in array">
    <div class="col-md-6" ng-repeat="item in chunk">
         {{item}}
    </div>
</div>

私のためのそのトレーニング:)幸運を!

9
markkillah

ng-repeat-startおよびng-repeat-endの使用

<div class="row">
    <div ng-repeat-start="item in items track by $index" class="col-sm-4">
      {{item}}
    </div>
    <div ng-repeat-end ng-if="($index+1) % 3 == 0" class="clearfix"></div>
</div>

。visible-*クラスを使用すると、さまざまなメディアクエリに簡単に適応できます

<div class="row">
    <div ng-repeat-start="item in items track by $index" class="col-lg-2 col-md-4 col-sm-6">
      {{item}}
    </div>
    <div ng-repeat-end>
        <div class="clearfix visible-lg-block" ng-if="($index+1) % 6 == 0"></div>
        <div class="clearfix visible-md-block" ng-if="($index+1) % 3 == 0"></div>
        <div class="clearfix visible-sm-block" ng-if="($index+1) % 2 == 0"></div>
    </div>
</div> 

メインの繰り返しブロックの外に行管理ロジックがあることは明確で簡潔です。関心事の分離 :-)

3
Guillaume Morin

以下のソリューションはrow divを持つグリッドルールに従わないと言うかもしれませんが、別のソリューションはrowクラスを削除する(またはng-repeatの外部で使用する) )代わりにclearfixクラスを使用します。

<div class="col-md-12">
  <div ng-repeat="item in items">
    <div ng-class="{'clearfix': $index%3 === 0}"></div>
    <div class="col-md-4">{{item}}</div>
  </div>
</div>

私が見る限り、これはrowクラスとほぼ同じように見えますが、考えられる欠陥についてコメントしてください(上記で言及したものを除く)。

3
user4776684

少し遅い答えですが、私はこれを使用し、いくつかの場合にはそれが良いと信じています。これには Angular Filter パッケージとそのChunkByフィルターを使用できます。このパッケージは、この単一のタスクには大きな負担になりますが、さまざまなタスク用に他の便利なフィルターがあります。私が使用したコードは次のようなものです。

<div class="row mar-t2" ng-repeat="items in posts | chunkBy:3">
    <div class="col-md-4" ng-repeat="post in items">
        <img ng-src="{{post.featured_url}}" class="img-responsive" />
        <a ng-click="modalPop(post.id)"><h1 class="s04-bas2">{{post.title.rendered}}</h1></a>
        <div class="s04-spotbox2" ng-bind-html="post.excerpt.rendered"></div>
    </div>
</div>
2
heirenton

これは動作するはずです

<div ng-repeat="item in items">
    <div ng-class="{row : ($index % 3 == 0)}">
        ... 
    </div>
</div>
0
marcinowski

ngInit を使用して、少し異なる方法を取りました。 ngInitのドキュメントには次のように記載されているため、これが適切なソリューションであるかどうかはわかりません

NgInitの唯一の適切な使用は、以下のデモに見られるように、ngRepeatの特別なプロパティをエイリアスするためです。この場合のほかに、ngInitではなくコントローラーを使用して、スコープの値を初期化する必要があります。

これがそのケースに該当するかどうかはわかりませんが、テンプレートデザイナーがブートストラップを使用して行ごとにグループ化できるように、コントローラーからこの機能を移動したかったのです。私はまだこれをバインディングについてテストしていませんが、$ indexで追跡しているので、それが問題になるとは思いません。

フィードバックを聞きたいです。

1つの引数(各行のアイテム数のカウント)をとる "splitrow"というフィルターを作成しました

.filter('splitrow', function(){
    return function (input, count){
        var out = [];
            if(typeof input === "object"){
                for (var i=0, j=input.length; i < j; i+=count) {
                    out.Push(input.slice(i, i+count));
                }
            }
        return out;
    }
});

ビューテンプレート内で、bootstrap=行を次のように編成しました。

<div ng-init="rows = (items|splitrow:3)">
    <div ng-repeat='row in rows' class="row">
        <div ng-repeat="item in row track by $index" class="col-md-4">
            {{item.property}}
        </div>
    </div>
</div>

@ Shivam's Plunkerを編集して、この方法を使用しました。外部ライブラリは必要ありません。

Plunker

0
user1943442

私のソリューションは、@ CodeExpressのものと非常に似ています。配列の項目をグループ化するbatchフィルターを作成しました(名前は Twigの対応するフィルター から借用しています)。単純にするために、連想配列は処理しません。

_angular.module('myapp.filters', [])
    .filter('batch', function() {
        var cacheInputs = [];
        var cacheResults = [];

        return function(input, size) {
            var index = cacheInputs.indexOf(input);

            if (index !== -1) {
                return cacheResults[index];
            }

            var result = [];

            for (i = 0; i < input.length; i += size) {
                result.Push(input.slice(i, i + size));
            }

            cacheInputs.Push(input);
            cacheResults.Push(result);

            return result;
        }
    })
;
_

次のように使用できます。

_<div ng-repeat="itemsRow in items|batch:3">
    <div class="row">
        <div ng-repeat="item in itemsRow">
            <div class="col-md-4">
                ...
            </div>
        </div>
    </div>
</div>
_

10 $digest() iterations reached. Aborting!エラーを回避するために、フィルター結果はキャッシュされます。

0
Michaël Perrin

@CodeExpressの純粋なangularソリューションのAngular2バージョン。

alphabet: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 
                   'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];

<div *ngIf='alphabet && alphabet.length'>
    <div *ngFor='#letter of alphabet; #i = index' >
        <div class="row" *ngIf='i % 4 == 0'>
            <div class="col-md-3" *ngFor='#n of [i,i+1,i+2,i+3]'>
                {{alphabet[n]}}
            </div>
        </div>
    </div>
</div>
0
Alex Logan