7

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

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

样式.css

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

指令.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 实现,我将不胜感激。

谢谢

4

3 回答 3

14

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);
        }
      });
    }
  };  
});
于 2013-03-17T18:48:48.517 回答
4

@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

于 2013-08-26T10:49:13.220 回答
0

在尝试了 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);
                }
            });
        }
    };
});
于 2013-10-10T15:37:15.917 回答