Targaryen Targaryen - 1 month ago 14
AngularJS Question

Todo list takes 30 seconds to appear

I am using Angular 1.5.8. I have a component within a component. The parent component has a div with

ng-show
that decides when the child component should appear.

The parent component...

function ScheduleController() {
var ctrl = this;
ctrl.openTodo = function() {
ctrl.isTodoVisible = true;
}
}

angular.module('myApp').component('userTodoDisplay', {
template: `
<button click="ctrl.$openTodo()"></button>
<div class="my-todo" ng-show="$ctrl.isTodoVisible">
<eb-todo schedule-id="$ctrl.selectedScheduleId" connected-to-project="$ctrl.selectedScheduleConnectedToProject"
permissions="$ctrl.User.Role" close-click="$ctrl.closeTooltip()"></eb-todo>
</div>
`,
controller: [UserTodoDisplayController]
});


The following child component takes almost 30 seconds to appear once I set
isTodoVisible
to
true
.

function TodoController() {
//
}

angular.module('myApp').component('ebTodo', {
bindings: {
scheduleId: '<',
connectedToProject: '<',
statuses: '<',
permissions: '<',

detailsClick: '&',
printClick: '&',
editClick: '&',
shareClick: '&',
deleteClick: '&',
copyClick: '&',
toggleConnectClick: '&',
setStatusClick: '&',
closeClick: '&'
},
template: `
<div>
<button ng-click="$ctrl.closeClick()">Close</button>

<button class="glyphicon glyphicon-th-list" ng-show="$ctrl.permissions.CanViewTask"
ng-click="$ctrl.detailsClick({data: $ctrl.scheduleId})"></button>

<button class="glyphicon glyphicon-print" ng-show="$ctrl.permissions.CanViewTask"
ng-click="$ctrl.printClick({data: $ctrl.scheduleId})"></button>

<button class="glyphicon glyphicon-pencil" ng-show="$ctrl.permissions.CanEditTask"
ng-click="$ctrl.editClick({data: $ctrl.scheduleId})"></button>

<button class="glyphicon glyphicon-envelope" ng-show="$ctrl.permissions.CanEditTask"
ng-click="$ctrl.shareClick({data: $ctrl.scheduleId})"></button>

<button class="glyphicon glyphicon-trash" ng-show="$ctrl.permissions.CanDeleteTask"
ng-click="$ctrl.deleteClick({data: $ctrl.scheduleId});"></button>

<button ng-show="$ctrl.permissions.CanAddTask"
ng-click="$ctrl.copyClick({data: $ctrl.scheduleId})">Copy</button>

<button ng-show="$ctrl.connectedToProject" ng-click="$ctrl.toggleConnectClick({data: $ctrl.scheduleId})">Disconnect</button>
<button ng-hide="$ctrl.connectedToProject" ng-click="$ctrl.toggleConnectFromTooltip({data: $ctrl.scheduleId})">Connect</button>
</div>
`,
controller: [ScheduleTooltipController]
});


I have seen other issues similar to this one on SO, but those issues involved ngAnimate. I am not using ngAnimate.

I have created all of my other components the same way I created this one. I am only having trouble getting the component to appear now that I am using
ng-show
. Why does the
ebTodo
component take approx. 30 seconds to appear after I set
isTodoVisible
to
true
?

Answer

There are digest-aware alternatives to common asynchronous operations in Angular. For click events in templates ng-click directive is convenient:

<button ng-click="$ctrl.openTodo()">

For callbacks that are asynchronously called from places that aren't aware of scope digests (third-party code), a digest should be triggered manually with scope $apply method:

ctrl.openTodo = function() {
    $scope.$apply(function () {
        ctrl.isTodoVisible = true;
    });
}

This approach may be incompatible with digest-aware callers (e.g. ng-click). Digest cycle will be triggered twice and result in $rootScope:inprog Action Already In Progress error.

To safely trigger digest in both digest-aware and digest-unaware calling contexts, $evalAsync method can be used instead:

ctrl.openTodo = function() {
    $scope.$evalAsync(function () {
        ctrl.isTodoVisible = true;
    });
}
Comments