Can't convert dynamic routes from AngularJS 1.2 to 1.6

Issue

In AngularJS 1.2 I have some code to dynamically load routes and controllers, which works just fine. I want to upgrade to AngularJS 1.6 and now my dynamics doesn’t work anymore.

This is my old code to load JS files and recalculate the route (a bit simplified as I have some verifications of validity, but this is the basics):

moduleApp.config(function ($routeProvider, $controllerProvider) {
    moduleApp.controllerProvider = $controllerProvider.register;
    moduleApp.routeProvider = $routeProvider;

    $routeProvider.when('/', {
        templateUrl: 'startpage.html',
        controller: 'startpageController'
    })
    .otherwise({
        resolve: {
            deps: function($q, $rootScope, $location) {
                var deferred = $q.defer();

                var modulename = $location.path().split("/")[1];

                if (modulename !== null) {
                    // Load the JS using https://github.com/ded/script.js (Old but it works :)
                    $script(modulename + ".js", function() {
                        $rootScope.$apply(function() {
                            $rootScope.$broadcast('$locationChangeSuccess', $location.path(), $location.path());
                        });
                    });
                }

                return deferred.promise;
            }
        }
    });
});

And the JS file being loaded looks like this:

moduleApp.routeProvider.
    when('/FirstModule', {
        templateUrl: 'FirstModule.html',
        caseInsensitiveMatch: true
    });

moduleApp.controllerProvider('firstModuleController', function ($scope) {
});

Again, this works fine in 1.2, but I believe applying the route in 1.6 doesn’t work this way any more. So what do I need to change inside the function where I use $rootScope to get this to work again? Or do I also need to change more? In case, what?

I’ve made a Plunker with this code.

Change AngularJS version to 1.2.16 in index.html to see that it works in 1.2 (remember to also change the hashbang in the links to be only #instead of #!). Change it back to 1.6 and it doesn’t work any more.

Solution

This line is a little odd. It was putting you into an infinite loop.

$rootScope.$broadcast('$locationChangeSuccess', $location.path(), $location.path());

Instead of trying to trick Angular into reloading, just call $route.reload()

.otherwise({
    resolve: {
        deps: function($q, $rootScope, $location, $http, $route) {
            var deferred = $q.defer();

            var modulename = $location.path().split("/")[1];

            if (modulename !== null) {
                $script(modulename + ".js", function() {
                    $rootScope.$apply(function() {
                        //$rootScope.$broadcast('$locationChangeSuccess', $location.path(), $location.path());
                        $route.reload();
                    });
                });
            }

            return deferred.promise;
        }
    }
});

Here is the working Plunker

Also, there was a minor bug. Missing parenthesis in ng-click="FirstButton"

 

Edit in response to comment:

Broadcasting system events ($locationChangeSuccess) as you were just sounds risky. To some extent you got lucky that it worked in 1.2, as it was never really supported. Certainly the location change was not a success, as your code claims.

The docs for reload just say:

Causes $route service to reload the current route even if $location hasn’t changed.
As a result of that, ngView creates new scope and reinstantiates the controller.

So this should work in every supported version. I don’t anticipate any negative side effects. It is simply the standard way of doing what you tried to homebrew.

Answered By – Buh Buh

Answer Checked By – Mary Flores (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.