如何在AngularJS中有条件地应用CSS样式?


309

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

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

Q2。假设我想允许每个用户个性化展示我的网站。例如,从一组固定的字体大小中进行选择,允许用户定义前景色和背景色等。

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


Answers:


485

Angular提供了许多内置指令,用于有条件/动态地处理CSS样式:

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

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

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


Q1对于ng-class来说似乎是一个很好的例子-CSS样式可以在一个类中捕获。

ng-class接受“表达式”,该表达式必须计算以下值之一:

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

假设您的商品是使用ng-repeat在某些数组模型上显示的,并且选中了商品的复选框后,您想应用pending-delete该类:

<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样式-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">


为上述两者摆弄

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


这个答案太棒了!您是否愿意通过jsfiddle向我展示,如果click事件正在更改/在不是clicked元素的区域上添加类,会有什么不同?在页面其他位置说一个div。
tehaaron


太棒了。顺便说一句,您是否尝试过将角度滤镜应用于ng-style?
Evi Song 2015年

我建议添加一个与第二季度相关的附加选项,该选项是我最近在对此问题的回答中添加的。
加文·帕尔默

105

当我已经将一个类应用于整个表时(例如,将一种颜色应用于奇数行),当在元素内部应用类时,我发现了问题<myClass tbody tr:nth-child(even) td>。看来,当您使用Developer Tools检查元素时,element.style没有分配样式。因此ng-class,我尝试使用而不是使用,ng-style在这种情况下,新的CSS属性的确出现在inside 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,在每种情况下,我都<td>根据myvar值对每个样式应用一种样式,该样式将覆盖CSS类为整个表应用的当前样式。

更新

例如,如果要在表上应用类,则在访问页面时或在其他情况下,可以使用以下结构:

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

基本上,我们需要激活ng-class的是要应用的类以及一个true或false语句。True适用于该类,false不适用。因此,在这里,我们对页面的路由进行了两次检查,并检查了它们之间的OR,因此如果我们在/route_a ORroute_b,则将使用活动类。

这仅在右侧具有返回true或false的逻辑功能时有效。

因此,在第一个示例中,ng-style由三个语句限制。如果所有这些都是假的,则不应用任何样式,但是按照我们的逻辑,将至少应用一种样式,因此,逻辑表达式将检查哪个变量比较为真,并且由于非空数组始终为真,因此将留下一个数组作为return,并且只有一个true,考虑到我们对整个响应都使用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中的图标


像任何其他受c语言启发的语言一样,&&应该意味着AND的奇怪语法
Pizzaiola Gorgonzola 2014年

3
@PizzaiolaGorgonzola &&的确是AND和|| 确实意味着OR。这是一个巧妙的技巧,几乎将短路逻辑用作案例/切换语句……
Stein G. Strindhaug 2014年

谢谢麻省理工学院。我没有意识到那个细节。
廷贝格斯

新的更新部分就像一个魅力!+1!
Matias

使用了New Update中提到的ng-class的示例,对我来说效果很好。相当时尚
Acewin '17

34

当不能使用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文档中看到任何有关ng-attr的信息-您有链接吗?
Mark Rajcok

抱歉,没有链接。我通过关注Angular论坛找到了有关此问题的信息,尽管我不记得确切的页面对不起。
Ashley Davis

1
最新的文档(v1.2)ng-attr-指令页面的ngAttr属性绑定部分中进行了描述。
2013年

使用1.2,这将成为一个很好的答案。 ng-class不允许您执行逻辑,但是ng-attr-class可以。它们都有其用途,但是我敢打赌,很多开发人员都将寻找它们ng-attr-class
Hylianpuffball 2014年

当此处提供的其他解决方案失败时,我可以很好地工作。谢谢。
dps

13
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);
}

始终避免如果Word
LastTribunal

我想鼓励避免直接使用class属性。这将覆盖此元素上其他插件所做的更改。
SimonSimCity

10

这个解决方案对我有用

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

8

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

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

要么...

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

1
也许您会发现更好:<div ng-style =“ {'color':(myVariable> 100)?'red':'blue'}”> </ div>
Dudi

杜迪(Dudi),如果不是更好的话,同样有用,因此我将其添加到@maykel的“三元表达式”答案中。感谢你们俩!
jbobbins

7

需要一个或两个属性的简单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

请参阅以下示例

<!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>

2

从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 ...
}

1

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

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

</style>

但是如今,只有FireFox支持范围样式。


1

我最近发现了另一个选择,有些人可能会发现有用,因为它允许您更改样式元素内的CSS规则-从而避免了重复使用诸如ng-style,ng-class, ng-show,ng-hide,ng-animate等。

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

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);
        }
    };
});

1

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

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

并在控制器中检查情况

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

0

要注意的一件事是-如果CSS样式中有破折号-您必须将其删除。因此,如果要设置background-color,正确的方法是:

ng-style="{backgroundColor:myColor}" 

5
不,您不必。ng-style =“ {'background-color':myColor}”效果很好。
gerasalus 2014年

0

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.