【问题标题】:How do I conditionally apply CSS styles in AngularJS?如何有条件地在 AngularJS 中应用 CSS 样式?
【发布时间】:2012-11-28 14:13:23
【问题描述】:

第一季度。假设我想在按下主“删除”按钮之前更改用户标记为删除的每个“项目”的外观。 (这种即时的视觉反馈应该消除对众所周知的“你确定吗?”对话框的需要。)用户将选中复选框以指示应该删除哪些项目。如果未选中复选框,则该项目应恢复正常外观。

应用或删除 CSS 样式的最佳方法是什么?

第二季度。假设我想让每个用户个性化我的网站的呈现方式。例如,从一组固定的字体大小中进行选择,允许用户定义前景色和背景色等。

应用用户选择/输入的 CSS 样式的最佳方式是什么?

【问题讨论】:

标签: css angularjs


【解决方案1】:

Angular 提供了许多用于有条件/动态地操作 CSS 样式的内置指令:

  • ng-class - 当 CSS 样式集是静态的/提前知道时使用
  • ng-style - 当您无法定义 CSS 类时使用,因为样式值可能会动态变化。考虑对样式值进行可编程控制。
  • ng-showng-hide - 仅在需要显示或隐藏某些内容时使用(修改 CSS)
  • ng-if - 1.1.5 版中的新功能,如果您只需要检查单个条件(修改 DOM),请使用而不是更冗长的 ng-switch
  • ng-switch - 使用而不是使用几个互斥的 ng-shows(修改 DOM)
  • ng-disabledng-readonly - 用于限制表单元素的行为
  • ng-animate - 1.1.4 版新增,用于添加 CSS3 过渡/动画

正常的“Angular 方式”包括将模型/范围属性绑定到将接受用户输入/操作(即使用 ng-model)的 UI 元素,然后将该模型属性与内置指令之一相关联上文提到的。

当用户更改 UI 时,Angular 会自动更新页面上的关联元素。


Q1 听起来像是 ng-class 的一个很好的案例——CSS 样式可以在一个类中捕获。

ng-class 接受一个“表达式”,其计算结果必须为以下之一:

  1. 一串以空格分隔的类名
  2. 类名数组
  3. 类名到布尔值的映射/对象

假设使用某些阵列模型的NG-Repeat将显示您的项目,并且当检查项目的复选框时要应用pending-delete class:

<div ng-repeat="item in items" ng-class="{'pending-delete': item.checked}">
   ... HTML to display the item ...
   <input type="checkbox" ng-model="item.checked">
</div>

在上面,我们使用了 ng-class 表达式类型 #3 - 类名到布尔值的映射/对象。


Q2 听起来像是 ng-style 的一个很好的案例——CSS 样式是动态的,所以我们不能为此定义一个类。

ng-style 接受必须评估为的“表达式”:

  1. CSS 样式名称到 CSS 值的映射/对象

举一个人为的例子,假设用户可以在 texbox 中输入颜色名称作为背景颜色(jQuery 颜色选择器会更好):

<div class="main-body" ng-style="{color: myColor}">
   ...
   <input type="text" ng-model="myColor" placeholder="enter a color name">


Fiddle 用于上述两种情况。

小提琴还包含 ng-showng-hide 的示例。如果选中复选框,除了背景颜色变为粉红色外,还会显示一些文本。如果在文本框中输入“红色”,则会隐藏一个 div。

【讨论】:

  • 这个答案太棒了!如果单击事件在不是单击元素的区域上更改/添加类,您愿意通过 jsfiddle 向我展示有什么区别吗?在页面的其他地方说一个 div。
  • 很棒的答案。顺便说一句,你有没有尝试过将角度过滤器应用于 ng-style ?
  • 我建议添加一个与 Q2 相关的附加选项,我刚刚在我最近对这个问题的回答中添加了该选项。
【解决方案2】:

这是我在禁用按钮上有条件地应用灰色文本样式的方法

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  styleUrls: [ './app.component.css' ],
  template: `
  <button 
    (click)='buttonClick1()' 
    [disabled] = "btnDisabled"
    [ngStyle]="{'color': (btnDisabled)? 'gray': 'black'}">
    {{btnText}}
  </button>`
})
export class AppComponent  {
  name = 'Angular';
  btnText = 'Click me';
  btnDisabled = false;
  buttonClick1() {
    this.btnDisabled = true;
    this.btnText = 'you clicked me';
    setTimeout(() => {
      this.btnText = 'click me again';
      this.btnDisabled = false
      }, 5000);
  }
}

这是一个工作示例:
https://stackblitz.com/edit/example-conditional-disable-button?file=src%2Fapp%2Fapp.component.html

【讨论】:

  • 问题标签上写着“AngularJS”,这不是。
【解决方案3】:

我建议您使用返回 truefalse 的函数检查控制器中的条件。

<div class="week-wrap" ng-class="{today: getTodayForHighLight(todayDate, day.date)}">{{day.date}}</div>

并在您的控制器中检查条件

$scope.getTodayForHighLight = function(today, date){
    return (today == date);
}

【讨论】:

    【解决方案4】:

    您可以使用三元表达式。有两种方法可以做到这一点:

    <div ng-style="myVariable > 100 ? {'color': 'red'} : {'color': 'blue'}"></div>
    

    或者...

    <div ng-style="{'color': (myVariable > 100) ? 'red' : 'blue' }"></div>
    

    【讨论】:

    • 也许你会发现它更好:
    • Dudi,如果不是更好,也同样有用,所以我将它添加到@maykel 的“三元表达式”答案中。谢谢你们!
    【解决方案5】:

    当您需要一个或两个属性的简单 css 样式时的另一种选择:

    查看:

    <tr ng-repeat="element in collection">
        [...amazing code...] 
        <td ng-style="{'background-color': getTrColor(element.myvar)}">
            {{ element.myvar }}
        </td>
        [...more amazing code...]
    </tr>
    

    控制器:

    $scope.getTrColor = function (colorIndex) {
        switch(colorIndex){
            case 0: return 'red';
            case 1: return 'green';
            default: return 'yellow';
        }
    };
    

    【讨论】:

      【解决方案6】:

      我最近发现还有一个选项可能对某些人有用,因为它允许您更改样式元素中的 CSS 规则 - 从而避免重复使用 ng-style、ng 等角度指令-class、ng-show、ng-hide、ng-animate 等。

      此选项使用具有服务变量的服务,这些服务变量由控制器设置并由我称为“自定义样式”的属性指令监视。这种策略可以以多种不同的方式使用,我试图通过fiddle 提供一些一般性指导。

      var app = angular.module('myApp', ['ui.bootstrap']);
      app.service('MainService', function(){
          var vm = this;
      });
      app.controller('MainCtrl', function(MainService){
          var vm = this;
          vm.ms = MainService;
      });
      app.directive('customStyle', function(MainService){
          return {
              restrict : 'A',
              link : function(scope, element, attr){
                  var style = angular.element('<style></style>');
                  element.append(style);
                  scope.$watch(function(){ return MainService.theme; },
                      function(){
                          var css = '';
                          angular.forEach(MainService.theme, function(selector, key){
                              angular.forEach(MainService.theme[key], function(val, k){
                                  css += key + ' { '+k+' : '+val+'} ';
                              });                        
                          });
                          style.html(css);
                      }, true);
              }
          };
      });
      

      【讨论】:

        【解决方案7】:

        当我已经将一个类应用于整个表(例如,应用于奇数行&lt;myClass tbody tr:nth-child(even) td&gt; 的颜色)时,我在 table 元素中应用类时发现了问题。似乎当您使用 Developer Tools 检查元素时,element.style 没有指定样式。所以我没有使用ng-class,而是尝试使用ng-style,在这种情况下,新的CSS属性确实出现在element.style中。这段代码对我很有用:

        <tr ng-repeat="element in collection">
        
            [...amazing code...]
        
            <td ng-style="myvar === 0 && {'background-color': 'red'} ||
                          myvar === 1 && {'background-color': 'green'} ||
                          myvar === 2 && {'background-color': 'yellow'}">{{ myvar }}</td>
        
            [...more amazing code...]
        
        </tr>
        

        Myvar 是我正在评估的内容,在每种情况下,我都会根据 myvar 值对每个 &lt;td&gt; 应用一个样式,这会覆盖当前应用的样式整个表格的 CSS 类。

        更新

        如果你想将一个类应用到表格中,例如在访问页面时或其他情况下,你可以使用这个结构:

        <li ng-class="{ active: isActive('/route_a') || isActive('/route_b')}">
        

        基本上,我们需要激活一个 ng-class 是要应用的类和一个真假语句。 True 应用类,而 false 不应用。所以这里我们对页面的路由进行了两次检查,它们之间有一个OR,所以如果我们在/route_a OR我们在route_b,active 类将被应用。

        这只是在右边有一个返回真或假的逻辑函数。

        所以在第一个示例中,ng-style 受三个语句的限制。如果它们都为假,则不应用样式,但按照我们的逻辑,至少要应用一个,因此,逻辑表达式将检查哪个变量比较为真,因为非空数组始终为真,这将留下一个数组作为返回值,只有一个为真,考虑到我们对整个响应使用 OR,剩下的样式将被应用。

        对了,我忘了给你函数isActive():

        $rootScope.isActive = function(viewLocation) {
            return viewLocation === $location.path();
        };
        

        新更新

        这里有一些我觉得非常有用的东西。当你需要根据一个变量的值来应用一个类时,例如一个图标依赖于div的内容,你可以使用下面的代码(在ng-repeat非常有用):

        <i class="fa" ng-class="{ 'fa-github'   : type === 0,
                                  'fa-linkedin' : type === 1,
                                  'fa-skype'    : type === 2,
                                  'fa-google'   : type === 3 }"></i>
        

        来自Font Awesome的图标

        【讨论】:

        • 多么奇怪的语法,&& 应该表示 AND,就像在任何其他受 c 启发的语言中一样
        • @PizzaiolaGorgonzola && 确实意味着 AND 和 ||确实意味着或。这是一个巧妙的技巧,几乎将短路逻辑用作 case/switch 语句......
        • 谢谢 mit。我没有意识到那个细节。
        • 新的更新部分就像一个魅力!为它 +1!
        • 使用了新更新中提到的 ng-class 的例子,对我来说效果很好。很时尚
        【解决方案8】:
        span class="circle circle-{{selectcss(document.Extension)}}">
        

        和代码

        $scope.selectcss = function (data) {
            if (data == '.pdf')
                return 'circle circle-pdf';
            else
                return 'circle circle-small';
        };
        

        css

        .circle-pdf {
            width: 24px;
            height: 24px;
            font-size: 16px;
            font-weight: 700;
            padding-top: 3px;
            -webkit-border-radius: 12px;
            -moz-border-radius: 12px;
            border-radius: 12px;
            background-image: url(images/pdf_icon32.png);
        }
        

        【讨论】:

        • 永远避免使用 iF 字
        • 我想鼓励避免直接使用类属性。这将覆盖其他插件对此元素所做的更改。
        【解决方案9】:

        看下面的例子

        <!DOCTYPE html>
            <html ng-app>
            <head>
            <title>Demo Changing CSS Classes Conditionally with Angular</title>
            <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
            <script src="res/js/controllers.js"></script>
        
            <style>
        
            .checkboxList {
                border:1px solid #000;
                background-color:#fff;
                color:#000;
                width:300px;
                height: 100px;
                overflow-y: scroll;
            }
        
            .uncheckedClass {
               background-color:#eeeeee;
               color:black;
            }
            .checkedClass {
                background-color:#3ab44a;
                color:white;
            }
            </style>
        
            </head>
            <body ng-controller="TeamListCtrl">
            <b>Teams</b>
            <div id="teamCheckboxList" class="checkboxList">
        
            <div class="uncheckedClass" ng-repeat="team in teams" ng-class="{'checkedClass': team.isChecked, 'uncheckedClass': !team.isChecked}">
        
            <label>
            <input type="checkbox" ng-model="team.isChecked" />
            <span>{{team.name}}</span>
            </label>
            </div>
            </div>
            </body>
            </html>
        

        【讨论】:

          【解决方案10】:

          这个解决方案对我有用

          <a ng-style="{true: {paddingLeft: '25px'}, false: {}}[deleteTriggered]">...</a>
          

          【讨论】:

            【解决方案11】:

            另一种(将来)有条件地应用样式的方法是有条件地创建作用域样式

            <style scoped type="text/css" ng-if="...">
            
            </style>
            

            但现在只有 FireFox 支持范围样式。

            【讨论】:

              【解决方案12】:

              需要注意的一点是 - 如果 CSS 样式有破折号 - 您必须删除它们。所以如果要设置background-color,正确的做法是:

              ng-style="{backgroundColor:myColor}" 
              

              【讨论】:

              • 不,您不必这样做。 ng-style="{'background-color':myColor}" 效果很好。
              【解决方案13】:

              这在不能使用 ng-class 时效果很好(例如在设置 SVG 样式时):

              ng-attr-class="{{someBoolean && 'class-when-true' || 'class-when-false' }}"
              

              (我认为您需要使用最新的不稳定 Angular 才能使用 ng-attr-,我目前使用的是 1.1.4)

              我发表了一篇关于使用 AngularJS+SVG 的文章。它谈到了这个问题和许多其他问题。 http://www.codeproject.com/Articles/709340/Implementing-a-Flowchart-with-SVG-and-AngularJS

              【讨论】:

              • 我在1.1.4 docs 中没有看到任何提及 ng-attr -- 你有链接吗?
              • 抱歉没有链接。我是通过关注 Angular 论坛发现的,虽然我不记得确切的页面,抱歉。
              • 最新文档 (v1.2) 在 directives pagengAttr 属性绑定 部分描述了 ng-attr-
              • 在 1.2 中,这是一个很好的答案。 ng-class 不允许您执行逻辑,但 ng-attr-class 可以。它们都有自己的用途,但我敢打赌,很多开发人员都会寻找ng-attr-class
              • 当此处提供的其他解决方案失败时,我让它运行良好。谢谢。
              【解决方案14】:

              从 AngularJS v1.2.0rc 开始,ng-class 甚至 ng-attr-class 都无法使用 SVG 元素(它们确实可以更早地工作,即使在 class 属性内使用普通绑定也是如此)

              具体来说,这些现在都不起作用:

              ng-class="current==this_element?'active':' ' "
              ng-attr-class="{{current==this_element?'active':' '}}"
              class="class1 class2 .... {{current==this_element?'active':''}}"
              

              作为一种解决方法,我必须使用

              ng-attr-otherAttr="{{current==this_element?'active':''}}"
              

              然后使用样式

              [otherAttr='active'] {
                 ... styles ...
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2019-01-07
                • 2019-08-05
                • 1970-01-01
                • 2017-08-23
                • 2013-07-31
                • 2016-09-03
                • 1970-01-01
                相关资源
                最近更新 更多