Angular and jQuery slideToggle function implementation

Using angular and jquery, I applied the slideToggle function. To apply this function to only one specific HTML element, I use a single parameter function inside ng-click, my code works fine, but I want to know if there is another better way to implement ng-click directives and functions in angular:

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'); } }); }; }); 

One of my problems is how I communicate between the directive and the scope:

  $scope.section = section; 

and

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

I will be grateful for any recommendations for a better implementation of angular.

thanks

+6
source share
3 answers

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

FYI, at the time of writing, the AngularJS team is adding the ngAnimate directive, which (hopefully) will offer most of the animation functionality that jQuery currently offers. Slide, Fade, etc., which is currently very absent in 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); } }); } }; }); 
+12
source

@ GFoley83 It really helped me! I'm a newbie, so I'm not sure if this is the right way to add an offer to help, sorry if this is not the case. I am also not an expert, so I am happy that my proposal will be improved.

I need the element to start hiding and ng-init to do nothing. So, I added a fourth block with the attribute set to trigger hidden

Using @ GFoley83 code, provided that I have an additional attribute "start show" added to the div to be switched.

  <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> 

The directive has also been updated and now validates this new attribute. If it passed falsely, we will hide - otherwise it will continue as before and will begin by displaying the element.

  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);
                 }
             });
         }
     };

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

+4
source

After trying Peter's solution, I see that the directives below slideToggle cannot access the parent scope. This is my decision.

 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); } }); } }; }); 
0
source

All Articles