2013-03-22 12 views
16

Sto utilizzando la direttiva fisarmonica da http://angular-ui.github.com/bootstrap/ e ho bisogno di avere più controllo su quando le fisarmoniche si aprono e si chiudono.Qual è un buon modo per controllare una fisarmonica angolare-ui a livello di programmazione?

Per essere più precisi ho bisogno di un pulsante all'interno del gruppo della fisarmonica che chiuderà la sua consolle principale e aprirà quella successiva (quindi fondamentalmente imita quello che farebbe clic sul prossimo header se close-altri fosse impostato su true). Devo anche fare un po 'di convalida prima di poter permettere che una fisarmonica venga chiusa e la prossima da aprire, e devo anche collegarla per fare clic sugli eventi sulle intestazioni di fisarmonica.

Sono abbastanza nuovo da angolare e al momento stiamo riscrivendo un'applicazione da Backbone + JQuery ad Angular. Nella versione Backbone stavamo usando le fisarmoniche Twitter Bootstrap e le stavamo aprendo e chiudendo usando JQuery. Mentre possiamo continuare a farlo, preferirei eliminare completamente la manipolazione del JQuery DOM, quindi sto cercando una soluzione angolare pura a questo.

Quello che ho cercato di fare in termini di convalida è

<accordion-group ng-click="close($event)"> 

e nel mio controller

event.preventDefault(); 
    event.stopPropagation(); 

Questo, ovviamente, non ha funzionato come l'elemento DOM è sostituita dalla direttiva e la il gestore di clic non viene mai aggiunto. Ho esaminato il codice sorgente (e ho trovato alcune caratteristiche non documentate molto belle) ma non riesco a capire dove iniziare a risolvere questa specifica sfida. Stavo considerando biforcarsi angolare-ui e provare ad aggiungere questa funzionalità alla direttiva fisarmonica, ma se riuscirò a ottenere ciò senza modificare la direttiva sarebbe molto più bello.

risposta

23

C'è l'attributo is-open sullo accordion-group che punta a un'espressione associabile. Utilizzando questa espressione è possibile controllare gli elementi di fisarmonica programatically, es .:

<div ng-controller="AccordionDemoCtrl"> 
    <accordion> 
    <accordion-group ng-repeat="group in groups" heading="{{group.title}}" is-open="group.open"> 
     {{group.content}} 
    </accordion-group>  
    </accordion> 
    <button class="btn" ng-click="groups[0].open = !groups[0].open">Toggle first open</button> 
    <button class="btn" ng-click="groups[1].open = !groups[1].open">Toggle second open</button> 
</div> 

e la lavorazione buttare qui: http://plnkr.co/edit/DepnVH?p=preview

+0

Grazie, i miei pulsanti funzionano come se ne avessi bisogno. La mia altra domanda, però, è come farei una sorta di validazione prima di consentire la seconda fisarmonica (praticamente impedendo che venga ampliata). Ho modificato il plunk per lavorare con i pulsanti: http://plnkr.co/edit/J5hnuA?p=preview Ma mi stavo chiedendo se è possibile impedire l'apertura della seconda fisarmonica facendo clic sull'intestazione anche? – ivarni

+0

(Nel mio plunk non è possibile attivare la fisarmonica n. 2 facendo clic sul pulsante a meno che la casella di spunta in # 1 sia selezionata, ma è ancora possibile aprire n. 2 facendo clic sull'intestazione) – ivarni

+0

Sembra che non sia possibile eseguire alcuna convalida prima dell'apertura una nuova fisarmonica dal momento che il click-handler nel template dice semplicemente ng-click = "isOpen =! isOpen" – ivarni

5

Per chi la soluzione @ pkozlowski.opensource non funziona (io per esempio) potrebbe semplicemente forzare il componente ad accettare il CSS che lo chiuderà (senza transizione che sia).

Teoria: La direttiva angolare viene espansa in HTML standard, principalmente gli elementi div, in cui gli stili CSS gli danno l'aspetto della fisarmonica. Il div con classe .panel-collapse è il corpo dell'elemento del gruppo di fisarmonica. Puoi scambiare la sua seconda classe da .in a .collapse insieme ad alcune altre modifiche come mostrato di seguito.

Il Codice:

$scope.toggleOpen = function(project) { 

     var id = '<The ID of the accordion-group you want to close>'; 
     var elements = angular.element($document[0].querySelector('#'+id)); 
     var children = elements.children(); 

     for(var i = 0; i < children.length; i++) { 

      var child = angular.element(children[i]); 

      if(child.hasClass('panel-collapse')) { 
       if(child.hasClass('in')) { // it is open 
        child.removeClass('in'); 
        child.addClass('collapse'); 
        child.css('height', '0px'); 
       } else { // it is closed 
        child.addClass('in'); 
        child.removeClass('collapse'); 
        child.css('height', 'auto'); 
       } 

      } 
     } 
    }; 

Come stiamo parlando di angolare, è molto probabile che si sta generando la fisarmonica attraverso un tag ng-repeat. In questo caso si può anche generare l'ID del per gli elementi come:

<accordion-group ng-repeat="user in users" 
       is-disabled="user.projects.length == 0" 
       id="USER{{user._id}}"> 

Dato un modello di Mongoose utente, si noti che l'id sto dando non è user._id ma ha 'UTENTE' aggiunto di fronte. Questo perché Mongoose potrebbe generare id che iniziano numericamente e querySelector non gli piace ;-) go figure!

+1

Anche se questo non è il migliore rispondi alla domanda dell'OP, è una buona idea di Angular & Bootstrap –