Angular directive and Jquery slideToggle function implementation

試著忘記壹切 提交于 2019-12-09 05:52:50

问题


Using angular and jquery I implemented slideToggle function. In order to only apply this function to one specific HTML element, I am using within ng-click function one parameter, my code works fine but, I want to know if exists another better way to implement directives and ng-click 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 concern of my own is the way that I am communicating between directive and scope:

        $scope.section = section;

and

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

I will appreciate any advice for a better Angular implementation.

Thanks


回答1:


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

FYI, at the time of writing, the AngularJS team are adding an ngAnimate directive which will (hopefully) offer most of the animate functionality that jQuery currently offers, e.g. Slide, Fade etc, which is sorely missing at the moment 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);
        }
      });
    }
  };  
});



回答2:


@GFoley83 This helped me out a lot thanks! I'm a newbie, so not sure if this is the right way to add a suggestion to help, sorry if it's not. I'm also no expert, so i'm happy for my suggestion to be improved.

I needed the item to start hidden and the ng-init didn't seem to do anything. So, I've added a fourth box with an attribute set to start hidden

Using the code @GFoley83 provided I have an additional attribute "start shown" added to the div which will be toggled.

 <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 has a check on this new attribute.If it's passed false, we'll hide - otherwise it will continue as before and start by showing the item.

     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 updated : http://plnkr.co/edit/WB7UXK?p=preview




回答3:


After trying the solution of Peter i can see that directives below slideToggle cannot acces to parent scope. This is my solution.

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


来源:https://stackoverflow.com/questions/15444244/angular-directive-and-jquery-slidetoggle-function-implementation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!