Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to redirect to state if specific stateParam is empty

I'm not sure if the way I am doing it is correct, any advice would be appreciated.

I have a Restaurant Selector, which the user can select a restaurant from. Then all other child states load up content specific to the restaurant selected. But I need to have a child state selected by default, including a restaurant, which will be either selected based on the users closest location or on cookie data if they have previously selected one. But, i'm not sure how I can redirect to a child state by default without knowing the restaurant id already?

A bastardised version of my code below to illustrate.

app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/restaurant/[some id based on cookie info]/our-food"); // if no id is set, then I want to get it from a cookie, but then how do i do the redirect?

$stateProvider
    .state('restaurant', {
        url: '/restaurant/:restaurantId',
        template: "<ui-view/>",
        controller: function($state, $stateParams, Data, RestaurantService, $cookieStore) {
            if(typeof $stateParams.restaurantId !== 'undefined') {
                                  // get the restaurantID from the cookie
                            }
        }
    })
    .state('restaurant.our-food', {
        url: '/our-food',
        templateUrl: function($stateParams) {
        return 'templates/food-food.html?restaurantId=' + $stateParams.restaurantId;
        },
    controller: 'SubNavCtrl'
    })
    .state('restaurant.glutenfree-vegetarian', {
        url: '/glutenfree-vegetarian',
        templateUrl: function($stateParams) {
    return 'templates/food-vegetarian.html?restaurantId=' + $stateParams.restaurantId;
        },
    controller: 'SubNavCtrl'
    })

An image below to illustrate what is happening on the front end: www.merrywidowswine.com/ss.jpg

like image 778
Ben Southall Avatar asked Dec 17 '13 18:12

Ben Southall


2 Answers

I would create an event that is fired every time you open that specific state.

Check out their doc: https://github.com/angular-ui/ui-router/wiki#onenter-and-onexit-callbacks

So my guess is either something like this

1. onEnter callback to restaurant state (recommended)

$stateProvider.state("contacts", {
  template: '<ui-view>',
  resolve: ...,
  controller: function($scope, title){
  },
  onEnter: function(){
    if(paramNotSet){ $state.go(...)}
  }
});

I've never used an event as such myself so you might have to do some gymnastics with resolve, but I believe this is the cleanest, easiest to understand and most maintainable solution.

2 Global onStateChangeStart event A global event (although this would get fired for every state change)

$rootScope.$on('$stateChangeStart', 
function(event, toState, toParams, fromState, fromParams){ ... //check cookie, change state etc ...})

3 In the controller Alternatively If you want to use the controller like you started doing.

controller: ['$state', '$stateParams', 'Data', 'RestaurantService', '$cookieStore', 
function($state, $stateParams, Data, RestaurantService, $cookieStore) {
    if(typeof $stateParams.restaurantId !== 'undefined') {
        sate.go('restaurant', $cookieStore['restaurant'])
    }
}]

This is probably the fastest solution in terms of development but I believe using events is cleaner and makes for more understandable code.

Note: I haven't actually run any of this code so it might not work, it's just pseudo-code to give you an idea of where to go. Let me know if you run into issues.

EDIT: Acutally I'm not sure if stateParams are passed on to the controller. You might have to use resolve to access them.

EDIT: to access stateParams in onEnter callback or the controller, I believe you have to use resolve as such:

    resolve: {
         checkParam: ['$state','$stateParams', '$cookieStore', function($state, $stateParams, $cookieStore) {
//logic in here, what it returns can be accessed in callback or controller.
         }]

see the ui-router doc on resolve for more examples/better explanation

like image 173
NicolasMoise Avatar answered Nov 18 '22 09:11

NicolasMoise


I needed to get this working, so to add details to the answer from @NicolasMoise:

.state('restaurant', {
    url: '/restaurant/:restaurantId',
    template: "<ui-view/>",
    onEnter: function ($state, $stateParams, $cookies) {
      console.log($stateParams.restaurantId);
      if (!$stateParams.restaurantId) {
        $stateParams.restaurantId = $cookies.restaurantId;
        $state.go('restaurant.restaurantID');
      }
    },
})

I didn't test the cookies portion of this, but the conditional and state change worked.

like image 41
shanemgrey Avatar answered Nov 18 '22 08:11

shanemgrey