Directiva angular y implementación de la función Jquery slideToggle
angularjs angularjs-directive (3)
Usando angular y jquery implementé la función slideToggle. Para aplicar solo esta función a un elemento HTML específico, estoy usando la función ng-clic en un parámetro, mi código funciona bien, pero quiero saber si existe otra forma mejor de implementar directivas y funciones ng-click en 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'');
}
});
};
});
Una de mis preocupaciones es la forma en que me comunico entre directiva y alcance:
$scope.section = section;
y
if(attrs.toggle == scope.section){
Apreciaré cualquier consejo para una mejor implementación angular.
Gracias
Después de probar la solución de Peter, puedo ver que las directivas debajo de slideToggle no pueden acceder al alcance principal. Esta es mi solución.
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);
}
});
}
};
});
@ GFoley83 ¡ Esto me ayudó mucho gracias! Soy un novato, así que no estoy seguro si esta es la manera correcta de agregar una sugerencia para ayudar, lo siento si no es así. Tampoco soy un experto, por lo que estoy contento de que mi sugerencia sea mejorada.
Necesitaba el elemento para comenzar a ocultarse y el ng-init no parecía hacer nada. Entonces, agregué un cuarto cuadro con un conjunto de atributos para comenzar oculto
Usando el código @ GFoley83 siempre que tenga un atributo adicional "start shown" agregado al div que será cambiado.
<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>
La directiva también se ha actualizado y ahora tiene un control sobre este nuevo atributo. Si se pasa falso, lo ocultaremos; de lo contrario, continuará como antes y comenzará mostrando el elemento.
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 actualizado: http://plnkr.co/edit/WB7UXK?p=preview
Demostración de Plunker: http://plnkr.co/edit/u69puq?p=preview
Para su información, en el momento de redactar este informe , el equipo de AngularJS está agregando una directiva ngAnimate que (con suerte) ofrecerá la mayor parte de la funcionalidad animada que jQuery ofrece actualmente, por ejemplo, Slide, Fade, etc., que en este momento falta por completo en la 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);
}
});
}
};
});