Reputation: 5891
I am trying to find the best way to display tabular data using AngularJS based on three RESTful data endpoints. For example, the data is comprised of three models:
Roommate
id
name
Chore
id
name
ChoreAssignment
id
day
roommate (fk)
chore (fk)
I want to display the Chore Assignments in a table with day on the x-axis and roommates on the y-axis.
Mon Tue Wed Thu Fri Sat Sun
Bob dishes mow grass dishes
Alice trash dishes sweep
Mike dishes vacuum
I can easily display the data in separate lists with ng-repeat but I am unsure about combining them in the table. I am trying to avoid a custom API call for this table specifically if I can simply build it from the three separate lists of data I already have. Any advice is greatly appreciated.
Upvotes: 2
Views: 428
Reputation: 3374
I'd populate intermediate object (in service or controller) that contains data for selected viewing period - lets say last two weeks worth. Then that can be easily traversed in your template using familiar ng-repeat.
In other words let view not care about restful endpoints or other service structure - just provide it with a model to present.
Upvotes: 1
Reputation: 5891
I opted to build a $scope.choreTable
object in the controller (utilizing Underscore.js). $q.all()
is used to ensure the data promises are all resolved before building the table.
$q.all([roommateQuery, choreQuery, choreAssignmentQuery]).then(function(){
$scope.choreTable = [];
var days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
_.each($scope.roommates, function(roommate, i){
$scope.choreTable.push({roommate: roommate, days: []});
_.each(days, function(day, j){
$scope.choreTable[i].days.push(
_.where($scope.choreAssignments, {roommate: roommate.id, day: day})
);
});
});
});
resulting in an object like so:
[
{
roommate: {id: 1, name: "Bob"},
days: [[ChoreAssignment1], [], [], [ChoreAssignment2], [], [], [ChoreAssignment1]]
},
{
roommate: {id: 2, name: "Alice"},
days: [[], [ChoreAssignment3], [ChoreAssignment1], [], [], [ChoreAssignment4], []]
},
{
roommate: {id: 3, name: "Mike"},
days: [[], [], [], [], [ChoreAssignment1], [ChoreAssignment5], []]
}
]
and then in the view:
<tr ng-repeat="row in choreTable">
<td>
[[ row.roommate.name ]]
</td>
<td ng-repeat="day in row.days">
<div ng-repeat="choreAssignment in day">
[[ choreAssignment.chore.name ]]
</div>
</td>
</tr>
Upvotes: 0
Reputation: 343
This might be more than you want but have you tried angular-datatables before? If you set the source file to the roommates, you can then build seven columns each representing a day of the week. Since you set the source file to the roommates, it'll generate a row in the table for each roommate. As it generates the row, you can put together some code to find any chores that match up with the current roommate and day of the week. I realize this might be a little hard to follow so here's a bit of a code sample (after you follow the setup as shown on the Getting Started page):
$scope.dtOptions = DTOptionsBuilder.newOptions()
.withSource('enter your roommate api call here')
});
$scope.dtColumns = [
DTColumnBuilder.newColumn('Mon').withTitle('Mon').renderWith(function (data, type, full) {
currentRoommate = full.name
//write your code here that queries your join table for the roommate name and Monday
//return result;
}),
DTColumnBuilder.newColumn('Tue').withTitle('Tue').renderWith(function (data, type, full) {
currentRoommate = full.name
//write your code here that queries your join table for the roommate name and Tuesday
//return result;
}),
...so on until the rest of the week
In your view, just drop this:
<table id="foobar" datatable="" dt-options="dtOptions" dt-columns="dtColumns"></table>
It's a little verbose so you could probably splinter the join table query into a service. Angular-datatables comes with a lot of options that you can find in the API section of the documents so you can adjust the functionality of the table as you want (disable sorting, etc.). Don't forget to inject the dependencies for DTOptionsBuilder and DTColumnBuilder.
Hope this puts you on the right track.
Upvotes: 2