将AngularJS变量绑定到CSS语法中



我正试图弄清楚如何将AngularJS scope vars绑定到CSS语法中。我认为问题出在花括号上。以下是我基本上要做的:

<style>.css_class {background:{{ angular_variable }}; color:#ffffff;}</style>
<style>.css_rule {background:{{ "#000000" }}; color:#ffffff;}</style>
<style>.css_rule {background:{{ var | someFilter }}; color:#ffffff;}</style>

关于如何做到这一点,有什么想法吗?非常感谢。

正如这里所解释的,angular不在样式标记内的内容上运行。这篇文章中有一个变通方法plunkr,但作为一种更灵活的方法,我只需要创建一个获取内容、解析并替换的指令:

更新的答案

app.directive('parseStyle', function($interpolate) {
    return function(scope, elem) {
        var exp = $interpolate(elem.html()),
            watchFunc = function () { return exp(scope); };
        scope.$watch(watchFunc, function (html) {
            elem.html(html);
        });
    };
});

用法:

<style parse-style>.css_class {color: {{ angular_variable }};}</style>

http://jsfiddle.net/VUeGG/31/


原始答案

app.directive('parseStyle', function()
{
    return function(scope, elem)
    {
        elem.html(scope.$eval(''' + elem.html() + '''));
    };
});

然后:

<style parse-style>.css_class {color: ' + angular_variable + ';}</style>

但不确定浏览器对此的支持。

http://jsfiddle.net/VUeGG/4/

更新

我已经组装了一个名为ngCss的Angular"插件"(模块+过滤器+工厂),它可以处理这个问题以及更多问题——看看吧!

我还制作了一个Vanilla Javascript(例如,没有外部依赖项)版本;CjsSS.js(GitHub)。

ngCs是一个很小的*Angular Module+Factory+Filters,它可以在CSS中绑定字符串和对象(包括嵌套对象)。*1700字节下的精简+压缩脚本

功能:

  • CSS可以是实时绑定的($scope中的更改是$watch'ed),也可以通过自定义$broadcast事件updateCss进行更新
  • css和cssInline过滤器将Javascript/JSON objects输出为css,以启用mixin,包括嵌套objects的能力
  • $scope可以在CSS本身中初始化,允许所有与CSS相关的信息都位于*.CSS或STYLE元素中
  • $scope可以从任何Angular $element(经由angular.element($element).scope())分离或导入

原件多亏了@jonnyynoj的代码,我找到了一种方法,可以将{{angular_variable}}命名法保留在样式标签中,并实时绑定任何更改。查看@jonnynnoj的代码叉,获得一个简单的例子,或者看看下面我在应用程序中使用的内容:

(function (ngApp) {
    'use strict';
    //# Live bind a <style cn-styler="{ commented: true, usingSingleQuote: true }" /> tag with {{ngVars}}
    ngApp.directive('cnStyler', function () {
        return {
            //# .restrict the directive to attribute only (e.g.: <style cn-styler>...</style>)
            restrict: "A",
            link: function ($scope, $element, $attrs, controllers) {
                //# .$eval the in-line .options and setup the updateCSS function
                //#     NOTE: The expected string value of the inline options specifies a JSON/JavaScript object, hence the `|| {}` logic
                var css, regEx,
                    options = $scope.$eval($attrs["cnStyler"]) || {},
                    updateCSS = function () {
                        //# .$eval the css, replacing the results back into our $element's .html
                        $element.html($scope.$eval(css));
                    }
                ;
                //# Setup the .quote and the inverse in .unquote (which we use to process the css)
                //#     NOTE: In theory, the .unquote should not be present within the css
                options.quote = (options.usingSingleQuote !== false ? "'" : '"');
                options.unquote = (options.quote === '"' ? "'" : '"');
                regEx = new RegExp(options.unquote, "g");
                //# Process the $element's .html into css, .replace'ing any present .unquote's with .quote's (this could cause problems), then the {{Angular}} (or /*{{Angular}}*/) variables with ' + stringified_versions + '
                if (options.commented !== false) {
                    css = options.unquote + ($element.html() + '')
                        .replace(regEx, options.quote)
                        .replace(//*{{/g, options.unquote + "+")
                        .replace(/}}*//g, "+" + options.unquote)
                    + options.unquote;
                } else {
                    css = options.unquote + ($element.html() + '')
                        .replace(regEx, options.quote)
                        .replace(/{{/g, options.unquote + "+")
                        .replace(/}}/g, "+" + options.unquote)
                    + options.unquote;
                }
                //# .$watch for any changes in the $scope, calling our updateCSS function when they occur
                $scope.$watch(updateCSS);
            }
        };
    });
})(YOUR_NG_APP_VAR_HERE);

然后你使用这样的指令:

<style cn-styler type="text/css">
    .myClass{
        color: /*{{themeColor}}*/;
    }
</style>

在控制器中的某个位置设置了$scope.themeColor,并用ngApp变量替换了YOUR_NG_APP_VAR_HERE

注意:

确保您的ng-controller定义为具有<style>标记的作用域,因为<style>标记应在<head>中,而ng-controller通常在<body>标记或以下定义TL;DR:ng-controller放在<html>标签上,如下所示:

<html ng-app="YOUR_NG_APP_VAR_HERE" ng-controller="MyNgController">

由于Visual Studio等工具中的CSS解析和自动格式化,我添加了在CSS注释中包含{{Angular}}变量的功能(例如/*{{Angular}}*/这是指令的默认行为,除非您这样覆盖它:

<style cn-styler="{commented: false}" >...</style>

由于这个解决方案的性质(CSS是.$eval,作为一个插入变量的字符串),CSS中单引号或双引号的存在也需要处理。默认情况下,该指令假设您在CSS中使用单引号('),这意味着为了避免任何引入的错误,您应该在CSS中仅使用单引号,因为CSS中存在的任何双引号都将被单引号替换。您可以覆盖此默认行为(意味着您在CSS中使用双引号),如下所示:

<style cn-styler="{usingSingleQuote: false}" >...</style>

在某些边缘情况下,用单引号替换双引号会破坏CSS(例如在content中),因此您需要确保在CSS中只使用一种引号样式(并相应地发出指令信号),以避免任何潜在问题。值得庆幸的是,CSS中很少使用引号,所以这基本上不是问题。

您不应该需要大括号,因为这些大括号是在html指令中求值的-只有当您有一个表达式是在它们之外求值时,您才需要使用大括号,即;

<p ng-class="some-angular-variable">
  {{some-angular-variable}}
</p> 

在您的情况下,删除双大括号并使用双引号应该可以解决问题。

顺便说一句,Chandermani是有钱的——你试图通过ng类指令更好地完成的。使用它将允许将一个类(或多个)应用于相应的标记。

即;

<p ng-class="mystyle">
    some text
</p>

假设您有两个类style1和style2

您可以选择应用的哪一个

scope.mystyle = "style1" // or whatever

在您的控制器中。

我不明白你为什么要用这个主意!你应该用ng类!

例如:

<p ng-class="{strike: strike, bold: bold, red: red}">Map Senter code hereyntax Example</p>

最新更新