9

I am trying to add states to my app dynamically and tried using ui-router. I tried following this thread. AngularJS - UI-router - How to configure dynamic views

In my case, there are some existant states already and i need to append to that list with the dynamic states being read from json

For some reason, i get injector error on $urlRouterProvider when trying to use for deferIntercept() method. In my case, i am using angular 1.3 and the ui-router version is 0.2.10. I see that you can create states synamically. But can we add to the existing list of states already configured statically

Here is my code any help is appreciated,

MY modules.json,

 [{
   "name": "applications1",
    "url": "^/templates/applications1",
    "parent": "authenticated",
    "abstract": false,
     "views": [{
     "name": "",
     "templateUrl": "html/templates/basicLayout.html"
   }, {
      "name": "header@applications1",
      "templateUrl": "html/templates/header.html"
  }],
   {
   "name": "login",
   "url": "/login",
   "abstract": false,
   "views": [{
     "name": "",
     "templateUrl": "html/admin/loginForm.html"
   }]
 }]

My app.js

       var $stateProviderRef = null;
       var $urlRouterProviderRef = null;

       var aModule = angular.module('App', [
             'ui.bootstrap','ui.router'   
       ]);


         adminModule.run(['$rootScope', '$state', '$stateParams',
              function ($rootScope, $state, $stateParams) {
              $rootScope.$state = $state;
          $rootScope.$stateParams = $stateParams;
         }])

         adminModule.run(['$q', '$rootScope','$http', '$urlRouter',
            function ($q, $rootScope, $http, $urlRouter) 
            {
      $http
          .get("modules.json")
          .success(function(data)
       {
           angular.forEach(data, function (value, key) 
       { 
        var state = {
        "url": value.url,
        "parent" : value.parent,
        "abstract": value.abstract,
        "views": {}
      };

      angular.forEach(value.views, function (view) 
      {
        state.views[view.name] = {
          templateUrl : view.templateUrl,
        };
      });

      $stateProviderRef.state(value.name, state);
    });
    // Configures $urlRouter's listener *after* your custom listener

    $urlRouter.sync();
    $urlRouter.listen();
  });
}]);

    aModule.config(['$locationProvider', '$stateProvider',        '$urlRouterProvider', '$httpProvider', function ($locationProvider, $stateProvider, $urlRouterProvider, $httpProvider) {

    // XSRF token naming
    $httpProvider.defaults.xsrfHeaderName = 'x-dt-csrf-header';
    $httpProvider.defaults.xsrfCookieName = 'X-CSRF-TOKEN';

$httpProvider.interceptors.push('httpInterceptor');

$stateProvider
    .state('login', {
        url: '/login',
        templateUrl: 'html/XXX/loginForm.html',
        controller: 'AController'
    })
    .state('sAgree', {
        url: '/serviceAgreement',
        templateUrl: 'html/xxx/s.html',
        controller: 'SController'
    });
   $urlRouterProvider.deferIntercept();

$urlRouterProvider.otherwise('/login');

$locationProvider.html5Mode({enabled: false});
$stateProviderRef = $stateProvider;
$urlRouterProviderRef = $urlRouterProvider;

}]);
Zaheer Ahmed
  • 28,160
  • 11
  • 74
  • 110
looneytunes
  • 741
  • 4
  • 16
  • 35
  • At what point during the application run process are you trying to create or push in a new state? if it's post run function ... I'm not sure that's possible not without extending the $state object with a set method of your own. I'm pretty sure you can only create a new state via the stateProvider inside the config function. – btm1 Apr 02 '15 at 22:16
  • i am adding teh states in config and then attaching the states to state provider in the run function itself – looneytunes Apr 03 '15 at 04:40

1 Answers1

11

There is a working plunker, with all the above snippets.

In case that we want add some states, which are not already existing, we should check the $state.get('stateName')

$http
  .get("modules.json")
  .success(function(data) {
    angular.forEach(data, function(value, key) {

      // here we ask if there is a state with the same name
      var getExistingState = $state.get(value.name)

      // no need to continue, there is state (e.g. login) already
      if(getExistingState !== null){
        return; 
      }

      var state = {
        "url": value.url,
        "parent": value.parent,
        "abstract": value.abstract,
        "views": {}
      };

      angular.forEach(value.views, function(view) {
        state.views[view.name] = {
          templateUrl: view.templateUrl,
        };
      });

      $stateProviderRef.state(value.name, state);
    });
    // Configures $urlRouter's listener *after* your custom listener

    $urlRouter.sync();
    $urlRouter.listen();

  });

Check that here in action

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Thanks @Radim Kohler... I was able to get the states to load dynamically. But to reference the controllers from the dynamic states. How would one do it? – looneytunes Apr 03 '15 at 16:26
  • Controllers from dynamic states must be already loaded... unless we will use some tools or techniques how to load them lazily, when firstly touched. Here, I created plunker and provided detailed description to show how to do that with *RequireJS* http://stackoverflow.com/q/22627806/1679310... Hope it helps a bit... – Radim Köhler Apr 03 '15 at 16:28