HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Angular directive to toggle sidebar visibility based on window width

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
directivesidebarangularvisibilitywidthbasedwindowtoggle

Problem

I changed the normal way of using Angular. I'm using my controllers just to talk to my API routes and am using directives to manipulate the data and DOM as well.

I am using the object literal pattern where I have my INIT method that initializes global variables (object) and then calls other methods, bind clicks methods, etc. So, the logic is all the directives.

I'm finding it very confusing and would like the opinion of someone better.

```
'use strict';
var eventSidebarDirective = {

/**
* Initialize sidebar directive and return the link
* calling all nested methods.
*
*/
init: function() {
return {
link: function(scope) {
scope.$watch('events', function() {
if (scope.events === undefined) {
return;
}

/**
* Every time the user access the event page, this methods
* will be called.
*
*/
EventSidebar.init();
});
},
restrict: 'M'
};
}
};

var EventSidebar = {
init: function() {
this.element = $('[data-event-sidebar]');
this.indicator = $('[data-event-sidebar-to]');

/**
* To manipulate the element, bind a click in the indicator.
*
*/
this.indicator.bind('click', this._toggle.bind(this));
},

_toggle: function(e) {
var state = $(e.currentTarget).data('event-sidebar-to');

this.element
.css({

/**
* If the window width is less than 768px, i just want toggle
* between display block and none.
*
*/
display: 768 >= $(window).width()
? (state
? 'block'
: 'none')
: false

Solution

Yes, you're right. Your code is very hard to read.

  • I think you don't need that init stuff. Just remove it and add initialization to the controller.



  • You don't need jQuery for your directive. This is possible with Angular JS / pure Js. Use ng-show or ng-if for showing hiding your sidebar and use ng-class to add your class conditionally depending on a variable from your controller to do things differently for large screens.



  • Animation could be done with ngAnimate and animate.css.



There are some points that could be improved in my code:

  • Add options so it's better reusable.



  • Add default options for example start visible = false. with angular.module('adminApp').constants(...) then you can angular.extend(...) these in the controller of your directive.



  • Add an isolated scope for the directive so it can't modify the scope of your app. Somthing like scope: {} would be OK or {scope: { options: '@' } } for the sidebar options.



  • Remove restrict: M because it's not recommended to use directives as comments (see angular docs).



Please have a look at the demo below or in this jsfiddle.



function EventSidebarDirective($window) {
var directive = {
restrict: 'EAM',
templateUrl: 'components/sidebar/template.html',
controllerAs: 'ctrl',
controller: function ($scope) {
var self = this, // self needed because toggle is not bound to this ctrl.
screenWidth;

angular.extend(this, {
visible: false,
toggle: function () {
screenWidth = $window.innerWidth; //$(window).width();
self.visible = !self.visible; // toggle visibility
self.largeScreen = ( screenWidth >= 768 );
}
});
},
link: function (scope, element, attr, ctrl) {

}
};

return directive;
}

EventSidebarDirective.$inject = ['$window']; // only need with-out ng-annotate for minification

angular.module('adminApp', ['ngAnimate'])
.directive('eventSidebar', EventSidebarDirective);

.sidebar-content {
width: 200px;
height: 200px;
background: lightgray;
}

.sidebar-content-animation.ng-hide-remove {
-webkit-animation: fadeInLeft 1s;
-moz-animation: fadeInLeft 1s;
-ms-animation: fadeInLeft 1s;
-o-animation: fadeInLeft 1s;
animation: fadeInLeft 1s;
}

.sidebar-content-animation.ng-hide-add {
-webkit-animation: fadeOutUp 1s;
-moz-animation: fadeOutUp 1s;
-ms-animation: fadeOutUp 1s;
-o-animation: fadeOutUp 1s;
animation: fadeOutUp 1s;
}





I'm a sidebar

toggle sidebar


Context

StackExchange Code Review Q#101423, answer score: 3

Revisions (0)

No revisions yet.