【问题标题】:Angular directive and Jquery slideToggle function implementationAngular 指令和 Jquery slideToggle 函数实现
【发布时间】:2013-03-04 20:47:32
【问题描述】:

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

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

我自己关心的一个问题是我在指令和范围之间进行通信的方式:

        $scope.section = section;

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

我将不胜感激任何关于更好的 Angular 实现的建议。

谢谢

【问题讨论】:

  • 如果你想让你的控制器保持干净,你可以设置一个服务来处理你的切换容器,或者你可以为每个广播事件添加一个自定义 id,比如 $broadcast('toggle'+something)。

标签: jquery angularjs slide slidetoggle angularjs-directive


【解决方案1】:

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

仅供参考,在撰写本文时,AngularJS 团队正在添加一个 ngAnimate 指令,它将(希望)提供 jQuery 当前提供的大部分动画功能,例如Slide、Fade 等,目前 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);
        }
      });
    }
  };  
});

【讨论】:

  • 谢谢,但我认为我最初的担忧仍然存在,您可以注意到函数 toggle('first') 的参数指示必须显示或隐藏哪个元素。我想知道这个参数与指令通信的方式是否正确。
  • @Osy:查看更新的 cmets、代码和 Plnkr 演示。应该更符合您最初的需求。
  • 根据 AngularJs 的文档,“ngInit 的唯一适当用途是为 ngRepeat 的特殊属性起别名”:docs.angularjs.org/api/ng/directive/ngInit 你有什么解决方法吗?
  • @GFoley83 我发现您的代码有助于让我的表单切换,但不太了解其中发生了什么。具体为什么它被称为 data-slide-toggle 但命名为 slideToggle。我是 angJS 的新手,但还没有看到 2 之间的语法。另外,我不理解指令中的大部分语法,想知道你是否可以向我发送你的代码块的 cmets?我完全理解的唯一行是控制器和 element.stop() 行中的内容。抱歉......我已经找了好几天了,我只是想了解这如何给了我想要的行为。
  • @clanier9 这只是一个 Angular 约定。指令使用驼峰式大小写声明,例如thisIsMyDirective。当您将指令添加到您的 html 时,您必须使用蛇形大小写,因此如果我们坚持使用 thisIsMyDirective,则可以将其添加到元素中,如 this-is-my-directivedata-this-is-my-directivex-this-is-my-directive 等。基本上无论您有大写字母在你的指令 js 中,它变成一个破折号,后跟你的 html 中的小写字母。
【解决方案2】:

在尝试了 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);
                }
            });
        }
    };
});

【讨论】:

    【解决方案3】:

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

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

    使用代码@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>
    

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

    返回 { 限制:“A”, 范围: { isOpen: "=slideToggle" // 属性 }, 链接:功能(范围,元素,属性){ var slideDuration = parseInt(attr.slideToggleDuration, 10) || 200; if (attr.startShown=="false") { 元素.hide(); } scope.$watch('isOpen', function (newVal, oldVal) { if (newVal !== oldVal) { element.stop().slideToggle(slideDuration); } }); } };

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

    【讨论】:

    • 很高兴能帮上忙!我删除了ng-inits;正如@Charlesthk 指出的那样,使用它们来初始化变量通常是不好的做法(尽管在将 Angular 与 .NET Web 表单一起使用时,它们会很方便)。
    猜你喜欢
    • 2014-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-06
    • 1970-01-01
    相关资源
    最近更新 更多