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