Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it bad practice to use $apply when updating data in one directive that needs to be reflected in another directive?

I have a container and children directives that both affect data that is referenced via a service. The general idea is that I want to be able to click on the child directives and have them be "selected" per the below rules. And to be able to click on the container directive to clear the selections.

The basic rules are:

  • only have one child selected at a time, unless shift-clicking a child
  • clicking a child (no shift key), when others are selected, will clear the others and select the current one
  • clicking a child that is already selected will not unselect the child
  • shift clicking a child will toggle that child only
  • clicking outside of a child (in the container) should clear all selections

All of the rules above were pretty straightforward to implement. The main trouble I ran into was for the last rule. Clicking the container would actually set the selected value to false, however the UI would not update until the next user action. Having the container's click event wrap the call to the service in an $apply, "fixed it".

.directive('myContainer', function (dataService) {
    return {
        restrict: 'A',
        scope:{data:"="},
        link:function(scope, element, attrs){
            element.bind('click', function() {
                scope.$apply(function() {
                    dataService.clearSelectedChildren();
                });
            });
        }
    };
})

However, I seem to have ready that $apply is typically for use with an external update (outside of the angular world) to data (i.e. an async call to a remote server)? So, am I misusing the apply? If so, how else might I be able to accomplish my goals?

Here is a working JSFiddle for reference.

like image 482
Steve Avatar asked Apr 10 '15 16:04

Steve


1 Answers

When you bind your own event handlers ...the event is outside of angular. Within directives like ng-click angular does pretty much the same thing you are doing. In other words you do need to notify angular to run a digest

like image 56
charlietfl Avatar answered Nov 09 '22 16:11

charlietfl