2015-04-27 9 views
8

Tworzę aplikację ze stanami dynamicznymi, a czasami muszę rozwiązać nazwę stanu z adresu URL.ANGULAR-UI-ROUTER: rozwiń stan z adresu URL

np .: Mam /dashboard/user/12268 i potrzebuję uzyskać stan 'dashboard.user'.

Czy można to zrobić za pomocą narzędzi dostarczonych przez ui-router? Nie mogę się teraz dowiedzieć, jak to zrobić ...

Tworzę aplikację z dynamicznym ładowaniem modułów z requireJS. Na początku nie ma problemu, ponieważ użytkownik jest wysyłany do stanu logowania. Po zalogowaniu używam require, aby załadować tylko stany, do których użytkownik ma dostęp. Ale kiedy użytkownik ponownie załaduje stronę, ładuję moduły ponownie i muszę rozwiązać adres URL do stanu, i jest problem. Zacząłem próbować z urlMatcherFactory, ale nie mogę ich rozwiązać.

Stan jest ładowany po rozwiązaniu adresu URL.

Przepływ (po odświeżeniu strony http://localhost:8090/index.html#/dashboard/user/12268):

  • bootstrap aplikacji (bez stanów)
  • w tym momencie, ui-router został załadowany
  • dostać stany użytkownik ma dostęp do i zarejestrować je (te stany są zarejestrowane po fazie konfiguracji)
  • dowiedzieć się, czy mam stan, który pasuje do danego adresu URL, aby przekierować tam. To tutaj utknąłem.

Aby załadować stany po uruchomieniu aplikacji, użyłem odmiany Ben Nadel's solution, która zawiera stany i stałe.

My data-main w RequireJS ma ten kod inicjalizacji:

require.config({ 
 
    // REQUIREJS CONFIGURATION 
 
}); 
 

 
require(['app'], function (app) { 
 
    app.bootstrap(document); 
 

 
    var ng = angular.injector(['ng']); 
 
    var $window = ng.get('$window') 
 
    var $q = ng.get('$q'); 
 

 
    var appStorage = $window.localStorage; 
 
    var loadedManifests; 
 

 
    try { 
 
     loadedManifests = JSON.parse(appStorage.getItem('loadedManifests')); 
 
    } catch(e) { 
 
     loadedManifests = []; 
 
    } 
 

 
    if (!angular.isArray(loadedManifests) || loadedManifests.length === 0) { 
 
     $q.all([ 
 
       app.loadManifest('login/manifest'), //loadMainfest function loads the states for login 
 
       app.loadManifest('logout/manifest') //load states for logout 
 
      ]) 
 
      .then(function() { 
 
       app.injector.get('$rootScope').$evalAsync(function() { 
 
        app.injector.get('$state').go('login'); 
 
       }); 
 
      }); 
 
    } else { 
 
     var promisesArray = []; 
 

 
     for(var i = 0; loadedManifests[i]; i++) { 
 
      promisesArray.push(app.loadManifest(loadedManifests[i])); //load all manifests registered on localstorage 
 
     } 
 

 
     $q.all(promisesArray).then(function(){ 
 
      //TODO: Stuck. Get URL from querystring and resolve to valid state, or redirect to /login 
 
     }); 
 
    } 
 
});

Funkcja loadManifest rejestruje wszystko po-bootstrap elementów na mojej aplikacji (usługi, fabryki, sterowniki, routery, ...).

Dzięki za pomoc,
Alx

+2

proszę opublikuj to, co masz do tej pory. – tim

+0

Tworzę aplikację z dynamicznym ładowaniem modułów z requireJS. Na początku nie ma problemu, ponieważ użytkownik jest wysyłany do stanu logowania. Po zalogowaniu używam require, aby załadować tylko stany, do których użytkownik ma dostęp. Po ponownym załadowaniu strony, ponownie ładuję moduły i muszę rozwiązać problem z adresem URL, a problem występuje. Zacząłem próbować z urlMatcherFactory, ale nie mogę ich rozwiązać. Stan jest ładowany po rozwiązaniu adresu URL. –

+0

UI-Router Extras Future States może zarządzać scenariuszem dla ciebie: http://christopherthielen.github.io/uirouter -extras/#/future –

Odpowiedz

-2

Obecny stan można uzyskać od $ służby państwowej. Sprawdź jak $state.current to api http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state

+0

może zostać dodany jako komentarz –

+0

@pankajparkar to oświadczenie zawiera odpowiedź wraz z odniesieniem do dokumentu api. dlaczego miałby to być komentarz? –

+0

jak to rozwiązuje pytanie OP. Czy mógłbyś mi wyjaśnić? –

1

Wreszcie miałem zrobić małą zmianę na UI-routera $state usługi dostać się do roztworu.

Powoduje to, że stany przechowywane w usłudze mają więcej informacji niż ta podana w metodzie $state.get().Więc powtórzyć nad nimi, aby uzyskać stan, który odpowiada z moim adresem:

/** 
 
* @ngdoc function 
 
* @name ui.router.state.$state#fromUrl 
 
* @methodOf ui.router.state.$state 
 
* 
 
* @description 
 
* A method to resolve a state and its parameters from a given URL 
 
* 
 
* @returns {boolean} Returns a state that matches with the given URL, or undefined if no match 
 
*/ 
 
$state.fromUrl = function(url) { 
 
    if(!angular.isString(url)) { 
 
    //Only valid strings allowed 
 
    return undefined; 
 
    } 
 
    
 
    
 
    var keys = objectKeys(states); 
 
    //Iterate over all states 
 
    for(var i = 0; i < keys.length; i++) { 
 
    var state = states[keys[i]]; 
 
    var stateArgs = state.url.exec(url); 
 

 
    //If the state's URL does not match then stateArgs will be false 
 
    if(!!stateArgs) { 
 
     return { 
 
     name: state.name, 
 
     args: stateArgs 
 
     } 
 
    } 
 
    } 
 

 
    return undefined; 
 
};

Pozdrowienia,
ALX

+0

skąd "stany" pochodzą z objectKeys (stany)? –

14

https://github.com/angular-ui/ui-router/issues/1651

można wystawiać wewnętrzną realizację członkowskim przez przy użyciu haka .decorator na $stateProvider. Możesz ozdobić każdą nieruchomość budowniczego państwa; Wybrałem "rodzic" arbitralnie.


app.config(function($stateProvider) { 
    $stateProvider.decorator('parent', function (internalStateObj, parentFn) { 
    // This fn is called by StateBuilder each time a state is registered 

    // The first arg is the internal state. Capture it and add an accessor to public state object. 
    internalStateObj.self.$$state = function() { return internalStateObj; }; 

    // pass through to default .parent() function 
    return parentFn(internalStateObj); 
    }); 
}); 

Teraz można uzyskać dostęp do wewnętrznego stanu obiektu, na przykład przy użyciu .$$state()

var publicState = $state.get("foo"); 
var privateInternalState = publicState.$$state(); 

drugie, pętla nad każdym stanie w $ state.get() i przetestować je przed fragmentem adresu URL.

angular.forEach($state.get(), function(state) { 
    var privatePortion = state.$$state(); 
    var match = privatePortion.url.exec(url, queryParams); 
    if (match) console.log("Matched state: " + state.name + " and parameters: " + match); 
}); 
+0

To jest wielki dowód dobrego, projektu. Rozszerzalność ... –

+0

Najlepsza. Rozwiązanie. Zawsze. Dziękujemy! –

+3

W części wyszukiwania dodanie 'if (! Stan. $$ state) return;' byłoby dobre, ponieważ miałem stan abstrakcyjny _global_, który nie miał tej właściwości i spowodował błąd. – Parziphal

0

Aby uzyskać rozwiązanie @Chris T pracować dla mnie Robię to wewnątrz serwisu:

app.service('Helper', ['$state', '$location', 
    function($state, $location){ 

     var services = {}; 

     services.stateIs = function(state_name){ 
      var current_path = $location.$$path; 
      var state = $state.get(state_name); 

      if(state){ 
       var state_regexp = state.$$state().url.regexp; 
       return state_regexp.test(current_path); 
      }else{ 
       return false; 
      } 
     } 

     return services; 
    } 
]); 

więc później mogę wstrzyknąć Helper wszędzie i robić to:

if(Helper.stateIs('app.user')){ 
    //yeah 
}