1

http://jsfiddle.net/ocrsppvc/

<div ng-repeat="json in myJson track by $index" ng-class="{'row':$index % 4 === 0}">
  <div class="col-md-3 col-sm-4 col-xs-6" >
    {{$index+1}}
  </div>
</div>

I want to have 4 item in a row but I have problem with my ng-class logic.

8
  • Honestly I would just remove the repeat container and use bootstraps' overflowing nature determine what it looks like. Is there a particular reason you need exactly 4 items in your rows, regardless of what gets displayed? Commented Dec 11, 2016 at 3:01
  • @Jhecht that's the requirement. Commented Dec 11, 2016 at 3:10
  • What do you mean by "requirement?" Commented Dec 11, 2016 at 3:12
  • @Jhecht in a row there have to be 4 items. Commented Dec 11, 2016 at 3:13
  • And who set that? You, your boss...? Commented Dec 11, 2016 at 3:13

1 Answer 1

2

What I would recommend personally is the usage of a set of tools called Angular Filter. It's a dependency that you inject into your modules that does so much to assist with certain things, much like your problem here. The one I used is called "chunkBy," which you can read about at that link.

I have set up This Plunkr as a demo, but the code is here

angular.module('app', ['angular.filter']).controller('mainCtrl', function($scope) {
  $scope.myJson = ["mayank1", "mayank2", "mayank3", "mayank4", "mayank5", "mayank6", "mayank7", "mayank8", "mayank9"];
})
<link data-require="[email protected]" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />

<script data-require="[email protected]" data-semver="1.5.8" src="https://code.angularjs.org/1.5.8/angular.js"></script>
<script data-require="[email protected]" data-semver="0.5.7" src="//cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.7/angular-filter.js"></script>
<div ng-app="app" ng-controller="mainCtrl">
  <div ng-repeat="json in myJson|chunkBy:4" class="row">
    <div class="col-md-3 col-sm-4 col-xs-6" ng-repeat="item in json">
      {{item}}
    </div>
  </div>
</div>

Edit

If you just would like to use the code needed for chunkBy, I have extracted that. Credit still goes to a8m (which may be a good thing to include his copyright in the top of the file if you end up using it)

/**
 * Bunch of useful filters for angularJS(with no external dependencies!)
 * @version v0.5.14 - 2016-12-06 * @link https://github.com/a8m/angular-filter
 * @author Ariel Mashraki <[email protected]>
 * @license MIT License, http://www.opensource.org/licenses/MIT
 */
var isDefined = angular.isDefined,
  isUndefined = angular.isUndefined,
  isFunction = angular.isFunction,
  isString = angular.isString,
  isNumber = angular.isNumber,
  isObject = angular.isObject,
  isArray = angular.isArray,
  forEach = angular.forEach,
  extend = angular.extend,
  copy = angular.copy,
  equals = angular.equals;

function isNull(value) {
  return value === null;
}

function isScope(obj) {
  return obj && obj.$evalAsync && obj.$watch;
}
angular.module('a8m.filter-watcher', [])
  .provider('filterWatcher', function() {

    this.$get = ['$window', '$rootScope',
      function($window, $rootScope) {

        /**
         * Cache storing
         * @type {Object}
         */
        var $$cache = {};

        /**
         * Scope listeners container
         * scope.$destroy => remove all cache keys
         * bind to current scope.
         * @type {Object}
         */
        var $$listeners = {};

        /**
         * $timeout without triggering the digest cycle
         * @type {function}
         */
        var $$timeout = $window.setTimeout;

        /**
         * @description
         * get `HashKey` string based on the given arguments.
         * @param fName
         * @param args
         * @returns {string}
         */
        function getHashKey(fName, args) {
          function replacerFactory() {
            var cache = [];
            return function(key, val) {
              if (isObject(val) && !isNull(val)) {
                if (~cache.indexOf(val)) return '[Circular]';
                cache.push(val)
              }
              if ($window == val) return '$WINDOW';
              if ($window.document == val) return '$DOCUMENT';
              if (isScope(val)) return '$SCOPE';
              return val;
            }
          }
          return [fName, JSON.stringify(args, replacerFactory())]
            .join('#')
            .replace(/"/g, '');
        }

        /**
         * @description
         * fir on $scope.$destroy,
         * remove cache based scope from `$$cache`,
         * and remove itself from `$$listeners`
         * @param event
         */
        function removeCache(event) {
          var id = event.targetScope.$id;
          forEach($$listeners[id], function(key) {
            delete $$cache[key];
          });
          delete $$listeners[id];
        }

        /**
         * @description
         * for angular version that greater than v.1.3.0
         * it clear cache when the digest cycle is end.
         */
        function cleanStateless() {
          $$timeout(function() {
            if (!$rootScope.$$phase)
              $$cache = {};
          }, 2000);
        }

        /**
         * @description
         * Store hashKeys in $$listeners container
         * on scope.$destroy, remove them all(bind an event).
         * @param scope
         * @param hashKey
         * @returns {*}
         */
        function addListener(scope, hashKey) {
          var id = scope.$id;
          if (isUndefined($$listeners[id])) {
            scope.$on('$destroy', removeCache);
            $$listeners[id] = [];
          }
          return $$listeners[id].push(hashKey);
        }

        /**
         * @description
         * return the `cacheKey` or undefined.
         * @param filterName
         * @param args
         * @returns {*}
         */
        function $$isMemoized(filterName, args) {
          var hashKey = getHashKey(filterName, args);
          return $$cache[hashKey];
        }

        /**
         * @description
         * store `result` in `$$cache` container, based on the hashKey.
         * add $destroy listener and return result
         * @param filterName
         * @param args
         * @param scope
         * @param result
         * @returns {*}
         */
        function $$memoize(filterName, args, scope, result) {
          var hashKey = getHashKey(filterName, args);
          //store result in `$$cache` container
          $$cache[hashKey] = result;
          // for angular versions that less than 1.3
          // add to `$destroy` listener, a cleaner callback
          if (isScope(scope)) {
            addListener(scope, hashKey);
          } else {
            cleanStateless();
          }
          return result;
        }

        return {
          isMemoized: $$isMemoized,
          memoize: $$memoize
        }
      }
    ];
  });
angular.module('a8m.chunk-by', ['a8m.filter-watcher'])
  .filter('chunkBy', ['filterWatcher',
    function(filterWatcher) {
      return function(array, n, fillVal) {

        return filterWatcher.isMemoized('chunkBy', arguments) ||
          filterWatcher.memoize('chunkBy', arguments, this,
            _chunkBy(array, n, fillVal));
        /**
         * @description
         * Get array with size `n` in `val` inside it.
         * @param n
         * @param val
         * @returns {Array}
         */
        function fill(n, val) {
          var ret = [];
          while (n--) ret[n] = val;
          return ret;
        }

        function _chunkBy(array, n, fillVal) {
          if (!isArray(array)) return array;
          return array.map(function(el, i, self) {
            i = i * n;
            el = self.slice(i, i + n);
            return !isUndefined(fillVal) && el.length < n ? el.concat(fill(n - el.length, fillVal)) : el;
          }).slice(0, Math.ceil(array.length / n));
        }
      }
    }
  ]);
angular.module('app', ['a8m.chunk-by']).controller('mainCtrl', function($scope) {
  $scope.myJson = ["mayank1", "mayank2", "mayank3", "mayank4", "mayank5", "mayank6", "mayank7", "mayank8", "mayank9"];
})
<link data-require="[email protected]" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
<script data-require="[email protected]" data-semver="1.5.8" src="https://code.angularjs.org/1.5.8/angular.js"></script>
<script data-require="[email protected]" data-semver="0.5.7" src="//cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.7/angular-filter.js"></script>
<div ng-app="app" ng-controller="mainCtrl">
  <div ng-repeat="json in myJson|chunkBy:4" class="row">
    <div class="col-md-3 col-sm-4 col-xs-6" ng-repeat="item in json">
      {{item}}
    </div>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

9 Comments

so easier just use flexbox :D
Don't understand how flex box solves your particular html issue.
ya tried flexbox doesn't work lol. if I stuck on this I'll just use 33% width and float left. urghhhh..
The code I have provided results in your desired html, I'm not understanding the issue
although I have to plug in an over sized library but this solved my problem, thank very very much!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.