<!doctype html> <html ng-app="Demo"> <head> <meta charset="utf-8" /> <title> Binding A Single Directive To Multiple Priorities On The Same Element In AngularJS </title> <style type="text/css"> a[ ng-click ] { cursor: pointer ; text-decoration: underline ; } li.active { background-color: #FFD0D0 ; } </style> </head> <body ng-controller="AppController"> <h1> Binding A Single Directive To Multiple Priorities On The Same Element In AngularJS </h1> <ul> <!-- The bnFriends directive is going to be defined at two different priorities that allow the same directive to link both BEFORE and AFTER the ngRepeat directive does its transclusion. --> <li bn-friends ng-repeat="friend in friends"> {{ friend.name }} </li> </ul> <!-- Load scripts. --> <script type="text/javascript" src="../../vendor/jquery/jquery-2.1.0.min.js"></script> <script type="text/javascript" src="../../vendor/angularjs/angular-1.2.22.min.js"></script> <script type="text/javascript"> // Create an application module for our demo. var app = angular.module( "Demo", [] ); // -------------------------------------------------- // // -------------------------------------------------- // // I control the root of the application. app.controller( "AppController", function( $scope ) { $scope.friends = [ { id: 1, name: "Sarah" }, { id: 2, name: "Tricia" }, { id: 3, name: "Joanna" }, { id: 4, name: "Kim" } ]; } ); // -------------------------------------------------- // // -------------------------------------------------- // // Typically, we would only define a directive once; however, by defining it // twice, with different configurations, we can actually bind a "single" directive // to two different priorities in the same compilation and linking phase. // -- // NOTE: This directive will execute a priority 1001 and 999; since the ngRepeat // directive executes at priority 1000, this directive - bnFriends - will compile // and link on both "sides" of the ngRepeat directive. app .directive( "bnFriends", function( $compile ) { // I compile the current element. Since this executes with priority // 1001, it will be able to compile/alter the element BEFORE ngRepeat // compiles and transcludes it. function compile( tElement, tAttributes ) { console.info( "High priority compiling" ); tElement.text( tElement.text() + " is my good friend!" ); return( link ); // Because this executes before ngRepeat, it means that we have // an opportunity to set up a controller that will be available // to the post-ngRepeat phase. function link( scope, element, attributes, controller ) { console.info( "High priority linking" ); controller.message = "hello world"; }; } // Return the directive configuration. // -- // NOTE: This version of the directive, with priority 1001, will // execute before the ngRepeat directive. return({ compile: compile, controller: angular.noop, priority: 1001, restrict: "A" }); } ) .directive( "bnFriends", function() { // Since this executes with a lower priority than ngRepeat, it means // that this version of the directive will link for every node that // the ngRepeat directive will transclude and link. function link( scope, element, attributes, controller ) { console.info( "Low priority linking [ %d ][ %s ]", scope.$index, controller.message ); // Set up some simple mouse-behaviors for testing. element.hover( function handleMouseEnter() { element.addClass( "active" ); }, function handleMouseLeave() { element.removeClass( "active" ); } ); } // Return the directive configuration. Notice that we are "requiring" // the controller that our other version instantiated and defined. // -- // NOTE: This version of the directive, with priority 999, will // execute after the ngRepeat directive. return({ link: link, priority: 999, require: "bnFriends", restrict: "A" }); } ) ; </script> </body> </html>