Ich habe eine AngularJS- Direktive , die eine Sammlung von Entitäten in der folgenden Vorlage rendert:
<table class="table">
<thead>
<tr>
<th><input type="checkbox" ng-click="selectAll()"></th>
<th>Title</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="e in entities">
<td><input type="checkbox" name="selected" ng-click="updateSelection($event, e.id)"></td>
<td>{{e.title}}</td>
</tr>
</tbody>
</table>
Wie Sie sehen können, kann <table>
hier jede Zeile einzeln mit einem eigenen Kontrollkästchen ausgewählt werden, oder es können alle Zeilen gleichzeitig mit einem Master-Kontrollkästchen im Feld ausgewählt werden <thead>
. Ziemlich klassische Benutzeroberfläche.
Was ist der beste Weg, um:
- Wählen Sie eine einzelne Zeile aus (dh wenn das Kontrollkästchen aktiviert ist, fügen Sie die ID der ausgewählten Entität einem internen Array hinzu und fügen Sie
<tr>
der Entität, die die Entität enthält , eine CSS-Klasse hinzu , um den ausgewählten Status wiederzugeben)? - Alle Zeilen gleichzeitig auswählen? (dh führen Sie die zuvor beschriebenen Aktionen für alle Zeilen in der
<table>
)
Meine aktuelle Implementierung besteht darin, meiner Direktive einen benutzerdefinierten Controller hinzuzufügen:
controller: function($scope) {
// Array of currently selected IDs.
var selected = $scope.selected = [];
// Update the selection when a checkbox is clicked.
$scope.updateSelection = function($event, id) {
var checkbox = $event.target;
var action = (checkbox.checked ? 'add' : 'remove');
if (action == 'add' & selected.indexOf(id) == -1) selected.push(id);
if (action == 'remove' && selected.indexOf(id) != -1) selected.splice(selected.indexOf(id), 1);
// Highlight selected row. HOW??
// $(checkbox).parents('tr').addClass('selected_row', checkbox.checked);
};
// Check (or uncheck) all checkboxes.
$scope.selectAll = function() {
// Iterate on all checkboxes and call updateSelection() on them??
};
}
Genauer gesagt frage ich mich:
- Gehört der obige Code in eine Steuerung oder sollte er in eine
link
Funktion gehen? - Was ist der beste Weg, um DOM-Traversal durchzuführen, da jQuery nicht unbedingt vorhanden ist (AngularJS benötigt es nicht)? Ohne jQuery fällt es mir schwer, nur das übergeordnete
<tr>
Kontrollkästchen oder alle Kontrollkästchen in der Vorlage auszuwählen. - Die Weitergabe
$event
anupdateSelection()
scheint nicht sehr elegant zu sein. Gibt es nicht eine bessere Möglichkeit, den Status (aktiviert / deaktiviert) eines Elements abzurufen, auf das gerade geklickt wurde?
Vielen Dank.
quelle
ngChecked
Richtlinie erfahren . (Ich bedaure nur, dass wir diesen Code nicht weniger ausführlich machen können.)Ich bevorzuge die Anweisungen ngModel und ngChange, wenn es um Kontrollkästchen geht . Mit ngModel können Sie den aktivierten / deaktivierten Status des Kontrollkästchens an eine Eigenschaft der Entität binden:
<input type="checkbox" ng-model="entity.isChecked">
Immer wenn der Benutzer das Kontrollkästchen aktiviert oder deaktiviert
entity.isChecked
, ändert sich auch der Wert.Wenn dies alles ist, was Sie brauchen, brauchen Sie nicht einmal die Anweisungen ngClick oder ngChange. Da Sie das Kontrollkästchen "Alle überprüfen" haben, müssen Sie natürlich mehr tun, als nur den Wert der Eigenschaft festzulegen, wenn jemand ein Kontrollkästchen aktiviert.
Wenn Sie ngModel mit einem Kontrollkästchen verwenden, verwenden Sie am besten ngChange anstelle von ngClick, um aktivierte und nicht aktivierte Ereignisse zu behandeln. ngChange ist genau für diese Art von Szenario gemacht. Der ngModelController wird für die Datenbindung verwendet (er fügt dem
$viewChangeListeners
Array des ngModelController einen Listener hinzu . Die Listener in diesem Array werden aufgerufen, nachdem der Modellwert festgelegt wurde, um dieses Problem zu vermeiden ).<input type="checkbox" ng-model="entity.isChecked" ng-change="selectEntity()">
... und in der Steuerung ...
var model = {}; $scope.model = model; // This property is bound to the checkbox in the table header model.allItemsSelected = false; // Fired when an entity in the table is checked $scope.selectEntity = function () { // If any entity is not checked, then uncheck the "allItemsSelected" checkbox for (var i = 0; i < model.entities.length; i++) { if (!model.entities[i].isChecked) { model.allItemsSelected = false; return; } } // ... otherwise ensure that the "allItemsSelected" checkbox is checked model.allItemsSelected = true; };
Ebenso das Kontrollkästchen "Alle prüfen" in der Kopfzeile:
<th> <input type="checkbox" ng-model="model.allItemsSelected" ng-change="selectAll()"> </th>
... und ...
// Fired when the checkbox in the table header is checked $scope.selectAll = function () { // Loop through all the entities and set their isChecked property for (var i = 0; i < model.entities.length; i++) { model.entities[i].isChecked = model.allItemsSelected; } };
CSS
Wenn Sie den ngModel-Ansatz für die Datenbindung verwenden, müssen Sie dem Element lediglich die ngClass- Direktive
<tr>
hinzufügen, um die Klasse dynamisch hinzuzufügen oder zu entfernen, wenn sich die Entitätseigenschaft ändert:<tr ng-repeat="entity in model.entities" ng-class="{selected: entity.isChecked}">
Den vollständigen Plunker finden Sie hier .
quelle
Livius Antwort war sehr hilfreich für mich. Hoffe, das ist keine schlechte Form, aber ich habe eine Geige gemacht , die in Zukunft jemand anderem helfen könnte.
Zwei wichtige Teile, die benötigt werden, sind:
$scope.entities = [{ "title": "foo", "id": 1 }, { "title": "bar", "id": 2 }, { "title": "baz", "id": 3 }]; $scope.selected = [];
quelle