0
votes

I have been using AngularJS w/ UI-Router for the last couple months and I keep running into the same use case which I cannot seem to find an elegant solution for... I have a step-by-step web planner application that the user must run through to complete an order.

I have a root controller which lives outside of the ui-router scope (there is no 'state' for the root controller) where I have been trying to hold some data that is global to every page in my web planner. This information is like customer information and order name that will be displayed at the top and bottom of the planner throughout the process.

My problem is that in order to get this data into an Angular Service so it can be shared between my controllers I need the OrderId of the order we are talking about. This OrderId exists in the URL $stateParams, but the problem is that my 'root' controller gets instantiated before the ui-router gets involved, meaning I have no way of accessing my $stateParams from inside this controller.

I have resorted to using Angular's $broadcast signaler to tell my root controller when it finally found the OrderId in the url, but this solution just does not feel "right". Does anyone know of any better way to handle "global" information without having to add a query to my Service in every controller of my application?

// This is the root of my web app
<div ng-app="MyApp.backups.new" ng-controller="NewController">

    // This is where I need to display some "global" information
    <h2 class="dashTitle"><sk-img class="iBackup-Add"></sk-img> New Backup {{ (Master.Service.Name ? '- ' + Master.Service.Name : '') }}</h2>
    <div id="wpMenuContainer" class="wpMenuContainer">
        <ul class="wpMenu clearfix">
            <li ng-repeat="chevron in Chevrons | filter:{disabled:false}" ng-class="{ active : chevron.active, navable : $index < Index }" class="backupChevron" ng-click="!($index < Index)||navigate(chevron, $index)">
                <img ng-if="!$last" src="/App_Themes/App/images/misc/clear.gif" class="iMenuArrow">
                <span>{{ chevron.name }}</span>
            </li>

          </ul>
    </div>
    // The problem is ui-router's scope lives within this <div ui-view></div>, so I can't access $stateParams until these child controllers are created
    <div ui-view></div>

</div>
1

1 Answers

0
votes

Have you tried leveraging UI Router's state change events?

// custom factory for setting/getting current state params
app.factory('customFactory', function(){
  var currentParams = null;

  return {
    getParams: function(){ return currentParams; },
    setParams: function(params){ currentParams = params; }
  };

});

// your controller
app.controller('NewController', ['customFactory', function(customFactory){
  var routeParams = function(){ 
    return customFactory.getParams() || {};
  };

  $scope.orderID = routeParams().OrderId;
}]);

// set listener on the '$stateChangeSuccess' event to update the params in your factory
app.run(['$rootScope', 'customFactory', function($rootScope, customFactory){

  $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){
    customFactory.setParams(toParams);
  });

}]);

This way, you only need to reference the 'customFactory' service in 'app.run' and that 1 controller. I haven't tested any of this in a fiddle or anything, but the idea should get you on the right track.