Angular 指令和 Jquery slideToggle 函数的实现

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15444244/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 15:03:28  来源:igfitidea点击:

Angular directive and Jquery slideToggle function implementation

jqueryangularjsslideslidetoggleangularjs-directive

提问by Osy

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:

使用 angular 和 jquery 我实现了 slideToggle 功能。为了仅将此函数应用于一个特定的 HTML 元素,我在 ng-click 函数中使用了一个参数,我的代码运行良好,但是,我想知道是否存在另一种更好的方法来实现指令和 ng-click 函数的角度:

index.html

索引.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

指令.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.

对于更好的 Angular 实现,我将不胜感激。

Thanks

谢谢

回答by GFoley83

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

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

FYI, at the time of writing, the AngularJS team are adding an ngAnimatedirective 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.

仅供参考,在撰写本文时,AngularJS 团队正在添加一个ngAnimate指令,该指令将(希望)提供 jQuery 当前提供的大部分动画功能,例如 Slide、Fade 等,目前 IMO 非常缺少这些功能。

HTML

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

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

回答by Peter

@GFoley83This 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.

@GFoley83这对我帮助很大,谢谢!我是新手,所以不确定这是否是添加建议以提供帮助的正确方法,如果不是,抱歉。我也不是专家,所以我很高兴我的建议得到改进。

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

我需要该项目开始隐藏,而 ng-init 似乎没有做任何事情。因此,我添加了第四个框,其属性设置为隐藏

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

使用代码@GFoley83,前提是我将一个附加属性“开始显示”添加到将被切换的 div 中。

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

该指令也已更新,现在对这个新属性进行检查。如果传递 false,我们将隐藏 - 否则它将像以前一样继续并从显示项目开始。

     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

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

回答by evoratec

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

在尝试了 Peter 的解决方案后,我可以看到 slideToggle 下面的指令无法访问父作用域。这是我的解决方案。

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