Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Here's what I finally decided upon to handle groupings within ng-repeat. I read up more on directives and filters and while you can solve this problem with either, the filter approach seemed a better choice. The reason is that filters are better suited for situations where only the data needs to be manipulated. Directives are better when DOM manipulations are needed. In this example, I really only needed to manipulate the data and leave the DOM alone. I felt that this gave the greatest flexibility.</p> <p>See my final approach to groupings working on <a href="http://jsfiddle.net/drubarth/SDWRK/8/" rel="nofollow">jsFiddle</a>. I also added a little form to demonstrate how the list will work when dynamically adding data.</p> <p>Here's the HTML.</p> <pre><code>&lt;div ng-app="myApp"&gt; &lt;div ng-controller='TestGroupingCtlr'&gt; &lt;div ng-repeat="item in MyList | orderBy:'groupfield' | groupBy:'groupfield'" &gt; &lt;h2 ng-show="item.groupfield_CHANGED"&gt;{{item.groupfield}}&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;{{item.whatever}}&lt;/li&gt; &lt;/ul&gt; &lt;/div&gt; &lt;form role="form" ng-submit="AddItem()"&gt; &lt;input type="text" data-ng-model="item.groupfield" placeholder="Group"&gt; &lt;input type="text" data-ng-model="item.whatever" placeholder="Item"&gt; &lt;input class="btn" type="submit" value="Add Item"&gt; &lt;/form&gt; &lt;/div&gt; &lt;/div&gt; </code></pre> <p>Here's the Javascript.</p> <pre><code>var app=angular.module('myApp',[]); app.controller('TestGroupingCtlr',function($scope) { $scope.MyList = [ {groupfield: 'Group 1', whatever: 'abc'}, {groupfield: 'Group 1', whatever: 'def'}, {groupfield: 'Group 2', whatever: 'ghi'}, {groupfield: 'Group 2', whatever: 'jkl'}, {groupfield: 'Group 2', whatever: 'mno'} ]; $scope.AddItem = function() { // add to our js object array $scope.MyList.push({ groupfield:$scope.item.groupfield, whatever:$scope.item.whatever }); }; }) /* * groupBy * * Define when a group break occurs in a list of items * * @param {array} the list of items * @param {String} then name of the field in the item from the list to group by * @returns {array} the list of items with an added field name named with "_new" * appended to the group by field name * * @example &lt;div ng-repeat="item in MyList | groupBy:'groupfield'" &gt; * &lt;h2 ng-if="item.groupfield_CHANGED"&gt;{{item.groupfield}}&lt;/h2&gt; * * Typically you'll want to include Angular's orderBy filter first */ app.filter('groupBy', function(){ return function(list, group_by) { var filtered = []; var prev_item = null; var group_changed = false; // this is a new field which is added to each item where we append "_CHANGED" // to indicate a field change in the list var new_field = group_by + '_CHANGED'; // loop through each item in the list angular.forEach(list, function(item) { group_changed = false; // if not the first item if (prev_item !== null) { // check if the group by field changed if (prev_item[group_by] !== item[group_by]) { group_changed = true; } // otherwise we have the first item in the list which is new } else { group_changed = true; } // if the group changed, then add a new field to the item // to indicate this if (group_changed) { item[new_field] = true; } else { item[new_field] = false; } filtered.push(item); prev_item = item; }); return filtered; }; }) </code></pre> <p>For the application I'm using this in, I setup the filter as a reusable filter throughout the app.</p> <p>What I didn't like about the directive approach was that the HTML was in the directive, so it didn't feel reusable.</p> <p>I liked the previous filter approach, but it didn't seem efficient since the list would have to be traversed twice on ever digest cycle. I deal with long lists, so it could be an issue. In addition it just didn't seem as intuitive as a simple check against the previous item to see if it changed. Plus I wanted to be able to use the filter against multiple fields easily, which this new filter handles just by piping to the filter again with another field name.</p> <p>One other comment on my groupBy filter -- I do realize that multiple groupings would cause the array to be traversed multiple times, so I plan on revising it to accept an array of multiple group by fields so that it only has to traverse the array once.</p> <p>Thanks so much for the inputs. It really helped me in learning more about directives and filters in Angular.</p> <p>cheers, Darryl</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload