Como aplico condicionalmente estilos CSS no AngularJS?

Q1 Suponha que eu queira alterar a aparência de cada “item” que um usuário marca para exclusão antes que o botão principal “excluir” seja pressionado. (Esse feedback visual imediato deve eliminar a necessidade da proverbial checkbox de diálogo “Você tem certeza?”). O usuário marcará as checkboxs de seleção para indicar quais itens devem ser excluídos. Se uma checkbox de seleção estiver desmarcada, esse item deverá reverter para sua aparência normal.

Qual é a melhor maneira de aplicar ou remover o estilo CSS?

Q2 Suponha que eu queira permitir que cada usuário personalize como meu site é apresentado. Por exemplo, selecione de um conjunto fixo de tamanhos de fonte, permita colors de primeiro plano e de fundo definidas pelo usuário, etc.

Qual é a melhor maneira de aplicar o estilo CSS que o usuário seleciona / inputs?

Angular fornece várias diretivas internas para manipular o estilo CSS condicionalmente / dinamicamente:

  • ng-class – use quando o conjunto de estilos CSS é estático / conhecido antes do tempo
  • ng-style – use quando você não puder definir uma class CSS porque os valores de estilo podem mudar dinamicamente. Pense no controle programável dos valores de estilo.
  • ng-show e ng-hide – use se você precisar apenas mostrar ou ocultar algo (modifica CSS)
  • ng-if – new na versão 1.1.5, use em vez do ng-switch mais detalhado se você precisar apenas verificar uma única condição (modifica o DOM)
  • ng-switch – use em vez de usar vários ng-shows mutuamente exclusivos (modifica DOM)
  • ng-disabled e ng-readonly – use para restringir o comportamento do elemento de formulário
  • ng-animate – novo na versão 1.1.4, use para adicionar transições / animações CSS3

O “modo angular” normal envolve amarrar uma propriedade de modelo / escopo a um elemento de interface do usuário que aceitará input / manipulação do usuário (ou seja, usar ng-model) e associar essa propriedade de modelo a uma das diretivas internas mencionadas acima.

Quando o usuário altera a interface do usuário, o Angular atualiza automaticamente os elementos associados na página.


Q1 soa como um bom caso para ng-class – o estilo CSS pode ser capturado em uma class.

ng-class aceita uma “expressão” que deve ser avaliada para um dos seguintes:

  1. uma cadeia de nomes de classs delimitadas por espaço
  2. uma matriz de nomes de classs
  3. um mapa / object de nomes de classs para valores booleanos

Supondo que seus itens sejam exibidos usando ng-repeat em algum modelo de matriz e que quando a checkbox de seleção de um item estiver marcada, você deseja aplicar a class de pending-delete :

 
... HTML to display the item ...

Acima, usamos ng-class expression type # 3 – um map / object de nomes de classs para valores booleanos.


Q2 soa como um bom caso para ng-style – o estilo CSS é dynamic, então não podemos definir uma class para isso.

O ng-style aceita uma “expressão” que deve avaliar para:

  1. um mapa / object de nomes de estilo CSS para valores CSS

Para um exemplo planejado, suponha que o usuário possa digitar um nome de cor em uma checkbox de texto para a cor do plano de fundo (um selecionador de colors do jQuery seria muito melhor):

 
...

Violino para ambos os acima.

O violino também contém um exemplo de ng-show e ng-hide . Se uma checkbox de seleção estiver marcada, além da cor de fundo ficar rosa, algum texto será exibido. Se ‘red’ for inserido na checkbox de texto, um div ficará oculto.

Eu encontrei problemas ao aplicar classs dentro de elementos da tabela quando já tinha uma class aplicada à tabela inteira (por exemplo, uma cor aplicada às linhas ímpares ). Parece que quando você inspeciona o elemento com o Developer Tools , o element.style não tem estilo atribuído. Então, ao invés de usar ng-class , eu tentei usar ng-style , e neste caso, o novo atributo CSS aparece dentro de element.style . Esse código funciona muito bem para mim:

  [...amazing code...] {{ myvar }} [...more amazing code...]  

Myvar é o que eu estou avaliando, e em cada caso eu aplico um estilo a cada

dependendo do valor do myvar , que sobrescreve o estilo atual aplicado pela class CSS para toda a tabela.

ATUALIZAR

Se você quiser aplicar uma class à tabela, por exemplo, ao visitar uma página ou em outros casos, você pode usar essa estrutura:

 
  • Basicamente, o que precisamos para ativar uma class ng é a class para aplicar e uma declaração verdadeira ou falsa. Verdadeiro aplica a class e falso não. Portanto, aqui temos duas verificações da rota da página e uma OR entre elas, portanto, se estivermos em /route_a OU estivermos em route_b , a class ativa será aplicada.

    Isso funciona apenas com uma function lógica à direita que retorna verdadeiro ou falso.

    Portanto, no primeiro exemplo, o ng-style é condicionado por três declarações. Se todos eles são falsos, nenhum estilo é aplicado, mas seguindo a nossa lógica, pelo menos um será aplicado, então, a expressão lógica irá verificar qual comparação de variável é verdadeira e porque uma matriz não vazia é sempre verdadeira, que irá Deixou um array como retorno e com apenas um verdadeiro, considerando que estamos usando OR para toda a resposta, o estilo restante será aplicado.

    By the way, eu esqueci de dar-lhe a function isActive ():

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

    NOVA ATUALIZAÇÃO

    Aqui você tem algo que eu acho realmente útil. Quando você precisa aplicar uma class dependendo do valor de uma variável, por exemplo, um ícone dependendo do conteúdo da div , você pode usar o seguinte código (muito útil em ng-repeat ):

      

    Ícones da fonte impressionante

    Isso funciona bem quando ng-class não pode ser usado (por exemplo, ao estilizar SVG):

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

    (Eu acho que você precisa estar no mais recente Angular instável para usar ng-attr-, atualmente estou em 1.1.4)

    Eu publiquei um artigo sobre como trabalhar com o AngularJS + SVG. Ele fala sobre esse assunto e muitos outros. http://www.codeproject.com/Articles/709340/Implementing-a-Flowchart-with-SVG-and-AngularJS

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

    e código

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

    Esta solução fez o truque para mim

     ... 

    Outra opção quando você precisa de um estilo CSS simples de uma ou duas propriedades:

    Visão:

      [...amazing code...]  {{ element.myvar }}  [...more amazing code...]  

    Controlador:

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

    Veja o exemplo a seguir

        Demo Changing CSS Classes Conditionally with Angular      Teams 

    Você pode usar a expressão ternária. Existem duas maneiras de fazer isso:

    ou…

    Como no AngularJS v1.2.0rc, ng-class e ng-attr-class falham com elementos SVG (Eles funcionaram antes, mesmo com a vinculação normal dentro do atributo class)

    Especificamente, nada disso funciona agora:

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

    Como uma solução alternativa, tenho que usar

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

    e, em seguida, estilo usando

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

    Mais uma maneira (no futuro) de aplicar o estilo condicionalmente é criando condicionalmente o estilo de escopo

      

    Mas atualmente apenas o FireFox suporta estilos com escopo.

    Bem, eu sugiro que você verifique a condição em seu controlador com uma function retornando verdadeiro ou falso .

     
    {{day.date}}

    e no seu controlador verifique a condição

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

    Há mais uma opção que descobri recentemente que algumas pessoas podem achar útil porque permite alterar uma regra de CSS dentro de um elemento de estilo – evitando assim a necessidade de uso repetido de uma diretiva angular como ng-style, ng-class, ng-show, ng-hide, ng-animate e outros.

    Esta opção faz uso de um serviço com variables ​​de serviço que são definidas por um controlador e assistidas por uma diretiva de atributo que eu chamo de “estilo personalizado”. Essa estratégia poderia ser usada de muitas maneiras diferentes, e tentei fornecer algumas orientações gerais com esse violino .

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

    Uma coisa a observar é – se o estilo CSS tiver traços – você deve removê-los. Então, se você quiser definir background-color , a maneira correta é:

     ng-style="{backgroundColor:myColor}"