3
\$\begingroup\$

Here is my plunker example of what I am doing.

jQuery is a great way to use slide transitions and seem to work well with angular as long as you are only using the methods on the element object inside a directive.

Basically I am using a directive for divs I want to slide toggle which listens for a broadcast from the controller which happens when the click function is called in the controller.

I am not using jQuery selectors and am only calling slideToggle() on the angular element.

Is this an acceptable angular way of doing this? If not, what is?

HTML

<html ng-app="myApp">
<head>
    <title></title>
    <link type="text/css" rel="stylesheet" href="style.css"/>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
    <script src="script.js"></script>
</head>

  <div ng-controller="mainCtrl">
    <div class="login-div">
        <div class="login toggle">
            <input type="text" placeholder="username" />
            <input type="password" placeholder="password" />
            <button class="btn-login">Login</button>
            <div class="link">
                <p ng-click="toggleClick()">Click here</p>
            </div>
        </div>
        <div class="sign-up toggle">
            <input type="text" placeholder="username" />
            <input type="email" placeholder="email" />
            <input type="password" placeholder="password" />
            <button class="btn-login">Sign up</button>
            <div class="link">
                <p ng-click="toggleClick()">Click here again</p>
            </div>
        </div>
        <div class="btn-close">
            <button>X</button>
        </div>
    </div>
  </div>
</html>

JavaScript

var myApp = angular.module("myApp", []);

myApp.controller('mainCtrl', function($scope, $rootScope) {
  $scope.toggleClick = function(){
    $rootScope.$broadcast("toogleDiv","");
  };
});

myApp.directive('toggle', function () {
    return {
        restrict:'C',
        link: function (scope, element, attrs) {
            scope.$on("toogleDiv", function(e, val){
              element.slideToggle();
            });
        }                  
    }
});
\$\endgroup\$
2
\$\begingroup\$

Since you are loading jQuery before Angular, your Angular element will have all properties provided by jQuery, so this is perfect way to use jQuery on top of Angular. This is also how you would wrap a jQuery plugin inside an Angular directive, but see also the jQuery Passthrough directive that does exactly that.

What would be a bad use of jQuery is using jQuery selector (as you mention) to refer to a DOM element. That would break the encapsulation provided by directive, since the inside of the directive should not know anything about the DOM structure, beyong what is provided by Angulars API.

However, your event listener "toogleDiv" inside the directive does break this encapsulation! The event is not provided by the directive's API! (Which also makes your directive less re-usable.) Instead it is sent via another channel that is not visible from your template:

<div class="login toggle">

There is no way I see here that this directive listens to an event and no clue what the event is. A better design would be:

<div class="login" toggle-on="'toogleDivEvent'">

Now I can easily see all the ingredients used by the directive. Even if I don't know anything about your code, I see that this directive has an API accepting a string, and 'Event' in the name hints that this string represents an event. What more, now it is re-usable - you can put it anywhere to listen to any event.

Also note that putting it as attribute instead of class is better for readability - now you can easily tell it is directive and not a class used for styling. (It is unfortunately still used by Angular UI but they realised this way is bad and promised to remove it.)

BTW, you provided a long CSS file in this question about Angular/jQuery, I could not see any reason for that. If JavaScript is the focus of your question, you would help your reader by completely removing all styling classes.

\$\endgroup\$
2
\$\begingroup\$

I see no reason not to use JQuery animations. If you want to have your app pure angular, use angular animations.

The main issue usually being nagged about is view (dom) manipulation code in the controller, so the directive is the way to go, for sure.

The event broadcast is overkill though, just put the onclick in the directive too :) unless you are planning to put the link outside of <div class="toggle"....

\$\endgroup\$
  • \$\begingroup\$ Thank you for your answer and feedback. New plunker I put the click function in the directive but it did not yield the results I expected. The reason for the broadcast is so it triggers the animation on both of the directive divs. \$\endgroup\$ – Mandrake Aug 11 '14 at 22:47
  • \$\begingroup\$ @Lexxx didn't have the reputation to comment so I'm writing this comment for him: "so of course the event is not overkill in this case. I didn't get the consept fully, just by looking at the code. Now this being the case, I think one more improvement is needed, if you are planning to reuse the directive: take in a parameter to pass for the directive . updated the plunk ps. sorry to answer editing the answer, i dont have rep to comment, and wasn't sure about the protocol. and too busy (like also yesterday), since i'm working here :)" \$\endgroup\$ – Pimgd Aug 12 '14 at 8:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.