it-swarm.com.de

so teilen Sie die Wiederholungsdaten mit Hilfe von Bootstrap in drei Spalten

Ich verwende ng-repeat mit meinem Code. Ich habe 'n' Nummer des Textfelds basierend auf ng-repeat. Ich möchte das Textfeld mit drei Spalten ausrichten.

das ist mein Code

<div class="control-group" ng-repeat="oneExt in configAddr.ext">
    {{$index+1}}. 
    <input type="text" name="macAdr{{$index+1}}" 
           id="macAddress" ng-model="oneExt.newValue" value=""/>
</div>
118
kuppu

Der zuverlässigste und technisch korrekte Ansatz ist die Transformation der Daten in der Steuerung. Hier ist eine einfache Chunk-Funktion und Verwendung.

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

$scope.chunkedData = chunk(myData, 3);

Dann würde Ihre Ansicht so aussehen:

<div class="row" ng-repeat="rows in chunkedData">
  <div class="span4" ng-repeat="item in rows">{{item}}</div>
</div>

Wenn Sie Eingaben innerhalb von ng-repeat haben, möchten Sie die Arrays wahrscheinlich abmischen, wenn die Daten geändert werden oder beim Senden. So würde dies in einem $watch aussehen, so dass die Daten immer im ursprünglichen zusammengeführten Format verfügbar sind:

$scope.$watch('chunkedData', function(val) {
  $scope.data = [].concat.apply([], val);
}, true); // deep watch

Viele Leute ziehen es vor, dies in der Ansicht mit einem Filter zu erreichen. Dies ist möglich, sollte aber nur zu Anzeigezwecken verwendet werden! Wenn Sie Eingaben in diese gefilterte Ansicht hinzufügen, führt dies zu Problemen, die can gelöst werden können, jedoch nicht hübsch oder zuverlässig sind.

Das Problem bei diesem Filter ist, dass jedes Mal neue verschachtelte Arrays zurückgegeben werden. Angular überwacht den Rückgabewert des Filters. Wenn der Filter zum ersten Mal ausgeführt wird, kennt Angular den Wert und führt ihn dann erneut aus, um sicherzustellen, dass die Änderung abgeschlossen ist. Wenn beide Werte gleich sind, wird der Zyklus beendet. Wenn nicht, wird der Filter immer wieder ausgelöst, bis sie identisch sind, oder Angular erkennt, dass eine unendliche Digest-Schleife auftritt und wird heruntergefahren. Da neue geschachtelte Arrays/Objekte zuvor nicht von Angular nachverfolgt wurden, sieht der Rückgabewert immer anders als zuvor. Um diese "instabilen" Filter zu beheben, müssen Sie den Filter in eine memoize-Funktion einschließen. lodash hat eine memoize-Funktion und die neueste Version von lodash enthält auch eine chunk-Funktion. Daher können Sie diesen Filter sehr einfach erstellen, indem Sie npm-Module verwenden und das Skript mit browserify oder webpack kompilieren.

Nicht vergessen: nur Anzeige! Filtern Sie im Controller, wenn Sie Eingaben verwenden!

Lodash installieren:

npm install lodash-node

Erstellen Sie den Filter:

var chunk = require('lodash-node/modern/array/chunk');
var memoize = require('lodash-node/modern/function/memoize');

angular.module('myModule', [])
.filter('chunk', function() {
  return memoize(chunk);
});

Und hier ist ein Beispiel mit diesem Filter:

<div ng-repeat="row in ['a','b','c','d','e','f'] | chunk:3">
  <div class="column" ng-repeat="item in row">
    {{($parent.$index*row.length)+$index+1}}. {{item}}
  </div>
</div>

Artikel vertikal bestellen

1  4
2  5
3  6

Bei vertikalen Spalten (Liste von oben nach unten) und nicht bei horizontalen Spalten (von links nach rechts) hängt die genaue Implementierung von der gewünschten Semantik ab. Listen, die sich ungleichmäßig teilen, können auf verschiedene Arten verteilt werden. Hier ist ein Weg:

<div ng-repeat="row in columns">
  <div class="column" ng-repeat="item in row">
    {{item}}
  </div>
</div>
var data = ['a','b','c','d','e','f','g'];
$scope.columns = columnize(data, 3);
function columnize(input, cols) {
  var arr = [];
  for(i = 0; i < input.length; i++) {
    var colIdx = i % cols;
    arr[colIdx] = arr[colIdx] || [];
    arr[colIdx].Push(input[i]);
  }
  return arr;
}

Die direkteste und einfachste Möglichkeit, Spalten abzurufen, ist die Verwendung von CSS-Spalten :

.columns {
  columns: 3;
}
<div class="columns">
  <div ng-repeat="item in ['a','b','c','d','e','f','g']">
    {{item}}
  </div>
</div>
251
m59

Diese Lösung ist sehr einfach:

JSON:

[{id:"1",name:"testA"},{id:"2",name:"test B"},{id:"3",name:"test C"},{id:"4",name:"test D"},{id:"5",name:"test E"}]

HTML:

<div ng-controller="MyCtrl">
  <table>
    <tr ng-repeat="item in items" ng-switch on="$index % 3">
      <td ng-switch-when="0">
        {{items[$index].id}} {{items[$index].name}}
      </td>
      <td ng-switch-when="0">
        <span ng-show="items[$index+1]">
          {{items[$index+1].id}} {{items[$index+1].name}}
        </span>
      </td>
      <td ng-switch-when="0">
        <span ng-show="items[$index+2]">    
          {{items[$index+2].id}} {{items[$index+2].name}}
        </span>
      </td>
    </tr>
  </table>
</div>

DEMO in FIDDLE

 enter image description here

62
sgrillon

Eine saubere, anpassungsfähige Lösung, die keine Datenmanipulation erfordert:

Das HTML:

<div class="control-group" class="label"
    ng-repeat="oneExt in configAddr.ext"
    ng-class="{'new-row': startNewRow($index, columnBreak) }">
    {{$index+1}}. 
    <input type="text" name="macAdr{{$index+1}}" 
       id="macAddress{{$index}}" ng-model="oneExt.newValue" />
</div>

Das CSS:

.label {
    float: left;
    text-align: left;
}
.new-row {
    clear: left;
}

Das JavaScript:

$scope.columnBreak = 3; //Max number of colunms
$scope.startNewRow = function (index, count) {
    return ((index) % count) === 0;
};

Dies ist eine einfache Lösung für das dynamische Rendern von Daten in Zeilen und Spalten, ohne dass das anzuzeigende Datenarray bearbeitet werden muss. Wenn Sie versuchen, die Größe des Browser-Fensters zu ändern, können Sie das Raster dynamisch an die Größe des Bildschirms/Div anpassen.

(Ich habe auch ein {{$ index}} -Suffix zu Ihrer ID hinzugefügt, da ng-repeat versucht, mehrere Elemente mit derselben ID zu erstellen, wenn Sie dies nicht tun.)

Ein ähnliches Arbeitsbeispiel

19
Cumulo Nimbus

m59s Antwort ist ziemlich gut. Das Einzige, was mir nicht gefällt, ist, dass divs für mögliche Daten einer Tabelle verwendet wird.

In Verbindung mit dem m59-Filter (Antwort irgendwo oben) wird nun beschrieben, wie er in einer Tabelle angezeigt wird.

<table>
    <tr class="" ng-repeat="rows in foos | chunk:2">
        <td ng-repeat="item in rows">{{item}}</td>
    </tr>
</table>
15
Jarrod

Folgendes ist ein einfacher Weg:

<table>
    <tr ng-repeat="item in lists" ng-hide="$index%2!==0">
        <td>
            <label>{{ lists[$index].name}}</label>
        </td>
        <td ng-hide="!lists[$index+1]">
            <label>{{ lists[$index+1].name}}</label>
        </td>
    </tr>
</table>

Die Antwort von Cumulo Nimbus ist für mich nützlich, aber ich möchte, dass dieses Raster von einem div umschlossen wird, das die Bildlaufleiste anzeigen kann, wenn die Liste zu lang ist. 

Um dies zu erreichen, fügte ich style="height:200px; overflow:auto" zu einem div um die Tabelle hinzu, wodurch es als einzelne Spalte angezeigt wird.

Funktioniert jetzt für eine Arraylänge von 1.

7
geting

Ich habe eine Funktion und habe sie in einem Dienst gespeichert, sodass ich sie in meiner gesamten App verwenden kann:

Bedienung:

app.service('SplitArrayService', function () {
return {
    SplitArray: 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;
    }
}

});

Controller:

$scope.rows   = SplitArrayService.SplitArray($scope.images, 3); //im splitting an array of images into 3 columns

Markup:

 <div class="col-sm-12" ng-repeat="row in imageRows">
     <div class="col-sm-4" ng-repeat="image in row">
         <img class="img-responsive" ng-src="{{image.src}}">
     </div>
 </div>
4
Chancho

Ein einfacher Trick mit "clearfix" CSS, empfohlen von Bootstrap:

<div class="row">
      <div ng-repeat-start="value in values" class="col-md-4">
        {{value}}
      </div>
      <div ng-repeat-end ng-if="$index % 3 == 0" class="clearfix"></div>
</div>

Viele Vorteile: Effizient, schnell, Boostrap-Empfehlungen verwenden, mögliche Verdauungsprobleme vermeiden und das Angular-Modell nicht ändern.

2
Lastnico

Mein Ansatz war eine Mischung von Dingen.

Mein Ziel war es, ein Raster an die Bildschirmgröße anzupassen. Ich wollte 3 Spalten für lg, 2 Spalten für sm und md und 1 Spalte für xs.

Zunächst erstellte ich die folgende Bereichsfunktion mit dem $window-Service von angle:

$scope.findColNumberPerRow = function() {
    var nCols;
    var width = $window.innerWidth;

    if (width < 768) {
        // xs
        nCols = 1;
    }
    else if(width >= 768 && width < 1200) {
         // sm and md
         nCols = 2
    } else if (width >= 1200) {
        // lg
        nCols = 3;
    }
    return nCols;
};

Dann habe ich die von @Cumulo Nimbus vorgeschlagene Klasse verwendet:

.new-row {
    clear: left;
}

In dem div, das den ng-repeat enthält, habe ich die resizable-Direktive hinzugefügt, wie in diese Seite erklärt. Damit der Winkel $window-Dienst bei jeder Fenstergröße mit den neuen Werten aktualisiert wird.

Letztendlich habe ich in dem wiederholten div: 

ng-repeat="user in users" ng-class="{'new-row': ($index % findColNumberPerRow() === 0) }"

Bitte lassen Sie mich Fehler in diesem Ansatz wissen.

Ich hoffe es kann hilfreich sein.

2
igorauad

Hier ist eine leicht gehackte Art, es zu tun. Es ist mehr manuell und endet mit unordentlichem Markup. Ich empfehle das nicht, aber es gibt Situationen, in denen dies nützlich sein kann.

Hier ist ein Fiddle-Link http://jsfiddle.net/m0nk3y/9wcbpydq/

HTML:

<div ng-controller="myController">
    <div class="row">
        <div class="col-sm-4">
            <div class="well">
                <div ng-repeat="person in people = data | limitTo:Math.ceil(data.length/3)">
                {{ person.name }}
                </div>
            </div>
        </div>
        <div class="col-sm-4">
            <div class="well">
                <div ng-repeat="person in people = data | limitTo:Math.ceil(data.length/3):Math.ceil(data.length/3)">
                {{ person.name }}
                </div>
            </div>
        </div>
        <div class="col-sm-4">
            <div class="well">
                <div ng-repeat="person in people = data | limitTo:Math.ceil(data.length/3):Math.ceil(data.length/3)*2">
                {{ person.name }}
                </div>
            </div>
        </div>
    </div>
</div>

JS:

var app = angular.module('myApp', []);

app.controller('myController', function($scope) {

    $scope.Math = Math;
    $scope.data = [
        {"name":"Person A"},
        ...
    ];
});

Für dieses Setup müssen wir etwas Mathe für das Markup verwenden: /. Sie müssen also Math einfügen, indem Sie diese Zeile hinzufügen: $scope.Math = Math;

1
Gene Parcellano

Dieses Beispiel erzeugt einen verschachtelten Repeater, bei dem die äußeren Daten ein inneres Array enthalten, das ich in zwei Spalten auflisten wollte. Das Konzept würde für drei oder mehr Spalten gelten.

In der inneren Spalte wiederhole ich die "Reihe", bis das Limit erreicht ist. Die Grenze wird bestimmt, indem die Länge des Feldes von Elementen durch die Anzahl der gewünschten Spalten, in diesem Fall durch zwei, geteilt wird. Die Divisionsmethode befindet sich auf dem Controller und die aktuelle Arraylänge wird als Parameter übergeben. Die JavaScript-Funktion slice (0, array.length/columnCount) hat dann den Grenzwert auf den Repeater angewendet.

Der zweite Spalten-Repeater wird dann aufgerufen und wiederholt slice (array.length/columnCount, array.length), wodurch die zweite Hälfte des Arrays in Spalte zwei erzeugt wird.

<div class="row" ng-repeat="GroupAccess in UsersController.SelectedUser.Access" ng-class="{even: $even, odd: $odd}">
    <div class="col-md-12 col-xs-12" style=" padding-left:15px;">
        <label style="margin-bottom:2px;"><input type="checkbox" ng-model="GroupAccess.isset" />{{GroupAccess.groupname}}</label>
    </div>
    <div class="row" style=" padding-left:15px;">
        <div class="col-md-1 col-xs-0"></div>
        <div class="col-md-3 col-xs-2">
            <div style="line-height:11px; margin-left:2px; margin-bottom:2px;" ng-repeat="Feature in GroupAccess.features.slice(0, state.DivideBy2(GroupAccess.features.length))">
                <span class="GrpFeature">{{Feature.featurename}}</span>
            </div>
        </div>
        <div class="col-md-3 col-xs-2">
            <div style="line-height:11px; margin-left:2px; margin-bottom:2px;" ng-repeat="Feature in GroupAccess.features.slice( state.DivideBy2(GroupAccess.features.length), GroupAccess.features.length )">
                <span class="GrpFeature">{{Feature.featurename}}</span>
            </div>
        </div>
        <div class="col-md-5 col-xs-8">
        </div>
    </div>
</div>


// called to format two columns
state.DivideBy2 = function(nValue) {
    return Math.ceil(nValue /2);
};

Ich hoffe, das hilft, die Lösung auf eine andere Weise zu betrachten. (PS das ist mein erster Beitrag hier! :-))

1
Harvey Mushman

Alle diese Antworten scheinen massiv übertrieben. 

Bei weitem die einfachste Methode wäre das Einrichten der Eingabe divs in einem Bootstrap mit col-md-4-Spalten. Dann formatiert bootstrap es automatisch in 3 Spalten.

<div class="col-md-12">
    <div class="control-group" ng-repeat="oneExt in configAddr.ext">
        <div class="col-md-4">
            <input type="text" name="macAdr{{$index}}"
                   id="macAddress" ng-model="oneExt.newValue" value="" />
        </div>
    </div>
</div>
1
cullimorer

Ich fixiere ohne .row

<div class="col col-33 left" ng-repeat="photo in photos">
   Content here...
</div>

und css

.left {
  float: left;
}
1
selahattinunlu
<div class="row">
  <div class="col-md-4" ng-repeat="remainder in [0,1,2]">
    <ul>
      <li ng-repeat="item in items" ng-if="$index % 3 == remainder">{{item}}</li>
    </ul>
  </div>
</div>
1
mrded

Eine andere Möglichkeit ist, width:33.33%; float:left auf ein Wrapperdiv wie folgt zu setzen:

<div ng-repeat="right in rights" style="width: 33.33%;float: left;">
    <span style="width:60px;display:inline-block;text-align:right">{{$index}}</span>
    <input type="number" style="width:50px;display:inline-block" ">
</div>
0
geting

Ausgehend von der sehr guten Antwort von m59. Ich habe festgestellt, dass die Modelleingaben verschwommen wären, wenn sie geändert würden, sodass Sie nur jeweils einen Buchstaben ändern konnten. Dies ist eine neue für Objektlisten für alle, die es benötigen:

EDITAktualisiert, um mehrere Filter auf einer Seite zu behandeln

app.filter('partition', function() {
  var cache = {}; // holds old arrays for difference repeat scopes
  var filter = function(newArr, size, scope) {
    var i,
      oldLength = 0,
      newLength = 0,
      arr = [],
      id = scope.$id,
      currentArr = cache[id];
    if (!newArr) return;

    if (currentArr) {
      for (i = 0; i < currentArr.length; i++) {
        oldLength += currentArr[i].length;
      }
    }
    if (newArr.length == oldLength) {
      return currentArr; // so we keep the old object and prevent rebuild (it blurs inputs)
    } else {
      for (i = 0; i < newArr.length; i += size) {
        arr.Push(newArr.slice(i, i + size));
      }
      cache[id] = arr;
      return arr;
    }
  };
  return filter;
}); 

Und das wäre die Verwendung:

<div ng-repeat="row in items | partition:3:this">
  <span class="span4">
    {{ $index }}
  </span>
</div>
0
JSous

Ich befand mich in einem ähnlichen Fall und wollte Anzeigegruppen mit jeweils 3 Spalten generieren. Obwohl ich Bootstrap verwendete, versuchte ich, diese Gruppen in verschiedene übergeordnete Divs zu unterteilen. Ich wollte auch etwas generisch Nützliches machen.

Ich habe es mit 2 ng-repeat wie folgt angegangen:

<div ng-repeat="items in quotes" ng-if="!($index % 3)">
  <div ng-repeat="quote in quotes" ng-if="$index <= $parent.$index + 2 && $index >= $parent.$index">
                ... some content ...
  </div>
</div>

Dies macht es sehr einfach, zu einer anderen Anzahl von Spalten zu wechseln und diese in mehrere übergeordnete Divs aufzuteilen.

0
Matt Kindy

Lodash hat jetzt eine Chunk-Methode eingebaut, die ich persönlich verwende: https://lodash.com/docs#chunk

Auf dieser Grundlage könnte der Controller-Code wie folgt aussehen:

$scope.groupedUsers = _.chunk( $scope.users, 3 )

Code anzeigen:

<div class="row" ng-repeat="rows in groupedUsers">
  <div class="span4" ng-repeat="item in rows">{{item}}</div>
</div>
0
sean2078

Ich bin neu in Bootstrap und Eildjj, aber dies könnte auch Array pro 4 Elemente zu einer Gruppe machen, das Ergebnis wird fast wie 3 Spalten aussehen. Dieser Trick verwendet das Bootstrap-Prinzip.

<div class="row">
 <div class="col-sm-4" data-ng-repeat="item in items">
  <div class="some-special-class">
   {{item.XX}}
  </div>
 </div>
</div>
0
Nathan