Implementing Three-Column Layout for ng-repeat Data with Bootstrap: Controller Methods and CSS Solutions

Dec 04, 2025 · Programming · 11 views · 7.8

Keywords: AngularJS | ng-repeat | Bootstrap | three-column layout | data chunking

Abstract: This article explores how to split ng-repeat data into three columns in AngularJS, primarily using the Bootstrap framework. It details reliable approaches for handling data in the controller, including the use of chunk functions, data synchronization via $watch, and display optimization with lodash's memoize filter. Additionally, it covers implementations for vertical column layouts and alternative solutions using pure CSS columns, while briefly comparing other methods like ng-switch and their limitations. Through code examples and in-depth explanations, it helps developers choose appropriate three-column layout strategies to ensure proper data binding and view updates.

In AngularJS development, when using the ng-repeat directive to dynamically generate elements, it is often necessary to layout data in multiple columns, such as displaying a series of input boxes in three columns. This not only enhances user experience but also optimizes page structure. Based on a common problem—how to split ng-repeat-generated data into three columns—this article provides multiple solutions using the Bootstrap framework, along with a thorough analysis of their pros and cons.

Controller Method: Reliable Data Handling

The most reliable and technically correct approach is to preprocess data in the controller. By defining a chunk function, the original array is split into sub-arrays of a specified size. For example, to divide data into three columns:

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

In the view, use nested ng-repeat to render these sub-arrays:

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

This method ensures data structure stability and facilitates subsequent operations. If input boxes or other form elements are involved, synchronize updates to the original array when data changes. This can be achieved via $watch with deep monitoring:

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

This prevents data inconsistency and is the recommended approach for interactive content.

Filter Method: For Display Only

Another common method is to use a filter to split data directly in the view, but this is suitable only for display purposes. For instance, create a filter using lodash's chunk and memoize functions:

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

Apply it in the view:

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

Note that filters may trigger infinite digest loops in Angular, as new arrays are seen as different values each time. Using memoize caches results for better performance, but it is still not recommended for input binding to avoid data synchronization issues.

Implementing Vertical Column Layout

Sometimes, data needs to be arranged vertically (e.g., 1, 4, 7 in the first column) rather than horizontally. This can be achieved with a custom function:

function columnize(input, cols) {
  var arr = [];
  for (var i = 0; i < input.length; i++) {
    var colIdx = i % cols;
    arr[colIdx] = arr[colIdx] || [];
    arr[colIdx].push(input[i]);
  }
  return arr;
}

$scope.columns = columnize(data, 3);

Use nested ng-repeat in the view to render the data, ensuring the distribution meets expectations.

CSS Columns: A Simple Alternative

For pure layout needs, CSS columns offer a JavaScript-free solution. By setting the columns property, content can be automatically split into multiple columns:

.columns {
  columns: 3;
}

Apply it in HTML:

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

This method is simple and efficient but may not suit complex data binding scenarios, as CSS does not handle data logic.

Comparison with Other Methods

Beyond the above approaches, other attempts exist, such as using ng-switch to render columns based on index. For example, in one answer, a three-column table is created with ng-switch on="$index % 3":

<tr ng-repeat="item in items" ng-switch on="$index % 3">
  <td ng-switch-when="0">
    {{items[$index].id}} {{items[$index].name}}
  </td>
  <!-- other columns similar -->
</tr>

While intuitive, this method leads to redundant code and poor maintainability, especially with dynamic data changes. Thus, it scored lower (2.5 points) and is not recommended for production environments.

Summary and Best Practices

When implementing a three-column layout for ng-repeat data, choose methods based on specific needs. For scenarios requiring data binding and interaction, prefer using a chunk function in the controller combined with $watch for synchronization. For display-only purposes, consider filters with memoize or CSS columns. Vertical layouts can be implemented via custom functions. Avoid complex and error-prone view logic like the ng-switch method. By making informed choices, application performance and maintainability can be enhanced.

In practice, test different solutions for data update and rendering performance. For instance, controller methods may better handle large datasets, while CSS columns are more efficient for simple layouts. Integrating with Bootstrap's grid system can further optimize responsive design.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.