I have a pretty complex app for collaborative and interactive database creation and have run into performance issues. The app uses ui-router with various nested views... The states look like this:
$stateProvider
.state('origin', {
url: '/',
templateUrl: "/angular/databases.ejs",
controller: 'DatabasesController'
})
.state('databases', {
url: '/databases',
templateUrl: "/angular/databases.ejs",
controller: 'DatabasesController'
})
.state('collections', {
url: '/collections',
templateUrl: "/angular/collections.ejs",
controller: 'CollectionsController'
})
.state('dataviews', {
url: '/dataviews',
templateUrl: "/angular/dataviews.ejs",
controller: 'DataviewsController',
})
.state('dataviews.listView', {
url: '/listView',
templateUrl: '/angular/dataListView.ejs',
controller: 'DataListViewController'
})
.state('dataviews.listView.theModal', {
onEnter: ['$uibModal', '$state', 'ActiveStorage', function($uibModal, $state, ActiveStorage) {
console.log('Open modal');
$uibModal.open({
templateUrl: '/angular/viewItemModal.ejs',
animation: false,
background:false,
windowTemplateUrl: '',
controllerAs: '$ctrl',
controller: 'DataItemViewController',
size: 'lg',
}).result.finally(function() {
$state.go('^');
});
}]
})
.state('dataviews.listView.editItem', {
onEnter: ['$uibModal', '$state', 'ActiveStorage', function($uibModal, $state, ActiveStorage) {
console.log('Open modal');
$uibModal.open({
templateUrl: '/angular/editItemPanel.ejs',
animation: false,
background:false,
windowTemplateUrl: '',
controllerAs: '$ctrl',
controller: 'DataItemEditViewController',
size: 'lg',
}).result.finally(function() {
$state.go('^');
});
}]
})
However, the items in the list view are many, and rely on some complex filtering. I have a (probably) ugly bit of code in the list view that looks like this and provides the main ng-repeat that generates the filtered list:
<div
ng-repeat="(key, value) in $parent.filteredItems2 = (filteredItems = (items | orderBy: storageDefaultOrderBy() | showItems: state.selectedGroup._id: user : state.set : navigation : sortBy : groupType : hideComplete : selectedCategoryId : classes | filter: dateMagicFilter ) | orderBy: 'groupBy.id' | groupBy: 'groupBy.title' )"
The showItems filter is a custom filter that takes a lot of custom user inputs to do things like: toggle the color of items, group items by different properties, filter items based on completed status, or by user ids. The groupBy filter is from angular-filter.
A major problem I run into is when I open the edit item modal, every key press in a field triggers digest loops and this leads to unacceptably long lags in the characters appearing on the screen.
From list view I click an item in the list and use a service to store the active item using a simple getter/setter service like this:
.service('ActiveItem', function(){
var selected = {};
this.setActiveItem = function(data) {
selected = data;
}
this.getActiveItem = function() {
return selected;
}
})
The controller for the modal, in this case DataItemEditViewController uses this service to get the concerned item, which is then bound to the view:
$scope.item = ActiveItem.getActiveItem();
I have used Batarang to try and find the source of my problems and I see that there is a watcher text as follows:
function (c, d, e, f) {e=a(c,d,e,f); return b(e, c, d)
This can run up to 60+ times (if I type a couple of words in) and takes up to 1000ms to complete.
My hunch is that one way around this problem is to somehow isolate my modal $scope - or at least some way of allowing me to work on that item without triggering so many digest loops... In the meanwhile, I'm busily trying to make my filters and code (more generally) more efficient, but I feel that most of these fixes (of which many are no doubt required) will only ever have a superficial effect.
I look forward to any guidance available and can share more code if that would help (there's a lot of it so I've been trying to share what seems most critical to me).
Thanks in advance!