2013-03-16 19 views
6

Utilizzo di angular e jquery Ho implementato la funzione slideToggle. Per applicare questa funzione solo a uno specifico elemento HTML, sto usando all'interno di funzione un parametro ng-click, il mio codice funziona bene ma, voglio sapere se esiste un altro modo migliore per implementare le direttive e le funzioni di ng-clic in angolare:Implementazione della funzione Angular Directive e Jquery slideToggle

index.html

<!DOCTYPE html> 
<html ng-app="myApp" ng-controller="MainController"> 
<head> 
    <title></title> 
    <link type="text/css" rel="stylesheet" href="css/styles.css"/> 
</head> 
<body> 
    <div> 
     <input type="button" ng-click="toggle('first')" value="Toggle First"> 
     <input type="button" ng-click="toggle('second')" value="Toggle Second"> 
     <input type="button" ng-click="toggle('third')" value="Toggle third"> 
     <div class="div1" section="first" toggle="first" > 
      <p>This is section #1</p> 
     </div> 
     <div class="div1" toggle="second"> 
      <p>This is another section #1</p> 
     </div> 
     <div class="div1" toggle="third"> 
      <p>This is 3 section #1</p> 
     </div> 
    </div> 
</body> 
<footer> 
    <script src="js/jquery.min.js"></script> 
    <script src="js/angular.js"></script> 
    <script src="js/directives.js"></script> 
</footer> 
</html> 

styles.css

.div1 { 
    background: Brown; 
    width: 200px; 
    height: 200px; 
    text-align: center; 
} 
.div1 p { 
    position: relative; 
    top: 50%; 
} 

directives.js

angular.module("myApp", []) // 
    .controller('MainController', function($scope) { 
     $scope.toggle = function(section) { 
      console.log('<toggle function> section :' + section); 
      $scope.section = section; 
      $scope.$broadcast('event:toggle'); 
     } 
    }) // 
    .directive('toggle', function() { 
     return function(scope, elem, attrs) { 
      scope.$on('event:toggle', function() { 
       if(attrs.toggle == scope.section){ 
        elem.slideToggle('fast'); 
       } 
      }); 
     }; 
    }); 

Una preoccupazione della mia è il modo in cui sto comunicando tra la direttiva e la portata:

 $scope.section = section; 

e

 if(attrs.toggle == scope.section){ 

Io apprezzo qualche consiglio per un'attuazione migliore angolare .

Grazie

+0

Se si desidera mantenere pulito il controller si potrebbe istituire un servizio che gestisce i vostri contenitori commutate oppure è possibile aggiungere un ID personalizzato ad ogni evento trasmesso come $ trasmissione ('ginocchiera' + qualcosa). –

risposta

12

Plunker Demo:http://plnkr.co/edit/u69puq?p=preview

Cordiali saluti, al momento della scrittura, la squadra AngularJS stanno aggiungendo una direttiva ngAnimate che (si spera) offrire la maggior parte delle funzionalità animato che jQuery attualmente offerte, ad es Diapositiva, Dissolvenza, ecc., Che è gravemente mancante al momento IMO.

HTML

<div data-ng-controller="MainController">  
    <input type="button" value="Toggle First" ng-click="box1=!box1"> 
    <input type="button" value="Toggle Second" ng-click="box2=!box2"> 
    <input type="button" value="Toggle third" ng-click="box3=!box3"> 

    <div class="div1" data-slide-toggle="box1" data-slide-toggle-duration="100" > 
     <p>This is section #1</p> 
    </div> 
    <div class="div2" data-slide-toggle="box2" data-slide-toggle-duration="2000"> 
     <p>This is another section #1</p> 
    </div> 
    <div class="div3" data-slide-toggle="box3"> 
     <p>This is 3 section #1</p> 
    </div> 
</div> 

JS

var myApp = angular.module("myApp", []); 

myApp.controller('MainController', function($scope) { 
    $scope.box1 = $scope.box2 = $scope.box3 = true; 
}); 

myApp.directive('slideToggle', function() { 
    return { 
    restrict: 'A',  
    scope:{ 
     isOpen: "=slideToggle" 
    }, 
    link: function(scope, element, attr) { 
     var slideDuration = parseInt(attr.slideToggleDuration, 10) || 200;  
     scope.$watch('isOpen', function(newVal,oldVal){ 
     if(newVal !== oldVal){ 
      element.stop().slideToggle(slideDuration); 
     } 
     }); 
    } 
    }; 
}); 
+0

Grazie, ma penso che la mia preoccupazione originale resti, si può notare che il parametro per la funzione di commutazione ('prima') indica quale elemento deve essere mostrato o nascosto. Voglio sapere se il modo in cui questo parametro comunica con la direttiva è corretto. – Osy

+0

@Osy: Vedi commenti aggiornati, codice e demo di Plnkr. Dovrebbe essere più in linea con quello che eri inizialmente dopo. – GFoley83

+0

Secondo la documentazione di AngularJs, "L'unico uso appropriato di ngInit è per l'aliasing delle proprietà speciali di ngRepeat": http://docs.angularjs.org/api/ng/directive/ngInit avete qualche soluzione qui? – Charlesthk

4

@GFoley83 Questo mi ha aiutato molto, grazie! Sono un principiante, quindi non sono sicuro se questo è il modo giusto per aggiungere un suggerimento per aiutare, scusa se non lo è. Non sono nemmeno esperto, quindi sono felice che il mio suggerimento venga migliorato.

Avevo bisogno che l'elemento iniziasse nascosto e il ng-init non sembrava fare nulla. Quindi, ho aggiunto una quarta casella con un attributo impostato per iniziare nascosto

Utilizzando il codice @ GFoley83 a condizione di avere un attributo aggiuntivo "start shown" aggiunto al div che verrà attivato.

<input type="button" value="Toggle Fourth" ng-click="box4=!box4"> 
<div class="div1" data-slide-toggle="box4" data-start-shown="false"> 
    <p>This is 4 section and starts hidden</p> 
</div> 

La direttiva è stato aggiornato e ora ha un controllo su questo nuovo attribute.If è passata falsa, ci nascondiamo - altrimenti continuerà come prima e iniziare mostrando la voce.

 
    return { 
     restrict: "A", 
     scope: { 
      isOpen: "=slideToggle" // attribute 
     }, 
     link: function (scope, element, attr) { 
      var slideDuration = parseInt(attr.slideToggleDuration, 10) || 200; 
      if (attr.startShown=="false") { 
       element.hide(); 
      } 
      scope.$watch('isOpen', function (newVal, oldVal) { 
       if (newVal !== oldVal) { 
        element.stop().slideToggle(slideDuration); 
       } 
      }); 
     } 
    }; 

Plunker aggiornamento: http://plnkr.co/edit/WB7UXK?p=preview

+0

Felice di essere di aiuto! Ho rimosso il 'ng-init's, come sottolineato da @Charlesthk, è generalmente una cattiva pratica usarli per inizializzare le variabili (anche se si usa Angular con. Forme web NET, possono essere utili). – GFoley83

0

Dopo aver provato la soluzione di Pietro posso vedere che le direttive di sotto slideToggle non può accesso al campo di applicazione genitore. Questa è la mia soluzione.

evoapp.directive('slideToggle', function() { 
    return { 
     restrict: 'A', 
     scope: false , 
     link: function(scope, element, attr) { 
      var slideDuration = parseInt(attr.slideToggleDuration, 10) || 200; 
      var toggle = attr.toggle ; 

      scope.$watch(toggle, function(newVal,oldVal){ 
       if(newVal !== oldVal){ 
        element.stop().slideToggle(slideDuration); 
       } 
      }); 
     } 
    }; 
});