3

I'm sure this is going to be a "dont do that!" but I am trying to display the style on an angular element.

<div ng-repeat="x in ['blue', 'green']" class="{{x}}">
        <h3 insert-style>{{theStyle['background-color']}}</h3>
</div>

Result would be

<div class='blue'><h3>blue(psudeo code hex code)</h3></div>
<div class='green'><h3>green(psudeo code hex code)</h3></div>

I basically need to get the style attributes and display them.

Directive Code...

directives.insertStyle = [ function(){
    return {
       link: function(scope, element, attrs) {
           scope.theStyle = window.getComputedStyle(element[0], null);
       }
}   
}];

Fiddle example: http://jsfiddle.net/ncapito/G33PE/

4

4 回答 4

6

My final solution (using a single prop didn't work, but when I use the whole obj it works fine)...

Markup

<div insert-style  class="box blue">
  <h4 > {{ theStyle['color'] | toHex}} </h4>
</div>

Directive

directives.insertStyle = [ "$window", function($window){
    return {
        link: function(scope, element, attrs) {
            var elementStyleMap = $window.getComputedStyle(element[0], null);
            scope.theStyle = elementStyleMap
        }
    }   
}];
于 2013-12-24T13:06:04.167 回答
1

Eureka!

http://jsfiddle.net/G33PE/5/

var leanwxApp = angular.module('LeanwxApp', [], function () {});

var controllers = {};
var directives = {};
directives.insertStyle = [ function(){
    return {
       link: function(scope, element, attrs) {
           scope.theStyle = window.getComputedStyle(element[0].parentElement, null)
       }
}   
}];

leanwxApp.controller(controllers);
leanwxApp.directive(directives);

So that just took lots of persistence and guessing. Perhaps the timeout is unnecessary but while debugging it seemed I only got the style value from the parent after the timeout occurred.

Also I'm not sure why but I had to go up to the parentElement to get the style (even though it would realistically be inherited (shrug)?)

Updated fiddle again

Did one without the timeout but just looking at the parentElement for the style and it seems to still work, so scratch the suspicions about the style not being available at all, it's just not available where I would expect it.

Also holy cow there are a lot of ways to debug in Chrome: https://developers.google.com/chrome-developer-tools/docs/javascript-debugging

I used

debugger;

statements in the code to drop in breakpoints without having to search all the fiddle files.

One more quick update

The code below comes out of Boostrap-UI from the AngularUI team and claims to provide a means to watch the appropriate events (haven't tried this but it looks like it should help).

http://angular-ui.github.io/bootstrap/

/**
 * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete.
 * @param  {DOMElement} element  The DOMElement that will be animated.
 * @param  {string|object|function} trigger  The thing that will cause the transition to start:
 *   - As a string, it represents the css class to be added to the element.
 *   - As an object, it represents a hash of style attributes to be applied to the element.
 *   - As a function, it represents a function to be called that will cause the transition to occur.
 * @return {Promise}  A promise that is resolved when the transition finishes.
 */
.factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {

  var $transition = function(element, trigger, options) {
    options = options || {};
    var deferred = $q.defer();
    var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"];

    var transitionEndHandler = function(event) {
      $rootScope.$apply(function() {
        element.unbind(endEventName, transitionEndHandler);
        deferred.resolve(element);
      });
    };

    if (endEventName) {
      element.bind(endEventName, transitionEndHandler);
    }

    // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur
    $timeout(function() {
      if ( angular.isString(trigger) ) {
        element.addClass(trigger);
      } else if ( angular.isFunction(trigger) ) {
        trigger(element);
      } else if ( angular.isObject(trigger) ) {
        element.css(trigger);
      }
      //If browser does not support transitions, instantly resolve
      if ( !endEventName ) {
        deferred.resolve(element);
      }
    });

    // Add our custom cancel function to the promise that is returned
    // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,
    // i.e. it will therefore never raise a transitionEnd event for that transition
    deferred.promise.cancel = function() {
      if ( endEventName ) {
        element.unbind(endEventName, transitionEndHandler);
      }
      deferred.reject('Transition cancelled');
    };

    return deferred.promise;
  };

  // Work out the name of the transitionEnd event
  var transElement = document.createElement('trans');
  var transitionEndEventNames = {
    'WebkitTransition': 'webkitTransitionEnd',
    'MozTransition': 'transitionend',
    'OTransition': 'oTransitionEnd',
    'transition': 'transitionend'
  };
  var animationEndEventNames = {
    'WebkitTransition': 'webkitAnimationEnd',
    'MozTransition': 'animationend',
    'OTransition': 'oAnimationEnd',
    'transition': 'animationend'
  };
  function findEndEventName(endEventNames) {
    for (var name in endEventNames){
      if (transElement.style[name] !== undefined) {
        return endEventNames[name];
      }
    }
  }
  $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);
  $transition.animationEndEventName = findEndEventName(animationEndEventNames);
  return $transition;
}]);
于 2013-07-09T20:04:03.317 回答
1

The issue you'll face is that getComputedStyle is considered a very slow running method, so you will run into performance issues if using that, especially if you want angularjs to update the view whenever getComputedStyle changes.

Also, getComputedStyle will resolve every single style declaration possible, which i think will not be very useful. So i think a method to reduce the number of possible style is needed.

Definitely consider this an anti-pattern, but if you still insist in this foolishness:

module.directive('getStyleProperty', function($window){
    return {
        //Child scope so properties are not leaked to parent
        scope : true,
        link : function(scope, element, attr){
            //A map of styles you are interested in
            var styleProperties = ['text', 'border'];
            scope.$watch(function(){
                //A watch function to get the styles
                //Since this runs every single time there is an angularjs loop, this would not be a very performant way to do this
                var obj = {};
                var computedStyle = $window.getComputedStyle(element[0]);
                angular.forEach(styleProperties, function(value){
                    obj[value] = computedStyle.getPropertyValue(value);
                });
                return obj;
            }, function(newValue){
                scope.theStyle = newValue;
            });
        }
    }
});
于 2013-07-10T02:32:06.947 回答
0

This solution works if you don't HAVE to have the directive on the child element. If you just place the declaration on the ng-repeat element itself, your solution works:

<div insert-style ng-repeat="x in ['blue', 'green']" class="{{x}}">

Fiddle

于 2013-07-09T17:48:29.387 回答