2016-02-19 16 views
6

Ho un controller piuttosto complicato (circa 3K righe di codice) che dimostra la dashboard. Il controller contiene molti grafici, tabelle della griglia e così via.È buona norma utilizzare le direttive per suddividere la logica del controller in angolare?

Ad esempio, ho spostato la logica della tabella di griglia nella direttiva sottovoce denominata wmGridActionItems. Avviso, utilizza ambito padre:

app.directive('wmGridActionItems', ['$rootScope', '$timeout', function ($rootScope, $timeout) { 
     return { 
      restrict: 'E', 
      templateUrl: 'views/grid-action-items.html', 

      link: function (scope, elem, attrs) { 

       // logic goes here 
     } 
     }; 
    }]); 

e HTML:

<div ui-grid="gridActionItemsOptions"       
         ui-grid-auto-resize 
         ui-grid-pagination 
         ui-grid-selection 
         ui-grid-auto-resize 
         ui-grid-resize-columns> 
       </div> 

Quindi, in principale HTML regolatore ho appena scritto: <wm-grid-action-items></wm-grid-action-items>

non riesco a usare questa direttiva altri posti, ma almeno divido il mio controller BIG in diverse piccole direttive che dovrebbero aiutarmi a gestire la dashboard.

Ho fatto qualcosa di sbagliato? È una buona pratica? Ha altri approcci angolari per risolvere questo problema?

EDIT

Questa è la mia $StateProvider per la vista dashboard:

$stateProvider 
.state('sidemenu.dash', { 
        url: '/dshmngr', 
        abstract: true, 
        views: { 
         'content': { 
          templateUrl: 'views/dashboard/dashboard_manager.html', 
          controller: 'DashboardMngrCtrl' 
         } 
        } 


       }) 

       .state('sidemenu.dash.main', { 
        url: '/main', 
        views: { 
         'content': { 
          templateUrl: 'views/dashboard/dashboard-main.html', 
          controller: 'DashboardNewCtrl' 
         } 
        } 
       }) 


       .state('sidemenu.dash.drill', { 
        url: '/drill/:type', 
        views: { 
         'content': { 
          templateUrl: 'views/dashboard/dashboard-tag-details.html', 
          controller: 'DashboardDetailedCtrl' 
         } 
        } 
       }) 

Grazie,

+0

Piuttosto che inserire la logica del controller principale in una direttiva, perché non si crea _another_ controller e si inserisce la logica? Niente ti impedisce di avere più controller. – jperezov

+0

bene, provo a risolvere il problema attuale. Generalmente ho 3 controller con routing astratto e diverse sottoview. Ogni vista ha il proprio controller. ma dividere una vista su più controllori causerà la logica troppo complicata, trasmissioni, osservatori e così via – snaggs

+0

come una buona pratica che non vorrete fare gran parte della logica nel controller. E questo non si applica solo per i quadri angolari ma per i quadri MVC. Quindi vorrai rompere la logica nella direttiva nelle fabbriche o nei servizi. Come @jperov ha detto che puoi avere più controller e persino ereditare da uno ad altri – Radu

risposta

1

La "buona pratica" che mi sento di raccomandare a voi è il single responsibility principle.

Ogni componente (direttiva/controllore/servizio) creato non deve mai fare più di una cosa. Se si evita questo errore, i componenti saranno molto più riutilizzabili, leggibili e controllabili.

Naturalmente, questa pratica è non solo per angolare.

One rispetto che, io ti consiglierei di:

  • Evitare di mettere tutto il codice attività in controllori, e di utilizzare invece servizi (o fornitori). I servizi sono molto più potenti in quanto consentono di utilizzare il sistema di iniezione a dipendenza angolare.

  • Le direttive devono contenere solo la manipolazione DOM.

angolare direttiva/Controller/servizio è gentile di un modello View/ViewModel/Model. Cerca di tenerlo a mente.

Modifica: Ognuna delle vostre direttive può avere un controller. È possibile inserire direttive all'interno di un altro modello di direttiva e quindi utilizzare l'ultimo parametro della funzione di collegamento (controllers) e il parametro require per la comunicazione tra le direttive.

Esempio: (CoffeeScript) Diciamo che ho un contenitore che può essere all'interno di altri contenitori per sé e può contenere anche un widget:

angular.module('dashboard') 
.directive('dashboardWidget', [() -> 
    restrict: 'E' 
    templateUrl : '/views/dashboard/widget.html' 
    require: ['^^dashboardContainer'] 
    scope: 
     'model': '=' 
    controller: 'DashboardWidgetController' 
    controllerAs: 'DashboardWidget' 
    # default => post link (children already instanciated) 
    link: ($scope, element, attrs, ctrls) -> 
     [parentDashboardContainerController] = ctrls 

     # some very small code (mainly events), the real code is in the controller 

     return 
]) 

angular.module('dashboard') 
.directive('dashboardContainer', [() -> 
    restrict: 'E' 
    templateUrl : '/views/dashboard/container.html' 
    require: ['?^^dashboardContainer', '?^ngController'] 
    scope: 
     'model': '=' 
    controller: 'DashboardContainerController' 
    controllerAs: 'DashboardContainer' 
    # default => post link (children already instanciated) 
    link: ($scope, element, attrs, ctrls) -> 
     [parentDashboardContainerController, ngController] = ctrls 

     # some very small code (mainly events), the real code is in the controller 

     return 
]) 
+0

quando dico "circa 3K righe di codice" significa logica del controller NETO. a.e. UI. tutta la logica aziendale risiede nei servizi e nelle fabbriche, anzi – snaggs

+0

conosco bene il modello MVC e so che la direttiva è responsabilità dell'interfaccia utente e manipolazioni del DOM .... – snaggs

+0

Ciascuna delle tue direttive può avere un controller (con la proprietà 'controller'). Quindi dividi il tuo codice con il principio di responsabilità singola e questo dovrebbe essere molto più pulito. Personalmente, se uno dei miei file contiene più di 200 righe, comincio a chiedermi se non fa troppe cose. Questa è una cosa molto importante, specialmente nei grandi progetti. Un giorno tornerai ai tuoi file in modo da renderli facili da leggere. –

3

si sta puntando in direzione giusta. Rompere un controller di grandi dimensioni in componenti più piccoli sotto forma di direttive è la strada da percorrere, ma ti suggerisco di introdurre alcune modifiche.

  1. Isolare l'ambito della direttiva e definire i dati che la direttiva si aspetta esplicitamente. In questo modo si può immediatamente vedere quale direttiva dati accetta.

  2. Per semplificare i test accoppiare la direttiva con Controller.

Sulla base di queste due proposte, la vostra direttiva dovrebbe essere simile a questa:

app.directive('wmGridActionItems', [function() { 
     return { 
      controller: 'WmGridActionItemsController' 
      restrict: 'E', 
      templateUrl: 'views/grid-action-items.html', 
      scope: { 
       gridActionItemsOptions: '=gridActionItemsOptions' 
      } 
      link: function (scope, elem, attrs) { 
       // DOM manpulation (if needed) goes here 
      } 
     }; 
    }]); 

app.controller('WmGridActionItemsController', ['$cope', '$timeout', function ($cope, $timeout) { 
    // logic goes here 
}]); 

Si potrebbe quindi chiamare sopra direttiva come:

<wm-grid-action-items grid-action-item-options="gridActionItemsOptions"> 
</wm-grid-action-items> 

io suggerisco di leggere anche questo ottimo blog post che spiega in dettaglio "Motivo del componente".

Si noti inoltre che la condivisione di un modello specificandolo esplicitamente quando si definisce un ambito isolato non è l'unico modo. Un'altra alternativa per la condivisione di dati sarebbe ad esempio un modello come servizio (vedere related reading).

+0

mi è piaciuto il post 'Component Pattern' che hai fornito, grazie – snaggs

+0

Prego ... – PrimosK

Problemi correlati