Diciamo che hai un array che è reso in un ul
con un li
per ogni elemento e una proprietà sul controller chiamata selectedIndex
. Quale sarebbe il modo migliore per aggiungere una classe al li
con l'indice selectedIndex
in AngularJS?
Attualmente sto duplicando (a mano) il codice li
e aggiungendo la classe a uno dei tag li
e usando ng-show
e ng-hide
per mostrare solo un li
per indice.
Se non volete mettere i nomi delle classi CSS in Controller come faccio io, ecco un vecchio trucco che uso fin dai giorni pre-v1. Possiamo scrivere un'espressione che valuta direttamente un nome di classe selezionato, non sono necessarie direttive personalizzate:
ng:class="{true:'selected', false:''}[$index==selectedIndex]"
*Si prega di notare la vecchia sintassi con i due punti.
C'è anche un nuovo modo migliore di applicare le classi in modo condizionale, come:
ng-class="{selected: $index==selectedIndex}"
Angular ora supporta le espressioni che restituiscono un oggetto. Ogni proprietà (nome) di questo oggetto è ora considerata come un nome di classe e viene applicata a seconda del suo valore.
Tuttavia questi modi non sono funzionalmente uguali. Ecco un esempio:
ng-class="{admin:'enabled', moderator:'disabled', '':'hidden'}[user.role]"
Potremmo quindi riutilizzare le classi CSS esistenti fondamentalmente mappando una proprietà del modello in un nome di classe e allo stesso tempo mantenere le classi CSS fuori dal codice del Controller.
Ecco una soluzione molto più semplice:
function MyControl($scope){
$scope.values = ["a","b","c","d","e","f"];
$scope.selectedIndex = -1;
$scope.toggleSelect = function(ind){
if( ind === $scope.selectedIndex ){
$scope.selectedIndex = -1;
} else{
$scope.selectedIndex = ind;
}
}
$scope.getClass = function(ind){
if( ind === $scope.selectedIndex ){
return "selected";
} else{
return "";
}
}
$scope.getButtonLabel = function(ind){
if( ind === $scope.selectedIndex ){
return "Deselect";
} else{
return "Select";
}
}
}
.selected {
color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
<div ng-app ng-controller="MyControl">
<ul>
<li ng-class="getClass($index)" ng-repeat="value in values" >{{value}} <button ng-click="toggleSelect($index)">{{getButtonLabel($index)}}</button></li>
</ul>
<p>Selected: {{selectedIndex}}</p>
</div>
Ho affrontato un problema simile di recente e ho deciso di creare semplicemente un filtro condizionale:
angular.module('myFilters', []).
/**
* "if" filter
* Simple filter useful for conditionally applying CSS classes and decouple
* view from controller
*/
filter('if', function() {
return function(input, value) {
if (typeof(input) === 'string') {
input = [input, ''];
}
return value? input[0] : input[1];
};
});
Prende un singolo argomento, che è o un array di 2 elementi o una stringa, che viene trasformata in un array a cui viene aggiunta una stringa vuota come secondo elemento:
<li ng-repeat="item in products | filter:search | orderBy:orderProp |
page:pageNum:pageLength" ng-class="'opened'|if:isOpen(item)">
...
</li>