2013-12-17 6 views
27

Non sono sicuro che il modo in cui lo sto facendo sia corretto, qualsiasi consiglio sarebbe apprezzato.Come reindirizzare per specificare se stateParam specifico è vuoto

Ho un Selettore ristorante, da cui l'utente può selezionare un ristorante. Quindi tutti gli altri stati secondari caricano il contenuto specifico per il ristorante selezionato. Ma ho bisogno di avere uno stato figlio selezionato di default, incluso un ristorante, che sarà selezionato in base alla posizione più vicina degli utenti o ai dati dei cookie se ne hanno selezionato uno in precedenza. Ma non sono sicuro di come reindirizzare a uno stato figlio per impostazione predefinita senza conoscere già l'ID del ristorante?

Una versione bastardizzata del mio codice qui sotto per illustrare.

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' 
    }) 

Un'immagine di seguito per illustrare ciò che sta accadendo sul front-end: www.merrywidowswine.com/ss.jpg

risposta

37

vorrei creare un evento che viene generato ogni volta che si apre questo stato specifico.

controllare il loro doc: https://github.com/angular-ui/ui-router/wiki#onenter-and-onexit-callbacks

Quindi la mia ipotesi è o qualcosa di simile

1. onEnter callback allo stato ristorante (consigliato)

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

non ho mai usato un evento in quanto tale me stesso in modo che tu possa dover fare qualche ginnastica con risolutezza, ma credo che questa sia la soluzione più pulita, più facile da capire e più mantenibile.

2 Global onStateChangeStart evento Un evento globale (anche se questo sarebbe licenziato per ogni cambiamento di stato)

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

3 Nel controllore In alternativa, se si desidera utilizzare il controller come hai iniziato facendo.

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

Questa è probabilmente la soluzione più veloce in termini di sviluppo, ma credo che con gli eventi è più pulito e rende il codice più comprensibile.

Nota: Non ho effettivamente eseguito alcun codice in modo che non funzioni, è solo uno pseudo-codice per darti un'idea di dove andare. Fammi sapere se incontri problemi.

MODIFICA: In linea di massima non sono sicuro se stateParams vengono passati al controller. Potrebbe essere necessario utilizzare la risoluzione per accedervi.

EDIT: per accedere stateParams in onEnter callback o il controller, credo che si deve utilizzare risolvere in quanto tale:

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

vedere il doc ui-router sulla risoluzione per ulteriori esempi/spiegazione migliore

+0

Grazie, questo mi indica la direzione giusta, sto per giocare e vedere se riesco a far funzionare tutto. Saluti! –

+1

Il problema (che avevo) con la tua soluzione n. 1 è che tutte le proprietà di risoluzione sono risolte prima che venga eseguito 'onEnter'. Ho iniziato un problema su github: https://github.com/angular-ui/ui-router/issues/1102. Non sono sicuro che ci sia un gancio nascosto da cortocircuitare se non si desidera risolvere i parametri risolti prima di reindirizzare (se, ad esempio, la rotta richiede un parametro particolare). – Beez

+0

Invece di '$ state.transitionTo' forse sarebbe meglio usare' $ state.go', come indicato [qui] (https://github.com/angular-ui/ui-router/wiki/Quick-Reference# state-1) – Daniele

3

avevo bisogno di ottenere questo lavoro, in modo da aggiungere dettagli per la risposta da @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 non ha testato la parte relativa ai cookie, ma ha funzionato la modifica condizionale e di stato.