1

I have a simple directive

app.directive('cell', function() 
{
    return {
        restrict: 'C',
        link: function(scope, element, attrs)
        {
            element.bind('click', function()
            {
                element.addClass('selected');
            });

            element.bind('blur', function()
            {
                console.log('blur');
                element.removeClass('selected');
            });
        }
    }
});

And my cell is

<div class="shift">
    <div class="cell" ng-repeat="cell in cells"></div>
</div>

The click binds fine, but the blur doesn't. It is never triggered!

10
  • Are you omitting your cell contents? Blur only fires when a control has focus and loses it to another control. If you can't use TAB to get to the control, it can't gain focus and there will be no blur event. Usually only input type controls and buttons can get focus. Commented Jul 20, 2014 at 19:35
  • Okay okay, thanks! So is there a way to fire something up when you click anywhere outside of that element? That is without using $document cause that will just create an infinite number of events~ Commented Jul 20, 2014 at 19:36
  • You can use mouseleave to detect when the mouse moves out of the element, but you'd have to register a click handler on the document and trigger the change when you detect a click that is not over that element. What are you trying to do? There may be a better way. Off the top of my head I would think you could maintain a 'selectedCell' property on your scope and the ng-click on your div would just be ng-click="selectedCell = cell". Then on your div ng-class="{selected : cell == selectedCell}" Commented Jul 20, 2014 at 19:43
  • Do you need to set selected class when user click on element itself, or when user set focus on any input in cell? Commented Jul 20, 2014 at 19:45
  • This is suppose to be like an excel type cell. So upon clicking, I want to select the cell (just adding border). And when you click anywhere else (could be another cell, or somewhere else), I want to deselect the cell and remove the border Commented Jul 20, 2014 at 19:46

2 Answers 2

3

Just because you click on a div, it doesn't mean it gets keyboard focus. And if it doesn't get keyboard focus (as it is not editable), it can't lose it and thus can't blur.

An alternative approach could be the following:
Upon clicking on any .cell element, remove the selected class from every element that has it and then add it to the clicked element.

E.g.:

.directive('cell', function cellDirective($window) {
  return {
    restrict: 'C',
    link: function cellPostLink(scope, elem, attrs) {
      elem.on('click', onClick);
      scope.$on('$destroy', onDestroy);

      function onClick() {
        Array.prototype.forEach.call(
            $window.document.querySelectorAll('.selected'),
            function (el) { angular.element(el).removeClass('selected'); });
        elem.addClass('selected');
      }

      function onDestroy() {
        elem.off('click', onClick);
      });
    }
  };
});

See, also, this short demo.


NOTES:

  1. Depending on the browsers you are supporting and on whether you are using jQuery or not the code above might need modifications.

  2. An alternative approach would be to register a click-listener on the document and remove the selected class from any element if the clicked element was a .cell. In that case, you need to take care to only register the listener once and not for every instance of .cell.

  3. It is a good practise to always clean-up your listeners upon scope's destruction, in order to prevent memory leaks. You can use scope.$on('$destroy', callback) to remove any event listeners registered on elements.

Sign up to request clarification or add additional context in comments.

1 Comment

I was doing this originally. but the problem is that if I click on a cell, and then click somewhere else (i.e. not another cell), then the cell will not be deselected. And I want it to be deselected.
0

You can handle chidlren focus and blur events in directive:

element.children().bind('focus', function() {
  element.addClass('selected');
});

element.children().bind('blur', function() {
  console.log('blur');
  element.removeClass('selected');
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.