wake-up-neo.com

Angular ng-repeat fügt alle 3 oder 4 Cols eine Bootstrap-Reihe hinzu

Ich bin auf der Suche nach dem richtigen Muster, um alle 3 Spalten eine Bootstrap-Row-Klasse einzufügen. Ich brauche das, weil cols keine feste Höhe hat (und ich möchte keine reparieren), also bricht es mein Design! 

Hier ist mein Code:

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

In jeder Zeile wird jedoch nur ein Produkt angezeigt. Was ich als Endergebnis möchte, ist:

<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>

Kann ich dies nur mit ng-repeat Muster (ohne Direktive oder Controller) erreichen? Die docs Einführung ng-repeat-start und ng-repeat-end, aber ich kann nicht herausfinden, wie man es benutzt, ist dieser Anwendungsfall! Ich denke, das ist etwas, was wir oft beim Bootstrap-Templating verwenden! ? Vielen Dank

108
hugsbrugs

Die am besten gewählte Antwort ist zwar effektiv, aber nicht das, was ich als kantig empfinden würde, und verwendet auch nicht die eigenen Klassen von Bootstrap, die mit dieser Situation umgehen sollen. Wie in @claies erwähnt, ist die .clearfix-Klasse für solche Situationen gedacht. Meiner Meinung nach sieht die sauberste Implementierung folgendermaßen aus:

<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>

Diese Struktur vermeidet eine unordentliche Indizierung des Produkt-Arrays, ermöglicht eine saubere Punktnotation und verwendet die clearfix-Klasse für den vorgesehenen Zweck.

154
Duncan

Ich weiß, dass es etwas spät ist, aber es könnte trotzdem jemandem helfen. Ich habe es so gemacht:

<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

146
alpar

Okay, diese Lösung ist weit einfacher als die hier bereits vorgestellten und ermöglicht unterschiedliche Spaltenbreiten für unterschiedliche Gerätebreiten.

<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>

Beachten Sie, dass der % 6-Teil der Anzahl der resultierenden Spalten entsprechen soll. Wenn also für das Spaltenelement die Klasse col-lg-2 vorhanden ist, gibt es 6 Spalten. Verwenden Sie also ... % 6.

Diese Technik (mit Ausnahme von ng-if) ist hier tatsächlich dokumentiert: Bootstrap-Dokumente

24
user3638471

Während das, was Sie erreichen möchten, nützlich sein kann, gibt es eine andere Option, die meiner Meinung nach übersehen wird und die viel einfacher ist.

Sie sind richtig, die Bootstrap-Tabellen verhalten sich seltsam, wenn Sie Spalten haben, die keine feste Höhe haben. Es wurde jedoch eine Bootstrap-Klasse erstellt, um dieses Problem zu bekämpfen und responsive resets auszuführen.

erstellen Sie einfach einen leeren <div class="clearfix"></div> vor dem Beginn jeder neuen Zeile, damit die Floats zurückgesetzt werden können und die Spalten an ihre korrekten Positionen zurückkehren.

hier ist ein bootply

17
Claies

Danke für Ihre Vorschläge, Sie haben mich auf den richtigen Weg gebracht!

Lassen Sie uns eine vollständige Erklärung geben:

  • Standardmäßig gibt AngularJS http ein Objekt zurück

  • Wenn Sie also die Funktion @Ariel Array.prototype.chunk verwenden möchten, müssen Sie das Objekt zuerst in ein Array umwandeln.

  • Wenn Sie dann die Chunk-Funktion IN YOUR CONTROLLER verwenden möchten, führt dies zu einem infdig-Fehler . Der Endkontrolleur sieht aus:

    // 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);
    });
    

Und HTML wird zu:

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

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

Auf der anderen Seite entschied ich mich, direkt ein Array [] anstelle eines Objekts {} aus meiner JSON-Datei zurückzugeben. Auf diese Weise wird der Controller (bitte beachten Sie die spezifische Syntax 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 bleibt wie oben. 

OPTIMIERUNG

Die letzte Frage in der Frage ist, wie man es zu 100% AngularJS macht, ohne das Javascript-Array mit Chunk-Funktion zu erweitern. . Ich bin neugierig ;)

ANDREW'S LÖSUNG

Dank @Andrew wissen wir jetzt, dass durch das Hinzufügen einer Bootstrap-Clearfix-Klasse alle drei Elemente (oder welche Zahl auch immer) das Anzeigeproblem aus unterschiedlichen Blockhöhen korrigiert wird.

So wird HTML zu:

<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}}

Und Ihr Controller bleibt mit der Funktion entfernter Chunck ziemlich weich: 

// 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;
        });
16
hugsbrugs

Basierend auf Alpar-Lösung, nur Vorlagen mit anidierter Wiederholgenauigkeit. Funktioniert mit vollen und teilweise leeren Zeilen:

<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

7
Juangui Jordán

Sie können dies auch ohne eine Direktive tun, aber ich bin nicht sicher, ob dies der beste Weg ist ... Um dies zu tun, müssen Sie ein Array eines Arrays aus den Daten erstellen, die in der Tabelle angezeigt werden sollen... Und danach 2 ng verwenden -wiederholen, um das Array zu durchlaufen.

verwenden Sie diese Funktion, um das Array für die Anzeige zu erstellen. products.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)];
        })
    );
}

und dann sowas mit 2 ng-repeat machen

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

Ich habe soeben eine Lösung gemacht, die nur in template funktioniert .. Die Lösung ist

    <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>

Point verwendet Daten zweimal, eine für eine externe Schleife . Zusätzliche Spanne-Tags bleiben erhalten, aber es hängt davon ab, wie Sie handeln.

Wenn es sich um ein 3-Spalten-Layout handelt, wird es ähnlich sein

    <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>

Ehrlich gesagt wollte ich

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

Obwohl es nicht geklappt hat.

5
wataru

Noch eine kleine Verbesserung über @Duncans Antwort und die anderen Antworten basierend auf dem clearfix-Element ..__ Wenn Sie den Inhalt anklickbar machen möchten, benötigen Sie einen z-index> 0 oder Clearfix überlappt den Inhalt und den Klick handhaben.

Dies ist das -Beispiel, das nicht funktioniert (Sie können den Cursor nicht sehen und durch Klicken wird nichts unternommen):

<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>

Während dies der Feste ist:

<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>

Ich habe z-index: 1 hinzugefügt, damit der Inhalt über den Clearfix angehoben wird, und ich habe den Container div mithilfe von ng-repeat-start und ng-repeat-end (verfügbar von AngularJS 1.2) entfernt, da Z-Index nicht funktioniert.

Hoffe das hilft!

Aktualisieren

Plunker: http://plnkr.co/edit/4w5wZj

5
McGiogen

ich löste das mit 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>
4
Josip

Die beste Methode zum Anwenden einer Klasse ist die Verwendung von ng-class. Sie kann verwendet werden, um Klassen basierend auf bestimmten Bedingungen anzuwenden.

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

und dann in Ihrem Controller

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

Kleine Änderung in @alpar's Lösung

<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

1
jaym

Nachdem ich hier viele Antworten und Vorschläge kombiniert habe, ist dies meine letzte Antwort, die gut mit flex zusammenarbeitet. Dadurch können wir Spalten mit gleicher Höhe erstellen. Außerdem wird der letzte Index geprüft, und Sie müssen den inneren HTML-Code nicht wiederholen. Es verwendet nicht 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>

Es wird so etwas ausgegeben:

<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
Alisson

Born Solutions ist das Beste, ich brauche nur ein bisschen Zeit, um die Bedürfnisse zu befriedigen, ich hatte unterschiedliche responsive Lösungen und habe mich etwas verändert

<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
Kiko Seijo

Das funktionierte für mich, kein Spleißen oder irgendetwas erforderlich:

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>

JavaScript

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

Update 2019 - Bootstrap 4

Da Bootstrap 3 Floats verwendete, erforderte es clearfix resets alle n (3 oder 4) Spalten (.col-*) im .row, um ein ungleichmäßiges Umbrechen der Spalten zu verhindern.

Da Bootstrap 4 nun flexbox verwendet, ist es nicht mehr erforderlich, Spalten in separate .row-Tags zu setzen oder zusätzliche divs einzufügen, um zu erzwingen, dass Spalten alle n Spalten umbrechen.

Sie können einfach alle der Spalten in einem einzelnen .row Container wiederholen.

Zum Beispiel sind 3 Spalten in jeder visuellen Zeile:

<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>

Für Bootstrap ist die ng-Wiederholung also einfach:

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

Demo: https://www.codeply.com/go/Z3IjLRsJXX

0
Zim

Ich habe es nur mit dem Bootstrap gemacht, Sie müssen sehr vorsichtig bei der Position der Zeile und der Spalte sein, hier ist mein Beispiel.

<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>
0
Alexis Suárez

Versuchen Sie dieses Beispiel 

<!DOCTYPE html>
<html>
<head>
	<title></title>

	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
	<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
	<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
	<script type="text/javascript">
		var app = angular.module('myApp', []);

		app.controller('myCtrl', function ($scope,$filter) {
			$scope.products =[{
				id:1,
				name:'aa',
			},{
				id:2,
				name:'bb',
			},{
				id:3,
				name:'cc',
			},{
				id:4,
				name:'dd',
			},{
				id:5,
				name:'ee',
			}];
		});

	</script>
</head>
<body ng-app="myApp">
	<div ng-controller="myCtrl">
		<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>
	</div>
</body>
</html>

0
Saurabh Agrawal