Our app incorporates a task list that can potentially grow to a substantial size. The main task list is accompanied by a sidebar, where selected tasks can be edited using a different controller (TasksSidebarCtrl instead of TasksCtrl which handles the list display). The selected task is duplicated and then merged back into the list, with communication managed through TasksService.
The significant number of watchers per task in the index prompted us to explore alternative solutions.
Implementing one-time binding has successfully reduced the number of watchers (currently only the submenu for editing/changing task statuses without selecting in the sidebar generates watchers). However, due to our use of track by task.id (which we deem necessary given the numerous filters and frequent DOM changes), employing splice does not effectively remove and replace the task with the updated version - defeating the purpose of track by.
Is there a method to enforce the update of this task item while still utilizing both track by and one-time binding?
tasks-index.html (filters omitted for clarity)
<md-list-item my-task-directive ng-repeat="task in TasksCtrl.tasks track by task.id">
TasksCtrl
TasksService.index().then(function(tasks) {
vm.tasks = tasks.data ? tasks.data : [];
});
$scope.$on('task-updated', function() {
var newTask = TasksService.getUpdatedTask();
$timeout(function() {
vm.tasks.splice(newTask.index, 1, newTask.task);
});
});
TaskSidebarCtrl
$scope.$watch(function() {
return TasksService.getSelectedTask();
}, function (newVal, oldVal) {
if (newVal !== oldVal) {
/* Using copy here to prevent index view from updating during editing */
vm.selectedTask = angular.copy(newVal);
vm.index = TasksService.getSelectedTaskIndex();
}
});
TasksService.update(vm.selectedTask).then(function(data) {
// handle notifications etc., then...
TasksService.updateTaskInIndex(vm.index, data.data);
});
TasksService
var selectedTask = {};
var indexOfTask;
var updatedTask = {};
var updatedIndex;
this.setSelectedTask = function(task, index) {
selectedTask = task;
indexOfTask = index;
};
this.getSelectedTask = function() {
return selectedTask;
};
this.getSelectedTaskIndex = function() {
return indexOfTask;
};
this.getUpdatedTask = function() {
return {
'index': updatedIndex,
'task': updatedTask
};
};
this.updateTaskInIndex = function(index, task) {
updatedTask = task;
updatedIndex = index;
$rootScope.$broadcast('task-updated');
};
Using a basic angular.copy (with destination) instead of TasksService.updateTaskInIndex(vm.index, data.data) in TaskSidebarCtrl's update function results in the one-time bound properties not being updated in the index view due to the one-time binding constraint. While this approach functions without track by task.id, we are reluctant to make such compromises if feasible, and wish to maintain the use of one-time binding.
Is there a workaround?