1

I'm trying to load states dynamically from a JSON file using ui-router-extras. The JSON file looks like the following:

    [
  {
    "name": "app",
    "url": "/app",
    "abstract": "true",
    "resolve": "helper.resolveFor('fastclick', 'modernizr', 'icons')"
    
  },
  {
    "name": "login",
    "url": "/login",
    "title": "User Login",
    "templateUrl": "",
    "redirectToLogin": "true"
  },
  {
    "name": "dashboard",
    "url": "/dashboard",
    "title": "Dashboard",
    "templateUrl": "helper.basepath('dashboard.html')",
    "resolve": "helper.resolveFor('flot-chart', 'flot-chart-plugins', 'weather-icons')"
   
  }
]

The following is the routes config file:

(function () {
'use strict';

angular
    .module('app.routes')
    .config(routesConfig);

routesConfig.$inject = ['$stateProvider', '$locationProvider', '$urlRouterProvider', 'RouteHelpersProvider', '$stateProvider', '$futureStateProvider'];
function routesConfig($stateProvider, $locationProvider, $urlRouterProvider, helper, $sp, $fsp) {

    $locationProvider.html5Mode(false);

    var futureStateResolve = function($http) { 
        return $http.get("states.json").then(function (response) {
            console.log(response.data);
            angular.forEach(response.data, function (state) {

                $sp.state(state);
                })
            })
        }
    $fsp.addResolve(futureStateResolve);

         // defaults to dashboard
    $urlRouterProvider.otherwise('/app/login');
    }
})();

The /login state works ok, but the others don't work and give the error 'invocables must be object'. I think this is because helper.basepath() and helper.resolveFor() functions are not working, as they are coming as strings from the JSON.

What should I do?

4
  • as for the function pass it as 2 properties...function name and arguments Commented Jan 24, 2016 at 1:33
  • my bad...just need array of args for resolve {"resolve": "['flot-chart', 'flot-chart-plugins', 'weather-icons']...} ... then pass array and use apply() .... helper.resolveFor.apply(null, obj.resolve) Commented Jan 24, 2016 at 2:40
  • But since I'm reading from json, where should be the change? As not all the states have resolve property. Commented Jan 24, 2016 at 6:39
  • well you will need some conditionals. What is the reason for doing all this? Commented Jan 24, 2016 at 12:01

1 Answer 1

1

My advice is the same as @charlietfli. I will elaborate.

Since you have already created a helper function that returns your resolve block, you can easily work around the fact that JSON doesn't support JS code or expressions.

Your helper function takes a list of strings as arguments. JSON supports arrays of strings. Change your JSON from this: "resolve": "helper.resolveFor('fastclick', 'modernizr', 'icons')" to this: "resolve": ["fastclick", "modernizr", "icons"]. Now, the JSON resolve contains a simple array of strings.

When you load the states, first convert the array to a resolve block using your helper, and then register them.

var futureStateResolve = function($http) { 
    return $http.get("states.json").then(function (response) {
        angular.forEach(response.data, function (state) {
            // The array of strings from the JSON
            var stringArgs = state.resolve;
            // If present, convert to a resolve: object and put back on the state definition
            if (stringArgs) state.resolve = helper.resolveFor.apply(helper, stringArgs);
            $sp.state(state);
        })
    })
}
$fsp.addResolve(futureStateResolve);

That should answer your question.

However, I noticed you are using future states from ui-router-extras, but you are not lazy loading the code (controllers or whole javascript angular modules) itself. Normally, you register future states with the $futureStateProvider, and not directly with the $stateProvider. There's nothing wrong with what you are doing (lazy loading the state definitions and taking advantage of deferred ui-router bootstrap from Future States). However, you could achieve the same thing without depending on the ui-router-extras library.

This is how you would lazily add state definitions without ui-router-extras:

Angular - UI Router - programmatically add states

This is how you can defer ui-router from parsing the url until you are done adding state definitions:

Angular ui-router and ocLazyLoad

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.