Come rispondere ai clic su una casella di controllo in una direttiva AngularJS?

Ho una direttiva AngularJS che esegue il rendering di una raccolta di quadro nel seguente modello:

Title
{{e.title}}

Come puoi vedere, è un

cui ogni riga può essere selezionata individualmente con una propria casella di controllo, oppure tutte le righe possono essere selezionate contemporaneamente con una casella di controllo principale situata in

. Interfaccia utente classica.

Qual è il modo migliore per:

  • Seleziona una singola riga (cioè quando la casella è selezionata, aggiungi l’id dell’ quadro selezionata a una matrice interna e aggiungi una class CSS alla
contenente l’ quadro per riflettere il suo stato selezionato)?
  • Seleziona tutte le righe contemporaneamente? (cioè fai le azioni precedentemente descritte per tutte le righe nella
  • )

    La mia attuale implementazione è di aggiungere un controller personalizzato alla mia direttiva:

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

    Più specificamente, mi chiedo:

    • Il codice sopra appartiene a un controller o dovrebbe andare in una funzione di link ?
    • Dato che jQuery non è necessariamente presente (AngularJS non lo richiede), qual è il modo migliore per fare DOM traversal? Senza jQuery, ho difficoltà a selezionare la parent
    di una casella di controllo specifica o selezionare tutte le caselle di controllo nel modello.
  • Passare $event a updateSelection() non sembra molto elegante. Non c’è un modo migliore per recuperare lo stato (selezionato / deselezionato) di un elemento che è stato appena cliccato?
  • Grazie.

    Questo è il modo in cui ho fatto questo genere di cose. Angular tende a favorire la manipolazione dichiarativa del dom piuttosto che un imperativo (almeno questo è il modo in cui ho giocato con esso).

    Il markup

     
    Title
    {{e.title}}

    E nel controller

     var updateSelected = function(action, id) { if (action === 'add' && $scope.selected.indexOf(id) === -1) { $scope.selected.push(id); } if (action === 'remove' && $scope.selected.indexOf(id) !== -1) { $scope.selected.splice($scope.selected.indexOf(id), 1); } }; $scope.updateSelection = function($event, id) { var checkbox = $event.target; var action = (checkbox.checked ? 'add' : 'remove'); updateSelected(action, id); }; $scope.selectAll = function($event) { var checkbox = $event.target; var action = (checkbox.checked ? 'add' : 'remove'); for ( var i = 0; i < $scope.entities.length; i++) { var entity = $scope.entities[i]; updateSelected(action, entity.id); } }; $scope.getSelectedClass = function(entity) { return $scope.isSelected(entity.id) ? 'selected' : ''; }; $scope.isSelected = function(id) { return $scope.selected.indexOf(id) >= 0; }; //something extra I couldn't resist adding :) $scope.isSelectedAll = function() { return $scope.selected.length === $scope.entities.length; }; 

    EDIT : getSelectedClass() aspetta l’intera entity framework ma è stata chiamata con l’id dell’entity framework solo, che ora è corretta

    Preferisco usare le direttive ngModel e ngChange quando si gestiscono le checkbox . ngModel ti consente di associare lo stato selezionato / deselezionato della casella di controllo a una proprietà sull’ quadro:

      

    Ogni volta che l’utente controlla o deseleziona la casella di controllo entity.isChecked valore entity.isChecked .

    Se questo è tutto ciò di cui hai bisogno, allora non hai nemmeno bisogno delle direttive ngClick o ngChange. Dato che hai la casella di controllo “Seleziona tutto”, devi ovviamente fare molto di più che impostare semplicemente il valore della proprietà quando qualcuno controlla una casella di controllo.

    Quando si utilizza ngModel con una casella di controllo, è meglio utilizzare ngChange piuttosto che ngClick per la gestione degli eventi selezionati e non selezionati. ngChange è fatto solo per questo tipo di scenario. Utilizza ngModelController per l’ associazione dati (aggiunge un listener all’array $viewChangeListeners . Gli ascoltatori in questo array vengono chiamati dopo aver impostato il valore del modello, evitando questo problema ).

      

    … e nel controller …

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

    Allo stesso modo, la casella di controllo "Seleziona tutto" nell'intestazione:

        

    ... e ...

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

    Qual è il modo migliore per ... aggiungere una class CSS al

    contenente l'entity framework per riflettere il suo stato selezionato?

    Se si utilizza l'approccio ngModel per l'associazione dati, tutto ciò che si deve fare è aggiungere la direttiva ngClass all'elemento

    per aggiungere o rimuovere dynamicmente la class ogni volta che la proprietà dell' quadro cambia:

      

    Vedi il Plunker completo qui .

    La risposta di Liviu è stata estremamente utile per me. Spero che questa non sia una ctriggers forma ma ho fatto un violino che potrebbe aiutare qualcun altro in futuro.

    Due pezzi importanti che sono necessari sono:

      $scope.entities = [{ "title": "foo", "id": 1 }, { "title": "bar", "id": 2 }, { "title": "baz", "id": 3 }]; $scope.selected = [];