2013-04-04 16 views
14

Sto provando a creare una direttiva per consentire all'utente di navigare la pagina con i tasti freccia per sezione. Ma voglio anche essere in grado di avere quelle sezioni sparse per il dom, e di fare in modo che non si rompano quando le cose vengono aggiunte e rimosse. Mi viene in mente diversi modi per fare questo, ma nessuno di loro sono soddisfacenti:Angularjs: trova tutte le istanze di una direttiva

  • Creare una direttiva con un controller che permette altre direttive si registrano (e annullare la registrazione su $ distruggere). Ma questo sarà fuori uso se aggiungo qualcosa nel mezzo più tardi. Inoltre, ho provato a scrivere in questo modo, e sembra molto più codice del necessario.

  • Ogni volta che l'utente preme un tasto freccia, crea un array vuoto e $ trasmette un evento, con un callback per le direttive che si registrano in tale elenco. Quindi, una volta che la lista è piena, avanzare o tornare indietro. Loro (dovrebbero?) Tornare nell'ordine in cui sono sul DOM, ma non sono sicuro visto che in questo modo sembra pazzo e hackish.

  • Contrassegna le cose che sono "tabbable" con css e scrivi questo nel modo più semplice in jquery, qualcosa del genere: in un nuovo evento click, var all = $('.tabbable'), e poi fai l'ovvio con quello. Ma davvero non voglio farlo in quel modo, perché non è il modo "angolare". Non per un senso di purezza, ma perché sto costruendo questo come parte di una più ampia libreria di widget, e voglio che questa funzionalità sia accessibile a loro.

Quindi, non v'è alcun modo per me per ottenere gli scopi di tutte le direttive di un certo tipo, senza ricorrere a hack strani, o diffondere la logica in tutto il luogo?

risposta

2

AngularJS services sono singleton e possono essere richiesti tramite l'iniezione dipendente. Potresti avere le tue direttive che richiedono un servizio di gestione dello stato e chiamare incrementatori/decrementatori.

In alternativa, un po 'più semplice ma più fragile, è possibile mantenere un array in $ rootScope. È più "angolare" idiomatico (ma non di molto) di un selettore jQuery globale, ma probabilmente non è il percorso migliore se stai costruendo una libreria di widget.

+0

Qualche suggerimento per gestire l'ordine di quell'array mentre vengono mescolati in giro? – doubledriscoll

+0

Penso che avrei bisogno di capire i requisiti un po 'meglio prima di dare un suggerimento. Vuoi ordinare gerarchicamente, in ordine cronologico rispetto all'inserimento DOM, ecc.? –

5

Questa è una buona domanda. +1

Innanzitutto, trovare tutte le direttive o i nodi per tipo va contro la modalità Angolare. The View è il record ufficiale di AngularJS, quindi le direttive dovrebbero dire quello che fanno e fare ciò che dicono. La codifica di alcuni processi da qualche parte per eseguire la scansione dei nodi DOM e agire di conseguenza è problematica per diversi motivi, non ultimo dei quali sono la separazione delle preoccupazioni e la testabilità.

Sono lieto di vedere che stai guardando altre opzioni, ma sono d'accordo che le altre opzioni che hai fornito sono sub-ottimali per le ragioni stesse che hai menzionato. Ma ne ho uno in più. Questo è quello che ho usato per un'applicazione diversa, ma che richiedeva la conoscenza dei nodi DOM sparsi.

Per prima cosa, creiamo un servizio per gestire lo stato di questo componente. È semplice. Chiamiamolo SectionsService. Successivamente, creiamo una direttiva per registrare le sezioni. Chiamiamo questo section per semplicità. La direttiva section registra l'ID del nodo DOM (forse creato in modo programmatico per garantire l'univocità) con lo SectionsService durante la sua fase di collegamento. Poiché il DOM viene elaborato (principalmente) in ordine, i nodi aggiunti a SectionsService saranno anche in ordine.Così il DOM simile a questa (roba irrilevante omesso):

<div section>...</div> 

<!-- other stuff --> 

<div section>...</div> 

<!-- other stuff --> 

<!-- etc. --> 

(anche se fuori del campo di applicazione qui, non sarebbe molto difficile da programmare in modo tale che l'ordine non sarebbe un problema, ma è essere basato su specifiche della tua app che non conosco.)

Successivamente, si creano i trigger, come un gestore di tasti freccia. Su questi eventi, è sufficiente comunicare allo SectionService di passare al nodo precedente/successivo nell'elenco. AngularJS viene fornito con un servizio chiamato $anchorScroll che può essere utilizzato per emulare il posizionamento basato su hash del browser con cui abbiamo familiarità. Ovviamente potresti anche usare un plugin jQuery per animare lo scrolling se lo desideri.

E questo è tutto! Una direttiva molto semplice, un servizio abbastanza semplice e qualsiasi trigger necessario. Tutto sommato, immagino meno di 100 righe di codice, inclusi test. Tutti i componenti sono disaccoppiati e facilmente testabili, ma ancora molto semplici. La vista rimane The Truth. La Via Angolare è preservata.

E c'era molta gioia.


Spero che questo ti metta sulla giusta direzione, ma ovviamente non esitate a fare una domanda di follow-up. Possiamo anche parlare di specifiche del codice, se lo desideri; come ho detto, non sarebbero molto complicati.

+0

Concordo sul fatto che un servizio sia una buona soluzione, ma come faccio a ottenere la lista delle cose tabbable in un ordine che riflette la dom, in quanto vengono aggiunte e rimosse arbitrariamente? (se una serie di elementi tabbable viene ordinata o mescolata, voglio che il loro ordine di tabulazione rispecchi il loro ordine sulla pagina.) Attualmente sono tornato alla "trasmissione di un callback" su ogni azione di navigazione, per ottenerli nell'ordine I bisogno e sta funzionando abbastanza bene (Ho erroneamente pensato che la trasmissione $ fosse asincrona, il che avrebbe reso la soluzione molto più spiacevole) – doubledriscoll

+0

Non sono sicuro di cosa intendi per la trasmissione. Qualsiasi componente o direttiva può comunicare con 'SectionService', quindi non dovrebbe esserci alcun problema a notificarlo delle modifiche. –

Problemi correlati