代码之家  ›  专栏  ›  技术社区  ›  LocustHorde

如何在decorator中访问ngStyle键和值?

  •  6
  • LocustHorde  · 技术社区  · 9 年前

    我的申请表中有一个颜色名称列表。

    let colours = {
      mango: '#e59c09',
      midnight: '#1476a0'
    };
    

    ngStyle公司 decorating 这个 ngStyle公司 ngStyle公司 属性,但它以字符串的形式出现(可以理解)。 JSON.parse() 由于绑定一次等原因,它并不总是有效的JSON字符串,因此不适用于它。。。

    我只是想介入,迭代所有样式键,如果它包含 color

    我似乎无法访问任何 ngStyle公司 source code ng-style="{color: ctrl.textColor}" -里面什么都没有 ngStyle公司 ctrl.textColour .我看错地方了吗?

    键值,以便我可以将自定义颜色更改为其十六进制代码?

    $provide.decorator('ngStyleDirective', function($delegate) {
    
        let directive = $delegate[0];
        let link = directive.link;
    
        directive.compile = function(element, attrs) {
    
            // Expression here is a string property
            let expression = attrs.ngStyle;
    
            return function(scope, elem, attr) {
    
              // How do I iterate over and update style values here?
    
              // Run original function
              link.apply(this, arguments);
    
            }
    
          }
    
          return $delegate;
    
    });
    

    我尝试使用正则表达式提取模式等并检查元素,但是,这似乎是解决问题的错误方法,因为我必须手动更新字符串并将其传递给基链接函数。

    plnkr example

    如果有更好的方法来做我想做的事情,请告诉我。

    2 回复  |  直到 9 年前
        1
  •  4
  •   Sᴀᴍ Onᴇᴌᴀ    9 年前

    无论如何,我如何访问ng样式的键值,以便我可以将自定义颜色更改为其十六进制代码?

    这个

    directive.compile = function(element, attrs) {
      let expression = getExpressions(attrs.ngStyle);
      attrs.ngStyle = expression;
    
      return function(scope, elem, attr) {
        // Run original function
        link.apply(this, arguments);  
      }
    }
    

    JSON.parse()

    JSON.parse() ng样式 属性需要用单引号分隔(不过如果真的需要,可以尝试转义双引号…)

    <p ng-style='{ "color": "#e59c09" }'>Hello {{name}}!</p>
    <p ng-style='{ "padding": "20px 10px", "background-color": "#1476a0", "color": "#ddd" }'>It is dark here</p>
    

    然后解析该字符串应该生成一个有效的对象,并且 Object.keys() 颜色 。如果密钥包含 颜色 Array.indexOf 可用于检查值是否存在于 颜色 String.replace() 可用于替换变量的值(即 ).

    function getExpressions(str) {
        var parsed = JSON.parse(str);
        Object.keys(parsed).forEach(function(key) {
            if (key.indexOf('color') > -1) {
                if (Object.keys(colours).indexOf(parsed[key]) > -1) {
                    str = str.replace(parsed[key], colours[parsed[key]])
                }
             }
        });
        return str;
    }
    

    请参见下面的示例。顺便说一句,我必须删除未使用的变量 在函数范围内声明 getExpressions() Here is an updated plunker

    let app = angular.module('plunker', []);
    let colours = {
      mango: '#e59c09',
      midnight: '#1476a0'
    };
    app.controller('MainCtrl', function($scope) {
      $scope.name = 'World';
    });
    app.config(function($provide) {
      // Extract colour values from the string
      function getExpressions(str) {
        var parsed = JSON.parse(str);
        Object.keys(parsed).forEach(function(key) {
          if (key.indexOf('color') > -1) {
            if (Object.keys(colours).indexOf(parsed[key]) > -1) {
              str = str.replace(parsed[key], colours[parsed[key]])
            }
          }
        });
        return str;
      }
    
      $provide.decorator('ngStyleDirective', function($delegate) {
        let directive = $delegate[0];
        let link = directive.link;
    
        directive.compile = function(element, attrs) {
          let expression = getExpressions(attrs.ngStyle);
          attrs.ngStyle = expression;
          return function(scope, elem, attr) {
            // Run original function
            link.apply(this, arguments);
          }
        }
        return $delegate;
      });
    });
    div + div {
      margin-top: 60px;
    }
    
    .comment { 
      font-family: courier;
      font-size: 12px;
      margin: 15px 0;
    }
    <script src="https://code.angularjs.org/1.4.12/angular.js"></script>
    <div ng-app="plunker" ng-controller="MainCtrl">
      <div>
        <p class="comment">--- with hex --</p>
        <p ng-style='{ "color": "#e59c09" }'>Hello {{name}}!</p>
        <p ng-style='{ "padding": "20px 10px", "background-color": "#1476a0", "color": "#ddd" }'>It is dark here</p>
      </div>
    
      <div>
        <p class="comment">--- with custom colours --</p>
        <p ng-style='{ "color": "mango" }'>Hello {{name}}!</p>
        <p ng-style='{ "padding": "20px 10px", "background-color": "midnight", "color": "#ddd" }'>It is dark here</p>
      </div>
    </div>
        2
  •  3
  •   hilnius    9 年前

    实际上,如果您想使用parse,您可以使用它来解析表达式,替换属性,然后将属性转换回json。

    // in the HTML
    <p ng-style="{ padding: '20px 10px', 'background-color': myController.color, color: '#ddd' }">It is dark here</p>
    // in the JS
    myController.color = 'midnight';
    

    那么解析JSON将不起作用。您应该使用$parse解析表达式,并使用指令的scope对象调用结果函数。

    这就是为什么您的提供商应该是这样的:

    $provide.decorator('ngStyleDirective', function($delegate, $parse) {
      let directive = $delegate[0];
      let link = directive.link;
    
      directive.compile = function(element, attrs) {
        return function(scope, elem, attrs) {
          let ngStyleObject = $parse(attrs.ngStyle)(scope, {});
    
          Object.keys(ngStyleObject).forEach(function(key) {
            if (key.indexOf('color') > -1 && Object.keys(colours).indexOf(ngStyleObject[key]) > -1) {
              ngStyleObject[key] = colours[ngStyleObject[key]];
            }
          });
    
          attrs.ngStyle = JSON.stringify(ngStyleObject); 
          // Run original function
          link.apply(this, arguments); 
        }
      }
      return $delegate;
    });
    

    $provide.decorator('ngStyleDirective', function($delegate) {
      let directive = $delegate[0];
    
      directive.compile = function(element, attrs) {
        return function(scope, elem, attrs) {
          // here, watch will do the $parse(attrs.ngStyle)(scope) and call the callback when values change
          scope.$watch(attrs.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
            if (oldStyles && (newStyles !== oldStyles)) {
              oldStyles.forEach(function(val, style) {  element.css(style, ''); });
            }
            if (newStyles) {
              // instead of just setting the new styles, replace colors with their values
              Object.keys(newStyles).forEach(function(key) { 
                if (key.indexOf('color') > -1 && Object.keys(colours).indexOf(newStyles[key]) > -1) {
                  newStyles[key] = colours[newStyles[key]];
                }
              });
              element.css(newStyles);
            }
          }, true);
    
        }
      }
      return $delegate;
    });
    

    You can find the plunker (two versions) here