Q1. Supposons que je veuille modifier l'apparence de chaque "élément" qu'un utilisateur sélectionne pour suppression avant d'appuyer sur le bouton principal "Supprimer". (Ce retour visuel immédiat devrait éliminer le besoin de la boîte de dialogue proverbiale "êtes-vous sûr?".) L'utilisateur cochera les cases pour indiquer les éléments à supprimer. Si une case à cocher n'est pas cochée, cet élément devrait revenir à son aspect normal.
Quelle est la meilleure façon d'appliquer ou de supprimer le style CSS?
Q2. Supposons que je veuille permettre à chaque utilisateur de personnaliser la présentation de mon site. Par exemple, choisissez parmi un ensemble fixe de tailles de police, autorisez les couleurs de premier plan et d'arrière-plan, etc.
Quelle est la meilleure façon d'appliquer le style CSS que l'utilisateur sélectionne/entre?
Angular fournit un certain nombre de directives intégrées permettant de manipuler le style CSS de manière conditionnelle/dynamique:
La "voie angulaire" normale implique de lier une propriété model/scope à un élément d'interface utilisateur qui acceptera les entrées/manipulations de l'utilisateur (c'est-à-dire, utilisez ng-model), puis d'associer cette propriété de modèle à l'une des directives intégrées susmentionnées.
Lorsque l'utilisateur modifie l'interface utilisateur, Angular mettra automatiquement à jour les éléments associés sur la page.
ng-class accepte une "expression" qui doit être évaluée comme suit:
En supposant que vos éléments sont affichés à l'aide de ng-repeat sur un modèle de tableau, et que, lorsque la case à cocher correspondant à un élément est cochée, vous souhaitez appliquer la classe 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>
Ci-dessus, nous avons utilisé le type d'expression ng-class # 3 - une carte/objet de noms de classes en valeurs booléennes.
ng-style accepte une "expression" qui doit avoir pour résultat:
Pour un exemple artificiel, supposons que l'utilisateur puisse taper un nom de couleur dans une texbox pour la couleur d'arrière-plan (un sélecteur de couleur jQuery serait beaucoup plus agréable):
<div class="main-body" ng-style="{color: myColor}">
...
<input type="text" ng-model="myColor" placeholder="enter a color name">
Le violon contient également un exemple de ng-show et ng-hide. Si une case à cocher est cochée, du texte s'affiche, en plus de la couleur d'arrière-plan virant au rose. Si 'rouge' est entré dans la zone de texte, un div devient caché.
J'ai rencontré des problèmes lors de l'application de classes à l'intérieur d'éléments table alors qu'une classe était déjà appliquée à l'ensemble du tableau (par exemple, une couleur appliquée aux lignes impaires <myClass tbody tr:nth-child(even) td>
). Il semble que lorsque vous inspectez l'élément avec Developer Tools, aucun style n'est attribué au element.style
. Ainsi, au lieu d’utiliser ng-class
, j’ai essayé d’utiliser ng-style
et, dans ce cas, le nouvel attribut CSS apparaît dans element.style
. Ce code fonctionne très bien pour moi:
<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>
J'évalue Myvar et, dans chaque cas, j'applique un style à chaque <td>
en fonction de la valeur myvar, qui écrase le style actuel appliqué par la classe CSS pour l'ensemble du tableau.
METTRE &AGRAVE; JOUR
Si vous souhaitez appliquer une classe à la table, par exemple, lors de la visite d'une page ou dans d'autres cas, vous pouvez utiliser cette structure:
<li ng-class="{ active: isActive('/route_a') || isActive('/route_b')}">
Fondamentalement, ce dont nous avons besoin pour activer une classe ng est la classe à appliquer et une déclaration vraie ou fausse. True applique la classe et false ne l'applique pas. Nous avons donc ici deux contrôles de la route de la page et un OU entre eux, donc si nous sommes dans /route_a
OU nous sommes dans route_b
, la classe active sera sois appliqué.
Cela fonctionne simplement en ayant une fonction logique à droite qui renvoie vrai ou faux.
Ainsi, dans le premier exemple, ng-style est conditionné par trois instructions. Si tous sont faux, aucun style n'est appliqué, mais suivant notre logique, au moins un va être appliqué, ainsi, l'expression logique va vérifier quelle comparaison de variable est vraie et comme un tableau non vide est toujours vrai, laissé un tableau comme retour et avec un seul vrai, étant donné que nous utilisons OU pour toute la réponse, le style restant sera appliqué.
Au fait, j'ai oublié de vous donner la fonction isActive ():
$rootScope.isActive = function(viewLocation) {
return viewLocation === $location.path();
};
NOUVELLE MISE À JOUR
Ici, vous avez quelque chose que je trouve vraiment utile. Lorsque vous devez appliquer une classe en fonction de la valeur d'une variable, par exemple une icône en fonction du contenu de la div
, vous pouvez utiliser le code suivant (très utile dans ng-repeat
):
<i class="fa" ng-class="{ 'fa-github' : type === 0,
'fa-linkedin' : type === 1,
'fa-skype' : type === 2,
'fa-google' : type === 3 }"></i>
Icônes de Font Awesome
Cela fonctionne bien lorsque ng-class ne peut pas être utilisé (par exemple lors du stylage de SVG):
ng-attr-class="{{someBoolean && 'class-when-true' || 'class-when-false' }}"
(Je pense que vous devez être sur la dernière angulaire instable pour utiliser ng-attr-, je suis actuellement sur la 1.1.4)
J'ai publié un article sur le travail avec AngularJS + SVG. Il parle de ce problème et de nombreux autres. http://www.codeproject.com/Articles/709340/Implementing-a-Flowchart-with-SVG-and-AngularJS
span class="circle circle-{{selectcss(document.Extension)}}">
et code
$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);
}
Cette solution a fait le tour pour moi
<a ng-style="{true: {paddingLeft: '25px'}, false: {}}[deleteTriggered]">...</a>
Une autre option lorsque vous avez besoin d’un style CSS simple d’une ou deux propriétés:
Vue:
<tr ng-repeat="element in collection">
[...amazing code...]
<td ng-style="{'background-color': getTrColor(element.myvar)}">
{{ element.myvar }}
</td>
[...more amazing code...]
</tr>
Manette:
$scope.getTrColor = function (colorIndex) {
switch(colorIndex){
case 0: return 'red';
case 1: return 'green';
default: return 'yellow';
}
};
Vous pouvez utiliser l'expression ternaire. Il y a deux façons de faire ça:
<div ng-style="myVariable > 100 ? {'color': 'red'} : {'color': 'blue'}"></div>
ou...
<div ng-style="{'color': (myVariable > 100) ? 'red' : 'blue' }"></div>
Voir l'exemple suivant
<!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>
À partir de AngularJS v1.2.0rc, ng-class
et même ng-attr-class
échouent avec les éléments SVG (ils fonctionnaient auparavant, même avec une liaison normale dans l'attribut de classe)
Plus précisément, aucun de ceux-ci ne fonctionne maintenant:
ng-class="current==this_element?'active':' ' "
ng-attr-class="{{current==this_element?'active':' '}}"
class="class1 class2 .... {{current==this_element?'active':''}}"
Pour contourner le problème, je dois utiliser
ng-attr-otherAttr="{{current==this_element?'active':''}}"
puis coiffez avec
[otherAttr='active'] {
... styles ...
}
eh bien, je vous suggère de vérifier la condition de votre contrôleur avec une fonction retournant vrai ou faux .
<div class="week-wrap" ng-class="{today: getTodayForHighLight(todayDate, day.date)}">{{day.date}}</div>
et dans votre contrôleur vérifier l'état
$scope.getTodayForHighLight = function(today, date){
return (today == date);
}
Une autre manière (à l’avenir) d’appliquer du style de manière conditionnelle consiste à créer conditionnellement un style
<style scoped type="text/css" ng-if="...">
</style>
Mais à présent, seul FireFox prend en charge les styles étendus.
Il y a une autre option que j'ai récemment découverte que certaines personnes peuvent trouver utile, car elle vous permet de modifier une règle CSS dans un élément de style, évitant ainsi l'utilisation répétée d'une directive angulaire comme ng-style, ng-class ng-show, ng-hide, ng-animate et autres.
Cette option utilise un service avec des variables de service définies par un contrôleur et surveillées par une directive d'attribut que j'appelle "style personnalisé". Cette stratégie pourrait être utilisée de nombreuses manières différentes, et j’ai essayé de fournir quelques indications générales avec ce violon .
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);
}
};
});
Une chose à regarder est - si le style CSS a des tirets - vous devez les supprimer. Donc, si vous voulez définir background-color
, la manière correcte est:
ng-style="{backgroundColor:myColor}"
Voici comment j'ai appliqué conditionnellement le style de texte gris sur un bouton désactivé
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);
}
}
Voici un exemple de travail:
https://stackblitz.com/edit/example-conditional-disable-button?file=src%2Fapp%2Fapp.component.html