Làm cách nào để tôi áp dụng có điều kiện các kiểu CSS trong AngularJS?


309

Q1. Giả sử tôi muốn thay đổi giao diện của từng "mục" mà người dùng đánh dấu để xóa trước khi nhấn nút "xóa" chính. (Phản hồi trực quan ngay lập tức này sẽ loại bỏ sự cần thiết của hộp thoại "bạn có chắc không?".) Người dùng sẽ kiểm tra các hộp kiểm để cho biết mục nào sẽ bị xóa. Nếu một hộp kiểm được bỏ chọn, mục đó sẽ trở lại giao diện bình thường.

Cách tốt nhất để áp dụng hoặc loại bỏ kiểu CSS là gì?

Quý 2 Giả sử tôi muốn cho phép mỗi người dùng cá nhân hóa cách trình bày trang web của tôi. Ví dụ: chọn từ một tập hợp kích thước phông chữ cố định, cho phép màu nền và màu nền có thể xác định được của người dùng, v.v.

Cách tốt nhất để áp dụng kiểu CSS mà người dùng chọn / nhập liệu là gì?


Câu trả lời:


485

Angular cung cấp một số chỉ thị tích hợp để thao tác tạo kiểu CSS theo điều kiện / động:

  • ng-class - sử dụng khi tập hợp các kiểu CSS là tĩnh / được biết trước
  • ng-style - sử dụng khi bạn không thể xác định lớp CSS vì các giá trị kiểu có thể thay đổi linh hoạt. Hãy suy nghĩ lập trình kiểm soát các giá trị phong cách.
  • ng-show ng-hide - sử dụng nếu bạn chỉ cần hiển thị hoặc ẩn thứ gì đó (sửa đổi CSS)
  • ng-if - mới trong phiên bản 1.1.5, sử dụng thay vì ng-switch dài dòng hơn nếu bạn chỉ cần kiểm tra một điều kiện duy nhất (sửa đổi DOM)
  • ng-switch - sử dụng thay vì sử dụng một số ng-shows loại trừ lẫn nhau (sửa đổi DOM)
  • ng-tật ng-readonly - sử dụng để hạn chế hành vi của phần tử biểu mẫu
  • ng-animate - mới trong phiên bản 1.1.4, sử dụng để thêm hiệu ứng chuyển tiếp / hoạt hình CSS3

"Cách góc" thông thường liên quan đến việc buộc thuộc tính mô hình / phạm vi vào thành phần UI sẽ chấp nhận thao tác nhập / thao tác của người dùng (nghĩa là sử dụng mô hình ng), sau đó liên kết thuộc tính mô hình đó với một trong các chỉ thị tích hợp được đề cập ở trên.

Khi người dùng thay đổi UI, Angular sẽ tự động cập nhật các yếu tố liên quan trên trang.


Q1 có vẻ như là một trường hợp tốt cho ng-class - kiểu CSS có thể được ghi lại trong một lớp.

ng-class chấp nhận một "biểu thức" phải đánh giá theo một trong các cách sau:

  1. một chuỗi các tên lớp được phân tách bằng dấu cách
  2. một mảng các tên lớp
  3. một ánh xạ / đối tượng của các tên lớp thành các giá trị boolean

Giả sử các mục của bạn được hiển thị bằng ng-repeat trên một số mô hình mảng và khi hộp kiểm cho một mục được chọn, bạn muốn áp dụng pending-deletelớp:

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

Ở trên, chúng tôi đã sử dụng loại biểu thức ng-class # 3 - một bản đồ / đối tượng của các tên lớp cho các giá trị boolean.


Q2 nghe có vẻ là một trường hợp tốt cho phong cách ng - kiểu CSS là động, vì vậy chúng ta không thể định nghĩa một lớp cho việc này.

phong cách ng chấp nhận một "biểu thức" phải ước tính để:

  1. một bản đồ / đối tượng của các tên kiểu CSS thành các giá trị CSS

Đối với một ví dụ giả định, giả sử người dùng có thể nhập tên màu vào hộp tex cho màu nền (trình chọn màu jQuery sẽ đẹp hơn nhiều):

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


Fiddle cho cả hai ở trên.

Fiddle cũng chứa một ví dụ về ng-showng-hide . Nếu một hộp kiểm được chọn, ngoài màu nền chuyển sang màu hồng, một số văn bản được hiển thị. Nếu 'đỏ' được nhập vào hộp văn bản, div sẽ bị ẩn.


Câu trả lời này là tuyệt vời! Bạn có sẵn lòng chỉ cho tôi qua jsfiddle sự khác biệt sẽ là gì nếu sự kiện nhấp đang thay đổi / thêm một lớp trên một khu vực không phải là yếu tố được nhấp? Nói một div ở nơi khác trên trang.
tehaaron

đó là bài viết hữu ích tech-blog.maddyzone.com/javascript/ từ
Rituraj ratan

Anwser tuyệt vời. Btw, bạn đã bao giờ thử áp dụng bộ lọc góc cho phong cách ng chưa?
Bài hát Evi

Tôi đề nghị thêm một tùy chọn bổ sung liên quan đến Q2 mà tôi vừa thêm vào câu trả lời gần đây cho câu hỏi này.
Gavin Palmer

105

Tôi đã gặp vấn đề khi áp dụng các lớp bên trong các thành phần bảng khi tôi có một lớp đã được áp dụng cho toàn bộ bảng (ví dụ: màu được áp dụng cho các hàng lẻ <myClass tbody tr:nth-child(even) td>). Có vẻ như khi bạn kiểm tra phần tử bằng Công cụ dành cho nhà phát triển , element.stylekiểu không được gán. Vì vậy, thay vì sử dụng ng-class, tôi đã thử sử dụng ng-stylevà trong trường hợp này, thuộc tính CSS mới xuất hiện bên trong element.style. Mã này hoạt động rất tốt cho tôi:

<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 là những gì tôi đang đánh giá, và trong mỗi trường hợp, tôi áp dụng một kiểu cho mỗi kiểu <td>tùy thuộc vào myvar giá trị , ghi đè lên kiểu hiện tại được áp dụng bởi lớp CSS cho toàn bộ bảng.

CẬP NHẬT

Nếu bạn muốn áp dụng một lớp cho bảng chẳng hạn, khi truy cập một trang hoặc trong các trường hợp khác, bạn có thể sử dụng cấu trúc này:

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

Về cơ bản, những gì chúng ta cần để kích hoạt một lớp ng là lớp để áp dụng và một tuyên bố đúng hoặc sai. Đúng áp dụng lớp và sai không. Vì vậy, ở đây chúng tôi có hai kiểm tra về tuyến đường của trang và OR giữa chúng, vì vậy nếu chúng tôi ở trong /route_a OR chúng tôi đang ở route_b, lớp hoạt động sẽ được áp dụng.

Điều này hoạt động chỉ cần có một chức năng logic ở bên phải trả về đúng hoặc sai.

Vì vậy, trong ví dụ đầu tiên, phong cách ng được quy định bởi ba câu lệnh. Nếu tất cả chúng đều sai, không có kiểu nào được áp dụng, nhưng theo logic của chúng tôi, ít nhất một kiểu sẽ được áp dụng, vì vậy, biểu thức logic sẽ kiểm tra so sánh biến nào là đúng và bởi vì một mảng không trống luôn luôn đúng, điều đó sẽ đúng để lại một mảng là trả về và chỉ có một đúng, vì chúng tôi đang sử dụng OR cho toàn bộ phản hồi, kiểu còn lại sẽ được áp dụng.

Nhân tiện, tôi quên cung cấp cho bạn hàm isActive ():

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

CẬP NHẬT MỚI

Ở đây bạn có một cái gì đó tôi thấy thực sự hữu ích. Khi bạn cần áp dụng một lớp tùy thuộc vào giá trị của biến, ví dụ: biểu tượng tùy thuộc vào nội dung của nó div, bạn có thể sử dụng mã sau (rất hữu ích trong ng-repeat):

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

Các biểu tượng từ Font Awesome


thật là một cú pháp lạ, && có nghĩa là VÀ, giống như trong bất kỳ ngôn ngữ lấy cảm hứng từ c nào khác
Pizzaiola Gorgonzola

3
@PizzaiolaGorgonzola && có nghĩa là VÀ và || không có nghĩa HOẶC. Đó là một cách hack thông minh bằng cách sử dụng logic ngắn mạch gần như là một tuyên bố về trường hợp / chuyển đổi ...
Stein G. Strindhaug

Cảm ơn Tôi đã không nhận ra chi tiết đó.
Timbergus

Phần cập nhật mới hoạt động như một cơ duyên! +1 cho nó!
Matias

đã sử dụng ví dụ về ng-class như được đề cập trong Bản cập nhật mới, hoạt động khá tốt đối với tôi. Khá bóng bẩy
Acewin 16/2/2017

34

Điều này hoạt động tốt khi ng-class không thể được sử dụng (ví dụ: khi tạo kiểu SVG):

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

(Tôi nghĩ rằng bạn cần phải có Angular không ổn định mới nhất để sử dụng ng-attr-, tôi hiện đang ở 1.1.4)

Tôi đã xuất bản một bài viết về làm việc với AngularJS + SVG. Nó nói về vấn đề này và nhiều người khác. http://www.codeproject.com/Articles/709340/Imcellenceing-a-Flowchart-with-SVG-and-AngularJS


Tôi không thấy bất kỳ đề cập nào về ng-attr trong tài liệu 1.1.4 - bạn có liên kết không?
Mark Rajcok

Xin lỗi không có một liên kết. Tôi đã tìm hiểu về nó bằng cách theo dõi các diễn đàn Angular, mặc dù tôi không thể nhớ chính xác trang xin lỗi.
Ashley Davis

1
Các tài liệu mới nhất (v1.2) mô tả ng-attr-trên trang chỉ thị , phần ràng buộc thuộc tính ngAttr .
Mark Rajcok

Với 1,2, đây trở thành một câu trả lời tuyệt vời. ng-classkhông cho phép bạn thực hiện logic, nhưng ng-attr-classkhông. Cả hai đều có công dụng của chúng, nhưng tôi có thể đặt cược rất nhiều nhà phát triển sẽ tìm kiếm ng-attr-class.
Hylianpuffball

Tôi đã làm điều này để làm việc tốt khi các giải pháp khác được cung cấp ở đây không thành công. Cảm ơn bạn.
dps

13
span class="circle circle-{{selectcss(document.Extension)}}">

và mã

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

Luôn luôn tránh từ iF
LastTribunal

Tôi muốn khuyến khích để tránh sử dụng trực tiếp thuộc tính lớp. Điều này sẽ ghi đè lên các thay đổi được thực hiện bởi các plugin khác trên thành phần này.
SimonSimCity

10

Giải pháp này đã giúp tôi rất nhiều

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

8

Bạn có thể sử dụng biểu thức ternary. Có hai cách để làm điều này:

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

hoặc là...

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

1
Có lẽ bạn sẽ tìm thấy nó tốt hơn: <div ng-style = "{'color': (myVariable> 100)? 'Red': 'blue'}"> </ div>
Dudi

Dudi, nếu không tốt hơn, cũng hữu ích, vì vậy tôi đã thêm nó vào câu trả lời "biểu hiện ternary" của @ maykel. Cám ơn hai bạn!
jbobbins

7

Một tùy chọn khác khi bạn cần một kiểu css đơn giản gồm một hoặc hai thuộc tính:

Lượt xem:

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

Điều khiển:

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

6

Xem ví dụ sau

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

Kể từ AngularJS v1.2.0rc, ng-classvà thậm chí ng-attr-classthất bại với các phần tử SVG (Chúng đã hoạt động sớm hơn, ngay cả với ràng buộc bình thường bên trong thuộc tính lớp)

Cụ thể, không ai trong số này làm việc bây giờ:

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

Như một cách giải quyết, tôi sẽ sử dụng

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

và sau đó tạo kiểu bằng cách sử dụng

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

1

Một cách nữa (trong tương lai) để áp dụng phong cách có điều kiện là bằng cách tạo điều kiện theo kiểu có phạm vi

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

</style>

Nhưng ngày nay chỉ có FireFox hỗ trợ các kiểu có phạm vi.


1

Có một tùy chọn nữa mà gần đây tôi phát hiện ra rằng một số người có thể thấy hữu ích vì nó cho phép bạn thay đổi quy tắc CSS trong một thành phần kiểu - do đó tránh việc sử dụng lặp lại một lệnh góc cạnh như kiểu ng, lớp ng, ng-show, ng-hide, ng-animate, và những người khác.

Tùy chọn này sử dụng một dịch vụ với các biến dịch vụ được đặt bởi bộ điều khiển và được xem bởi một chỉ thị thuộc tính mà tôi gọi là "kiểu tùy chỉnh". Chiến lược này có thể được sử dụng theo nhiều cách khác nhau và tôi đã cố gắng cung cấp một số hướng dẫn chung với câu đố này .

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

tôi cũng sẽ đề nghị bạn kiểm tra điều kiện trong bộ điều khiển của bạn với một hàm trả về đúng hay sai .

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

và trong bộ điều khiển của bạn kiểm tra điều kiện

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

0

Một điều cần xem là - nếu kiểu CSS có dấu gạch ngang - bạn phải xóa chúng. Vì vậy, nếu bạn muốn đặt background-color, cách chính xác là:

ng-style="{backgroundColor:myColor}" 

5
Không, bạn không phải. ng-style = "{'background-color': myColor}" hoạt động hoàn hảo.
gerasalus

0

Đây là cách tôi áp dụng có điều kiện kiểu văn bản màu xám trên một nút bị vô hiệu hóa

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

Dưới đây là một ví dụ hoạt động:
https://stackblitz.com/edit/example-conditable-disable-button?file=src%2Fapp%2Fapp.component.html

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.