Search code examples
angularjsangularjs-directiveangular-ng-if

Angular Custom Directive - How to make it Behave Like Ng-if


I'm trying to build a custom directive to either show items on a page or completely remove them based on authorization data, and I'm clearly missing something, 'cuz its not working and I'm having a hard time figuring out why.

I've been following the guide here: http://adamalbrecht.com/2014/09/22/authorization-with-angular-and-ui-router/

Which said to take a copy of the NgIf source code, and modify it (as I have below).

I'm really confused because not only is it not working as expected, but even when I put break-points within the function calls in the directive, it never hits those break points.

I'm not sure what I'm doing wrong. Is there something else not documented within the steps that I need to do in order to use a custom directive, or did I somehow miss a step? Regular ng-if's work on the same page just fine.

EDIT: I should note that AuthorizeService.isAuthorizedForOne returns a promise value which is either true or false. This works fine in other contexts.

'use strict';
/**
 * @ngdoc directive
 * @name ngIfPermission
 * @restrict A
 *
 * @description
 **/

var ngIfPermissionDirective = ['$animate', function($animate, AuthorizeService) {
  return {
    multiElement: true,
    transclude: 'element',
    priority: 600,
    terminal: true,
    restrict: 'A',
    $$tlb: true,
    link: function($scope, $element, $attr, ctrl, $transclude) {
      console.log("I am here");
      var block, childScope, previousElements;
      $attr.$observe("ngIfPermission", function(value){
        console.log("I am there");
        var permissions = JSON.parse(value.replace(/'/g, '"'));
        AuthorizeService.isAuthorizedForOne(permissions).then(function(auth){
            if (!childScope) {
              $transclude(function(clone, newScope) {
                childScope = newScope;
                clone[clone.length++] = document.createComment(' end ngIfPermission: ' + $attr.ngIfPermission + ' ');
                // Note: We only need the first/last node of the cloned nodes.
                // However, we need to keep the reference to the jqlite wrapper as it might be changed later
                // by a directive with templateUrl when its template arrives.
                block = {
                  clone: clone
                };
                $animate.enter(clone, $element.parent(), $element);
              });
            }
          },
          function(err) {
            if (previousElements) {
              previousElements.remove();
              previousElements = null;
            }
            if (childScope) {
              childScope.$destroy();
              childScope = null;
            }
            if (block) {
              previousElements = getBlockNodes(block.clone);
              $animate.leave(previousElements).then(function() {
                previousElements = null;
              });
              block = null;
            }
        });
      });
    }
  };
}];

How I'm referencing it:

<div ng-if-permission="['OOGY']">You can see this.</div>
<div ng-if-permission='["BOOGY"]'>or this</div>

Solution

  • I think you might got the declaration for the directive wrong.

    app.directive( 'ngIfPermissionDirective', function($animate){
        //directive here
    ));
    

    DEMO http://plnkr.co/edit/BhubrfMAiW3K4ANI3pTx