简体   繁体   中英

Can directives be used outside of HTML tags?

Since learning Angular a few months ago, I was under the impression that ` directives are special functions which are activated by placing a keyword in an HTML tag in one of two ways - either as an element, as an attribute.

For example:

<my-directive>Something</my-directive>

or

<div my-directive></div>

However, in a Git project I came across , I'm seeing a directive used in a totally different way and I don't understand how it works.

The directive is supposedly activated just by adding a key-value of css: {} to a .state() function in ui-router.

For instance:

.state('state1', {
      url: '/state',
      controller: 'StateCtrl',
      templateUrl: 'views/my-template.html',
      data: {
        css: 'styles/style1.css'
      }
    })

How does this "directive" works?

----------

The Javascript source of the directive copied from the Git project, so it's preserved in this question:

/**
 * @author Manuel Mazzuola
 * https://github.com/manuelmazzuola/angular-ui-router-styles
 * Inspired by https://github.com/tennisgent/angular-route-styles
 */

'use strict';

angular
  .module('uiRouterStyles', ['ui.router'])
  .directive('head', ['$rootScope', '$compile', '$state', '$interpolate',
    function($rootScope, $compile, $state, $interpolate) {
      return {
        restrict: 'E',
        link: function(scope, elem){
          var start = $interpolate.startSymbol(),
              end = $interpolate.endSymbol();
          var html = '<link rel="stylesheet" ng-repeat="(k, css) in routeStyles track by k" ng-href="' + start + 'css' + end + '" >';
          elem.append($compile(html)(scope));

          // Get the parent state
          var $$parentState = function(state) {
            // Check if state has explicit parent OR we try guess parent from its name
            var name = state.parent || (/^(.+)\.[^.]+$/.exec(state.name) || [])[1];
            // If we were able to figure out parent name then get this state
            return name && $state.get(name);
          };

          scope.routeStyles = [];
          $rootScope.$on('$stateChangeStart', function (evt, toState) {
            // From current state to the root
            scope.routeStyles = [];
            for(var state = toState; state && state.name !== ''; state=$$parentState(state)) {
              if(state && state.data && state.data.css) {
                if(!Array.isArray(state.data.css)) {
                  state.data.css = [state.data.css];
                }
                angular.forEach(state.data.css, function(css) {
                  if(scope.routeStyles.indexOf(css) === -1) {
                    scope.routeStyles.push(css);
                  }
                });
              }
            }
            scope.routeStyles.reverse();
          });
        }
      };
    }
  ]);

The directive is named after HTML <head> tag. It presumes that your html page contains a <head> tag and treats that as your directive declaration. It also presumes that the angular ng-app declaration is placed on <html> tag.

The directive does nothing but erases and writes css <link> tags within the html head tag content everytime the state changes.

Note that it is not preferable to name your directives after native html tags. This is why you see angular directives prepended by 'ng' so as to clearly demarcate them as angular tags. Otherwise, it can lead to confusion, as you have yourself found out with trying to understand this piece of git code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM