简体   繁体   中英

Eval directive's parameters angular

I have this html template :

<div width-watcher>
    <div parallax-bg parallax-active="!(tablet || mobile)">
        ...
    </div>
</div>

width-watcher exposes 3 boolean values: mobile, tablet and screen. No directive options here. I want to evaluate the expression "!(tablet || mobile)" to pass it to my second directive parallax-bg , to disable parallax on mobile devices.

I've tried the following (in parallax-bg ):

  • Use scope.$eval(attr.parallaxActive) returns "undefined"
  • Use directly scope.parallaxActive with :
    • "&" => returns a function, when executed returns "undefined"
    • "=" => returns "undefined"
    • "@" => returns "!(tablet || mobile)"

And I ran out of ideas. As english isn't my native language, I've probably missed some solutions on Google.

This is the code of my background-parallax directive :

.directive('parallaxBackground', function($window) {
return {
    transclude: true,
    template: '<div ng-transclude></div>',
    scope: {
        parallaxRatio: '@',
        parallaxOffset: '@',
    },
    link: function(scope, elem, attrs) {
        var scopeActive = scope.$eval(attrs.parallaxActive);
        var ...
        if(scopeActive){
            ...
        }
    }
};

Your first method, scope.$eval(attr.parallaxActive) is correct, but won't work if you bind the attribute value to your directive's scope.

Working example: JSFiddle

angular.module('myApp').directive(function() {
  return {
    link: postLink,
    template: '<ng-transclude></ng-transclude>',
    transclude: true
  };

  function postLink(scope, iElement, iAttrs) {
    alert(scope.$eval(iAttrs.parallaxActive));
  };
}

That said, my recommendation would be to turn your widthWatcher directive into a service using the factory strategy. This way, you can just inject it into any controller, directive, filter or other service and determine the screen type without relying on scope.

Working example: JSFiddle

angular.module('myApp', [])
  .factory('$widthWatcher', widthWatcherFactory)
  .directive('parallaxBg', parallaxBgDirective)
;

function widthWatcherFactory() {
  return {
    isMobile: isMobile,
    isScreen: isScreen,
    isTablet: isTablet
  };

  function getWidth() {
    return window.innerWidth || document.body.clientWidth;
  }

  function isMobile() {
    return getWidth() < 600;
  }

  function isScreen() {
    return getWidth() > 960;
  }

  function isTablet() {
    return !isMobile() && !isScreen();
  }
}

function parallaxBgDirective($widthWatcher) {
  return {
    link: postLink,
    template: '<ng-transclude></ng-transclude>',
    transclude: true
  };

  function postLink(scope, iElement, iAttrs) {
    alert($widthWatcher.isScreen());
  };
}

UPDATE

To address the comment about values being undefined when the parallaxBg link function is called, I updated the JSFiddle to show the order in which link functions are called.

In order to understand what is going on, you need to understand how directives are compiled .

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