Pro / con di utilizzo di direttive angolari per la validazione di forme complesse / la manipolazione della GUI

3

Sto costruendo un nuovo front-end SPA per sostituire il guazzabuglio legacy di sistemi esistenti che sono obsoleti e che necessitano di aggiornamento. Sono nuovo all'angolare e volevo vedere se la comunità potesse darmi una prospettiva. Indicherò il mio problema, quindi porrò la mia domanda.

Devo generare diverse serie di caselle di controllo basate sui dati di una .js include, con dati come questo:

$scope.fieldMappings.investmentObjectiveMap = [
  {'id':"CAPITAL PRESERVATION", 'name':"Capital Preservation"},
  {'id':"STABLE", 'name':"Moderate"},
  {'id':"BALANCED", 'name':"Moderate Growth"},
   // etc
  {'id':"NONE", 'name':"None"}
];

Le checkbox sono create usando una ng-repeat, come questa:

<div ng-repeat="investmentObjective in fieldMappings.investmentObjectiveMap">
 ...
</div>

Tuttavia, avevo bisogno dei valori rappresentati dalle caselle di controllo per eseguire il mapping su un modello diverso (non solo legato a 2 vie all'oggetto fieldmappings).

Per fare ciò, ho creato una direttiva, che accetta un destarray di array di destinazione che viene infine mappato al modello. So anche che ho bisogno di gestire alcuni controlli di gui molto specifici, come deselezionare "Nessuno" se qualcos'altro viene controllato, o controllare "Nessuno" se tutto il resto viene deselezionato.

Inoltre, "Nessuno" non sarà un'opzione in ogni gruppo di caselle di controllo, quindi la direttiva deve essere abbastanza generica da accettare una funzione di convalida che possa interferire con lo stato verificato degli input del gruppo di caselle di controllo in base a ciò che è già stato fatto clic , ma abbastanza intelligente da non interrompersi se non esiste un'opzione chiamata "NONE".

Ho iniziato a farlo aggiungendo un ng-click che invocava una funzione nel controller, ma guardando in Stack Overflow, leggo persone che dicono che è male inserire il codice di manipolazione DOM all'interno del controller - dovrebbe andare nelle direttive . Quindi ho bisogno di un'altra direttiva?

Finora: (html):

<input my-checkbox-group
          type="checkbox"
          fieldobj="investmentObjective"
          ng-click="validationfunc()"
          validationfunc="clearOnNone()"
          destarray="investor.investmentObjective" />

Codice direttiva:

.directive("myCheckboxGroup", function () {
  return {
    restrict: "A",
    scope: {
      destarray:      "=",  // the source of all the checkbox values
      fieldobj:       "=",  // the array the values came from
      validationfunc: "&"   // the function to be called for validation (optional)
    },
    link: function (scope, elem, attrs) {
      if (scope.destarray.indexOf(scope.fieldobj.id) !== -1) {
        elem[0].checked = true;
      }
      elem.bind('click', function () {
        var index = scope.destarray.indexOf(scope.fieldobj.id);
        if (elem[0].checked) {
          if (index === -1) {
            scope.destarray.push(scope.fieldobj.id);
          }
        }
        else {
          if (index !== -1) {
            scope.destarray.splice(index, 1);
          }
        }
      });
    }
  };
})

snippet del controller .js:

.controller( 'SuitabilityCtrl', ['$scope', function ( $scope ) {
  $scope.clearOnNone = function() {
    // naughty jQuery DOM manipulation code that
    // looks at checkboxes and checks/unchecks as needed
  };

Il codice sopra è fatto e funziona bene, tranne il codice jquery cattivo in clearOnNone (), motivo per cui ho scritto questa domanda.

Ed ecco la mia domanda: dopo TUTTO questo, penso a me stesso - potrei essere già fatto se ho gestito manualmente tutta questa logica GUI e la spazzatura di validazione con jQuery scritta nel mio controller. A che punto diventa sciocco scrivere queste complicate direttive che i futuri sviluppatori dovranno risolvere più che se avessi appena scritto il codice jQuery che il 99% di noi capirebbe con una sola occhiata? Come fanno gli altri sviluppatori a tracciare la linea?

Lo vedo dappertutto Stack Overflow. Ad esempio, questa domanda sembra possa rispondere a una dozzina di righe di semplice jQuery , tuttavia ha scelto di farlo in modo angolare, con una direttiva e un parziale ... sembra un sacco di lavoro per un semplice problema.

In particolare, suppongo che mi piacerebbe sapere: come DOVREI scrivere il codice che controlla se "Nessuno" è stato selezionato (se esiste come opzione in questo gruppo di checkbox), e quindi selezionare / deselezionare l'altro scatole di conseguenza? Una direttiva più complessa? Non posso credere di essere l'unico sviluppatore che sta implementando un codice che è più complesso del necessario solo per soddisfare un framework di opinioni.

    
posta tengen 07.10.2013 - 16:01
fonte

2 risposte

1

Secondo me, il modo più veloce per farlo in modo angolare è introdurre una proprietà dei tuoi dati javascript che traccia lo stato della casella di controllo. La tua funzione clearOnNone() modificherebbe una proprietà checked (introdotta dinamicamente) della tua investmentObjectiveMap . Questi aggiornamenti sarebbero immediatamente riflessi nel DOM. In questo modo non ci sono jQuery hacking nel bel mezzo del tuo controller.

I ha forked un vecchio violino del mio per darti un esempio.

html:

<div ng-app="myApp">
    <div ng-controller="MyCtrl">
        <event class="event" ng-repeat="event in events" event="{{ event.name }}"
               ng-class="{'selected' : event.selected}"
               ng-click="selectEvent($index)">
            {{ event.name }}
        </event>
        <br>
        <input ng-repeat="event in events" type="checkbox" ng-model="event.selected">
        <br>
        <button ng-click="selectNone()">select none</button>

    </div>
</div>

js:

var myApp = angular.module('myApp', []).controller('MyCtrl', function ($scope, $http) {
$scope.events = [
    {name: 'event1', selected: false},
    {name: 'event2', selected: false},
    {name: 'event3', selected: false}
];
$scope.selectEvent = function ($index) {
    var e = $scope.events[$index];
    e.selected = !e.selected;
};
$scope.selectNone = function () {
    $scope.events.forEach(function (event) {
        event.selected = false;
    });
};

});

Con ng-true-value e le direttive corrispondenti , puoi ottenere qualsiasi valore che desideri il tuo modello quando le caselle sono selezionate.

Modifica

Mi sono appena reso conto di aver frainteso il tuo comportamento di clearOnNone() , ma spero che tu possa vedere come modificare i dati e lasciare che il resto angolare faccia la risposta alla tua domanda.

    
risposta data 08.10.2013 - 17:20
fonte
0

Il tuo problema sembra essere facilmente risolvibile con l'associazione dati bidirezionale e alcune funzioni del gestore modello in un controller, ma scrivi che hai bisogno di più del binding all'oggetto fieldmappings?

Utilizzi effettivamente il modello di oggetti fieldmappings? Altrimenti, è possibile clonarne il contenuto su un modello proprio sull'inizializzazione del controller.

Dopodiché, imposta i modelli di caselle di controllo su false invece della manipolazione di jQuery DOM e Angular deselezionerà le caselle per te.

    
risposta data 08.11.2013 - 10:46
fonte

Leggi altre domande sui tag