AngularJS - Dynamic $StateProvider With UI-Router

2019-01-25 01:40发布

问题:

I currently have a good working static version of my question being asked. The issue is that I can't seem to format the JSON properly when trying to use $StateProvider in a loop. I'm not sure exactly what part isn't being formatted properly causing an "undefined is not a function" error. But below is my working static State definition with views and resolved using $ocLazyLoad. This works, really not sure why my JSON version version in a loop does not?

Working Static Version - THIS DEFINITELY WORKS FOR ME

// ABSTRACT APP LAYOUT - VIEW THAT DEFINES ENTIRE LAYOUT STRUCTURE
$stateProvider
    .state('app', {
        abstract: true,
        controller: 'LayoutCtrl',
        templateUrl: 'app/components/core/layout/layout.html'

    });

// VIEWS
// CURRENT LAZY LOADING WAS REFERENCED FROM HERE - https://egghead.io/lessons/angularjs-lazy-loading-modules-with-ui-router-and-oclazyload
$stateProvider
    .state('app.dashboard', {
        views: {
            'feature': {
                templateUrl: 'lazyload/components/core/features/dashboard/dashboard.html',
                controller: "DashboardCtrl as dashboard",
                resolve: {
                    dashboard: function ($ocLazyLoad) {
                        return $ocLazyLoad.load(
                            {
                                name: "dashboard",
                                files: ["lazyload/components/core/features/dashboard/dashboard-controller.js"]
                            }
                        )
                    }
                }
            }
        }
    })
    .state('app.other-feature', {
        views: {
            'feature': {
                templateUrl: 'lazyload/components/core/features/other-feature/other-feature.html',
                controller: "OtherFeatureCtrl as otherFeature",
                resolve: {
                    otherFeature: function ($ocLazyLoad) {
                        return $ocLazyLoad.load(
                            {
                                name: "otherFeature",
                                files: ["lazyload/components/core/features/other-feature/other-feature.js"]
                            }
                        )
                    }
                }

            }
        }
    });

I'd like to be clear, the static version does work, it's the looped version I can't seem to get working. Perhaps I'm not doing some kind of array notation for the function properly or something? Any help is greatly appreciated!

回答1:

I actually got this working and wanted to share the answer and code formatting in case anyone was interested in seeing a working standalone array with a loop that adds an Abstract state and child states with views that use resolves that lazy load controllers and files dynamically before the route is loaded via the $ocLazyLoad module.

I figured the code alone might help someone out there struggle less than I did.

var states = [
    { "name": "app", "abstract": true, "url": "", "templateUrl": "app/components/core/layout/layout.html", "controller": "LayoutCtrl" },
    {
        "name": "app.dashboard",
        "views": {
            "feature": {
                "templateUrl": "lazyload/components/core/features/dashboard/dashboard.html",
                "controller": "DashboardCtrl as dashboard",
                "resolve": {
                    "dashboard": function ($ocLazyLoad) {
                        return $ocLazyLoad.load(
                            {
                                "name": "dashboard",
                                "files": ["lazyload/components/core/features/dashboard/dashboard-controller.js"]
                            }
                        )
                    }
                }
            }
        }
    },
    {
        "name": "app.associations_hospital-surgeon",
        "views": {
            "feature": {
                "templateUrl": "lazyload/components/core/features/other-feature/other-feature.html",
                "controller": "OtherFeatureCtrl as otherFeature",
                "resolve": {
                    "otherFeature": function ($ocLazyLoad) {
                        return $ocLazyLoad.load(
                            {
                                "name": "otherFeature",
                                "files": ["lazyload/components/core/features/other-feature/other-feature.js"]
                            }
                        )
                    }
                }
            }
        }
    }
];

angular.forEach(states, function (state) {
    console.log('state --------------------------------------------------------------------------');
    console.log(state);
    $stateProvider.state(state.name, state);
});

And here I decorate the JSON so it can be loaded from a server, but since functions aren't valid in JSON files this seemed to work for me using custom data properties used to define the function attached when used. This allowed me to load the file externally or from a server and still use the lazyloading via $ocLazyLoad as a function when needed.

var states = [
    { "name": "app", "abstract": true, "url": "", "templateUrl": "app/components/core/layout/layout.html", "controller": "LayoutCtrl" },
    {
        "name": "app.dashboard",
        "views": {
            "feature": {
                "templateUrl": "lazyload/components/core/features/other-feature/other-feature.html",
                "controller": "DashboardCtrl as dashboard",
                "resolve": {},
                "data": {
                    "controllerAlias": "dashboard",
                    "controllerFiles": ["lazyload/components/core/features/other-feature/other-feature.js"]
                }
            }
        }
    },
    {
        "name": "app.associations_hospital-surgeon",
        "views": {
            "feature": {
                "templateUrl": "lazyload/components/core/features/associations/other-feature.html",
                "controller": "OtherFeatureCtrl as otherFeature",
                "resolve": {},
                "data": {
                    "controllerAlias": "otherFeature",
                    "controllerFiles": ["lazyload/components/core/features/other-feature/other-feature.js"]
                }
            }
        }
    }
];

angular.forEach(states, function (state) {
    console.log('state --------------------------------------------------------------------------');
    try{
        console.log(state.views.feature.resolve);
        state.views.feature.resolve[state.views.feature.data.controllerAlias] = function($ocLazyLoad){return $ocLazyLoad.load({"name": state.views.feature.data.controllerAlias,"files": state.views.feature.data.controllerFiles})};
    }catch(e){

    }

    $stateProvider.state(state.name, state);
});