0

I'd like to make a directive that keeps an element focussed. To do this I just attach a listener to the focusout event and call focus() when it first. This works great, but if I transition to another state and this directive goes out of scope, I don't want it to keep fighting for the focus.

If I do a

$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState) {

then I can get notified, but I don't know the current state that was rendering my directive.

Paul Tarjan
  • 48,968
  • 59
  • 172
  • 213

2 Answers2

0

I found a solution. Just read the $state.current.

angular.module('constant-focus', [])
.directive('constantFocus', function($rootScope, $state) {
  // http://stackoverflow.com/questions/25879759/prevent-keyboard-from-closing/25899264#25899264
  return {
    restrict: 'A',
    scope: {
      constantFocus: '=',
    },
    link: function($scope, element) {
      const curState = $state.current;

      const focusFunction = function() {
        if (!$scope.constantFocus) {
          unregister();
          element[0].blur();
        } else {
          element[0].focus();
        }
      };

      /* jslint latedef:false */
      const unregister = () => {
        element[0].removeEventListener('focusout', focusFunction);
      };

      const register = () => {
        element[0].addEventListener('focusout', focusFunction);
      };

      $scope.$watch('constantFocus', enabled => {
        if (enabled) {
          register();
        }
        focusFunction();
      });

      $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState) {
        if (fromState === curState) {
          unregister();
        } else if (toState === curState) {
          register();
        }
      });
    },
  };
});
Paul Tarjan
  • 48,968
  • 59
  • 172
  • 213
  • This isn't sufficient. You would also need to listen for `$scope`'s `$destroy` to remove the `$stateChangeStart` listener. Otherwise, if you leave this state and then come back, you'd have two state listeners. – Anid Monsur Oct 07 '15 at 05:15
0

Use the directive's $scope's $destroy event to detach the listener. You can do this in either the link or controller functions.

$scope.$on('$destroy', function() {
  // Detach focusout listener here
});
Anid Monsur
  • 4,538
  • 1
  • 17
  • 24