Search code examples
angularjsangular-routingdynamic-routing

AngularJS Dynamically Load Controller and Template based on Route


I am trying to dynamically load BOTH a template and controller based on the route (in Angular 1.6), pulling from the current directory architecture.

    app
    |__login.module.js
    |__home.controller.js
    |__login.factory.js
    |__home.view.html
    |__404.view.html
    |__index.html

Currently, the below code works to pull the proper template, but the controller won't load:

    angular.module('common.auto-loading-routes', []).config(function($routeProvider){

    function getTemplate(routeParams){
        var route = (routeParams.current) ? routeParams.current.params.route : routeParams.route;
        var directory = route.split('/');
        directory = directory.filter(function(entry) { return entry.trim() != ''; });
        var page = directory[directory.length - 1];
        directory.splice(-1,1);
        directory = directory.join('/');
        return directory + '/' + page +'.view.html';
    }

    function getController(routeParams){
        //I think I need a promise here, but I don't know how to write it
        routeParams = routeParams.route.split('/').join('.');
        return routeParams + 'controller';
    }

    $routeProvider.when('/:route*', {
        controller: function($routeParams) { //does not work
            return getController($routeParams);
        },
        templateUrl: function($routeParams) { //works
            return getTemplate($routeParams);
        },
        resolve: {
            check: function($route, $http, $location){
                return $http.get(getTemplate($route)).then(function(response){
                    if (response.status !== 404){
                        return true;
                    } else {
                        $location.path('404');
                    }
                });
            }
        }
    }).otherwise('/404');
});

I understand that controllers need to be present at the start of the app, but I am unable to write a proper resolve with a promise statement.

Can someone help me right a resolve with a simple promise that returns a string of the controller name based on the route?


Solution

  • I was able to get it working by not including the controller in the routing at all. Instead I put the ng-controller attribute in the view I was loading.

    This worked!

    angular.module('common.auto-loading-routes', []).config(function($routeProvider){
    
        function getTemplate(routeParams){
            var route = (routeParams.current) ? routeParams.current.params.route : routeParams.route;
            var directory = route.split('/');
            directory = directory.filter(function(entry) { return entry.trim() != ''; });
            var page = directory[directory.length - 1];
            directory.splice(-1,1);
            directory = directory.join('/');
            return directory + '/' + page +'.view.html';
        }
    
        $routeProvider.when('/:route*', {
            templateUrl: function($routeParams) { //works
                return getTemplate($routeParams);
            },
            resolve: {
                check: function($route, $http, $location){
                    return $http.get(getTemplate($route)).then(function(response){
                        if (response.status !== 404){
                            return true;
                        } else {
                            $location.path('404');
                        }
                    });
                }
            }
        }).otherwise('/404');
    });
    

    In the HTML of that view, I just put

    ng-controller="home.controller"
    (or whatever controller is appropriate)