0

The stated aim is fairly straight forward and easy to do in static pages with JQuery. On the document ready event, you'd have something like

$('.fadeIn').fadeIn();

Which would give you a nice, clean way of applying an animation effect to any elements that required it on your UI.

Enter angular and my first experience with it (very n00b here). I would like to apply the concept above but trigger it once angular has figured out and done all it's necessary rendering. I need this on most views but only on elements that I want to animate.

Researching this, it seems that the angular way of doing this is via a directive which lead me to this post on how to hook into angular at various points in the life cycle.

My angular setup is pretty basic;

HTML

<div ng-app="profile" class="fadeIn">
    Some content
</div>

Controller

(function (app) {
    var controller = function () {
    };
    app.controller("menuController", [controller]);
})(angular.module("dashboard"));

app.js

(function (appName) {

    var app = angular.module(appName, ["ngRoute", "ui.bootstrap"]);

    app.config(['$locationProvider', function ($locationProvider) {
        $locationProvider.hashPrefix("");
    }]);

    var routeConfig = function ($routeProvider) {
        $routeProvider.when("/",
                {
                    templateUrl: "app/menu/menu.html",
                    controller: "menuController"
                });

        $routeProvider.otherwise({ redirectTo: "/" });
    }

    app.config(routeConfig);
    console.log("app started");
}("dashboard"));

With that setup in mind, my approach to apply my original concept and hook into angular's directives is as follows;

myAnimate.js

angular.module("profile", []).directive('directive',
    function($timeout) {
        return {
            restrict: 'A',
            link: function(scope, element, attr) {
                $timeout(function() {
                    SetupAnimations();
                });
            }
        }
    });

function SetupAnimations() {
    $(".fadeIn").fadeIn();
}

When I put a breakpoint on the return statement, it's never hit. However, the angular.module() call is hit and runs without error.

I know I can hook into the controller's initialization using $rootScope but this means that I have to initialize for every controller. I'd like to be able to apply it globally across the application.

I'm pretty sure I'm either missing something very simple or have approached this from the wrong angle entirely.

DiskJunky
  • 4,750
  • 3
  • 37
  • 66
  • You haven't included your `profile` module as dependency in the main app module – charlietfl Nov 07 '17 at 12:43
  • @charlietfl how do I go about doing that? – DiskJunky Nov 07 '17 at 12:44
  • Same way you injected `ngRoute` – charlietfl Nov 07 '17 at 12:44
  • @charlietfl so change the `module` config to `angular.module(appName, ["ngRoute", "ui.bootstrap", "profile"])`? I just tried that and no effect. – DiskJunky Nov 07 '17 at 12:48
  • OK now the directive is looking for an element `` that doesn't exist. The `restrict:'E'` refers to element based on name of the directive – charlietfl Nov 07 '17 at 12:52
  • @charlietfl, it actually doesn't even get that far. A breakpoint on the `return` is never hit so the restrictions aren't applied. Good to know though, as I don't want it to restrict to element names but classes in which I should change that to `A` if my understanding of the documentation is correct – DiskJunky Nov 07 '17 at 12:56
  • Right ... if the registered directive is not found in the view the link will never fire because there is no reason to – charlietfl Nov 07 '17 at 12:59
  • @charlietfl so this implies adding `ng-app` to the root `div` in the view should be enough to it to connect the two. However, applying this too doesn't trigger the directive setup – DiskJunky Nov 07 '17 at 13:44
  • It means that the name and restrict type of directive needs to be found in view – charlietfl Nov 07 '17 at 13:58
  • @charlietfl I got this working. Issue had to do with an app name not being defined in angular which made attaching the directive effectively impossible. Moving the directive and animation setup into the `app.js` resolved the issue. – DiskJunky Nov 07 '17 at 14:10

1 Answers1

0

After a bit of tinkering and help from charlietfl, I managed to get to the source of the issue. There were a few misconfigurations there that resulted in the behaviour described.

The primary one was that appName was undefined and it not being used in any of the angular markup that was in the app (I'm working on legacy code) and this made hooking a directive in tricky. Knowing that, I moved the code for myAnimation.js into the app.js like so;

(function (appName) {
    // appName here results in "undefined" error message but angular hooks in all the same
    var app = angular.module(appName, ["ngRoute", "ui.bootstrap"]);
    app.config(['$locationProvider', function ($locationProvider) {
        $locationProvider.hashPrefix("");
    }]);

    // the moved in directive here where it can attach to the app correctly
    app.directive('animate',
        function () {
            return {
                restrict: 'A',
                link: function (scope, element, attr) {
                    SetupAnimations();
                }
            }
        });

    //...remainder of logic in here unchanged
}("dashboard"));

function SetupAnimations() {
    $(".fadeIn").fadeIn();
}

My HTML now looks like;

<div animate class="fadeIn"></div>

And the animation works just fine.

EDIT

I've refined further as per the angular documentation on directives such that my directive setup hooks into how the directives work rather than leveraging jQuery for the animation hookup. The SetupAnimations() method is removed and the directive reduced to the following;

app.directive('fadeIn',
    function () {
        return {
            restrict: 'A',
            link: function(scope, element) {
                element.fadeIn();
            }
        }
    });

Which leaves my HTML markup like (note the hyphen - read the documentation linked to above);

<div fade-In></div>
DiskJunky
  • 4,750
  • 3
  • 37
  • 66
  • 1
    Also note that `element` is a jQuery object when jQuery.js is in page before angular.js. So `element.fadeIn()` is same as `$(element).fadeIn()` – charlietfl Nov 07 '17 at 16:50
  • @charlietfl, that's good to know. I was taking an "assume nothing" approach but I'll clean that up – DiskJunky Nov 07 '17 at 19:24