Search code examples
angularjsangularjs-directiveevent-handlingangular-ng-if

element.on('click') on a directive within ng-if doesn't work


I use a directive on links to provide a modal login, if the user isn't logged in. And it works fine for all usecases until now. In a new case the directive is part of a ng-if section.

On the snippet the first link works fine, the second doesn't work. The element.on('click', function(evt) {…}) will never called. And the permissions are not checked and no modal login will prompt to the user.

Ok, if I use ng-show instead of ng-if, both links works. Because ng-show doesn't remove the element from the DOM and it doesn't create a child scope like ng-if. But in my usecase I must use ng-if. What can I do? How can I provide a click event, which works within a ng-if and other ng-x directives too?

var app = angular.module('myapp', []);

app.controller('MyCtrl', function($timeout) {
  // something stupid here
  var vm = this;
  vm.bar = false;
  $timeout(function() {
    vm.bar = true;
  });
});

/**
 * I need an isolate scope, because some user state checks
 * will take place in the directive. And there are different
 * login forms based on type and other attributes.
 */
app.directive('modalLogin', function() {
  return {
    restrict: 'A',
    scope: {
      type: '@mlType'
    },
    compile: function(element, attrs) {
      if (element[0].nodeName !== ('A')) {
        // use directive only at links
        return function() {};
      }

      return function(scope) {
        function checkPermissions() {
          // do the magic here
          alert('foo');
        }

        element.on('click', function(evt) {
          evt.preventDefault();
          checkPermissions();
        })
      }
    }
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<section ng-app="myapp" ng-controller="MyCtrl as FOO">
  <div>
    <!-- it works -->
    <a href="/myroute/" modal-login ml-type="simple-login">Klick me, I'm working well</a>
  </div>

  <!-- it doesn't work -->
  <div ng-if="FOO.bar">
    <a href="/another-route/" modal-login ml-type="theme-login">Klick me, I'm nested within a ng-if</a>
  </div>
</section>


Solution

  • Use link instead of compile.

    link: function(scope, element) {
    
      function checkPermissions() {
        alert('foo');
      }
    
      element.on('click', function(evt) {
        evt.preventDefault();
        checkPermissions();
      });
    
    }