I have a collection of project items that can be sorted in three different ways: by name, date, or randomly.
When sorted by name or date, the items are grouped by the first letter of the name or the year of the date. However, when sorted randomly, there is no grouping involved, which requires a different structure in the DOM.
Currently, I have implemented two distinct DOM structures in the view, which is not very efficient and may not be the best approach in terms of Angular development practices. I am using directives to toggle between the two DOM templates based on the selected sorting option, but I would appreciate some advice on how to improve this solution.
Update: It is important to note that there are two different implementations of the ng-repeat
directive depending on the selected sort option. Sorting by name and date involves a nested loop to iterate through the groups ((header, group) in projects
), while sorting randomly only requires a single loop since the items are not grouped (project in projects
).
Plunkr. Please observe the delay when you select the Random option. Relevant sections are provided below.
project-grid partial
<div class="project-controls">
<label><input type="radio" ng-model="orderChoice" value="name">Name</label>
<label><input type="radio" ng-model="orderChoice" value="date">Date</label>
<label><input type="radio" ng-model="orderChoice" value="random">Random</label>
</div>
<!-- DOM structure for grouped Name and Date sortings -->
<!-- Note the nested ng-repeat -->
<div id="nonRandomGrouping" ng-hide="randomSort">
<div class="group" ng-repeat="(header, group) in projects">
<h2>{{ header }}</h2>
<ul class="project-thumbnails">
<li ng-repeat="project in group | orderBy: 'name' ">
<img ng-src="{{project.coverImage}}">
<p><strong>{{ project.name }}</strong></p>
<p><strong>{{ project.date }}</strong></p>
</li>
</ul>
</div>
</div>
<!-- DOM structure for ungrouped Random sorting -->
<!-- Note the single ng-repeat -->
<div class="group" id="randomGrouping" ng-show="randomSort">
<ul class="project-thumbnails">
<li ng-repeat="project in projects" style="overflow: auto;">
<img ng-src="{{project.coverImage}}">
<p><strong>{{ project.name }}</strong></p>
<p><strong>{{ project.date }}</strong></p>
</li>
</ul>
</div>
controller
angular.module('myApp.controllers', [])
.controller('MyCtrl1', ['$scope', '$http', function($scope, $http) {
var projectsByName,
projectsByYear,
originalData
$scope.orderChoice = "name"
$scope.randomSort = false
function randomize() {
$scope.randomSort = true
$scope.projects = originalData.sort(function() { return 0.5 - Math.random() })
}
$scope.getProjects = function() {
$http({ method : "GET", url : "/projects.json" }).success(function(data) {
$scope.count = data.length
originalData = data.sort()
$scope.projects = projectsByName = _.groupBy(data, function grouper(proj){
return proj.name[0]
})
projectsByYear = _.groupBy(data, function grouper(proj){
return new Date(proj.date).getFullYear()
})
})
}
$scope.$watch('orderChoice', function orderChangeHandler(newVal, oldVal){
if ( newVal !== oldVal ) {
switch(newVal){
case 'name':
$scope.randomSort = false
$scope.projects = projectsByName
break;
case 'date':
$scope.randomSort = false
$scope.projects = projectsByYear
break;
case 'random':
randomize()
break;
}
}
})
$scope.getProjects()
}])