I have a horizontal month calendar that shows the activities for employees per day.
Currently it's using a table with the following hierarchy/flow
1) Controller: Generate an array containing every day for that month based on the select month / year. A $scope.$watchCollection updates the array whenever year or month changes.
As the code explains what I do better:
<table class="table table-bordered table-condensed" ng-controller="PlanningOverviewController">
<tr>
<th><input type="text" ng-model="employeefilter"/></th>
<th colspan="7" ng-repeat="week in weeks">
{{week | weekheader}}
</th>
</tr>
<tr>
<th> </th>
<th ng-repeat="day in days">
{{day.format("ddd")}}
</th>
</tr>
<tr>
<th> </th>
<th ng-repeat="day in days">
{{day.date()}}
</th>
</tr>
<tr ng-repeat="employee in planning | filter:employeefilter">
<td> {{employee.firstName}} {{employee.lastName}}</td>
<td class="calendar-unit" ng-repeat="day in days" ng-init="assignments = getAssignments(day, employee)">
<div class="assignment"
assignment ng-repeat="assignment in assignments"
assignment-description = "{{assignment.description}}"
assignment-period="{{assignment.period}}"
assignment-type="{{assignment.type}}">
</div>
</td>
</tr>
</table>
The problem is that the getAssignments() is "expensive" as it needs to check:
- Is it a public holiday?
- Does the employee work on that day?
- Has the employee a holiday?
- Get the project assignments for that day
Whenever the list of employee is changed (due to a filter), or the month changes, the generating of the table takes up to 6 seconds when having ~40 employees.
Is there another way to approach this, or to improve the nesting of ng-repeats?
Thanks, can clarify if more info is needed.
EDIT:
I've tried removing some elements from the code to see what causes improvements. When I let assignments return a dummy value, the rendering improves by 2-3 seconds, so some caching there might help it. However, it still takes 3-4 seconds to render the "empty" table that way.
I've then removed logic from the directive itself, effectively making it empty, this still caused the same delay.
However, when removing the directive itself from the html, the table renders almost instantly when changing dates. Do I have to assume that this is a (normal?) limitation to angular? I don't want static data, as the goal is to drag assignments around.
Update 2: I realised that I've been approaching this pretty inefficiently... After looking at the scopes & bindings with batarang + reviewing the code itself, I've noticed that I'm doing way too much "getAssignments()" checks, and that my entire approach is based on "getting assignments for an employee", while it'll probably be better / faster to focus on getting assignments for a day. I'll update the code over the weekend & post an answer if it improves/resolves the issue.
Update 3: After rewriting the way the planning get generated, it now takes 2 seconds to display the table for 50 resources. There are about 1750 directives, (at least 1 event for an employee per day). I assume this is a normal delay seeing the size?
update 4: Code for directive:
angular.module('planning.directives', ["templates.app", "ui.bootstrap", "planning.controllers"])
.directive("assignment", function () {
return {
restrict: "EA",
replace: true,
scope: {
assignmentData: "=",
assignmentCreateMethod: "&"
},
template: '<div class="assignment">{{assignmentData.description}} </div>',
link: function (scope, element, attrs) {
element.addClass(scope.assignmentData.type);
if (scope.assignmentData.period == "am") {
element.css("width", "50%");
element.css("float", "left");
}
if (scope.assignmentData.period == "pm") {
element.css("width", "50%");
element.css("float", "right");
}
element.on("mouseenter",function () {
element.addClass("hover");
}).on("mouseleave", function () {
element.removeClass("hover");
});
element.on("click", function() {
scope.assignmentCreateMethod();
});
}
};
});
See Question&Answers more detail:
os