2014-09-16 7 views
52

Gibt es eine Möglichkeit, programmgesteuert States nach der Modulkonfiguration States StateProvider hinzuzufügen, z. Bedienung ?Angular - UI-Router - programmgesteuert Hinzufügen von Zuständen

Um mehr Kontext zu dieser Frage hinzufügen, ich eine Situation, wo ich mit zwei Ansätzen gehen:

  1. Versuch zu zwingen, die reload auf dem Zustand definiert, in der Modulkonfiguration ist das Problem, dass Staat hat a reloadOnSearch eingestellt auf false, also wenn ich es versuche $ state.go ('state.name', {neu: param}, {reload: true}); nichts passiert, irgendwelche Ideen?

staatliche Definition

.state('index.resource.view', { 
    url: "/:resourceName/view?pageNumber&pageSize&orderBy&search", 
    templateUrl: "/resourceAdministration/views/view.html", 
    controller: "resourceViewCtrl", 
    reloadOnSearch: false, 
}) 
  1. versuchen programmatisch Staaten hinzuzufügen, die ich von einem Dienst laden müssen, damit Routing richtig funktionieren. Ich würde lieber mit der ersten Option gehen, wenn möglich.

Antwort

106

Siehe -edit- für aktuelle Informationen

Normalerweise Staaten zum $stateProvider während der Konfigurationsphase hinzugefügt werden. Wenn Sie zur Laufzeit Status hinzufügen möchten, müssen Sie einen Verweis auf die $stateProvider Umgebung beibehalten.

Dieser Code ist nicht getestet, sollte aber tun, was Sie wollen. Es erstellt einen Dienst mit der Bezeichnung runtimeStates. Sie können es in den Laufzeitcode einfügen und dann Zustände hinzufügen.

// config-time dependencies can be injected here at .provider() declaration 
myapp.provider('runtimeStates', function runtimeStates($stateProvider) { 
    // runtime dependencies for the service can be injected here, at the provider.$get() function. 
    this.$get = function($q, $timeout, $state) { // for example 
    return { 
     addState: function(name, state) { 
     $stateProvider.state(name, state); 
     } 
    } 
    } 
}); 

Ich habe einige Sachen Zukunft Staaten in UI-Router Extras, die kümmern sich um einige der Ecke Fälle für Sie wie Mapping Urls Staaten genannt implementiert, die noch nicht existieren. Future States zeigt auch, wie Sie den Quellcode für Laufzeitzustände langsam laden können. Werfen Sie einen Blick auf die source code, um ein Gefühl für das, was beteiligt ist, zu bekommen.

-edit- für UI-Router 1.0+

In UI-Router 1.0 können Staaten und zur Laufzeit mit StateRegistry.register und StateRegistry.deregister deregistriert werden.

Um Zugriff auf die StateRegistry zu erhalten, injizieren Sie sie als $stateRegistry oder injizieren Sie $uiRouter und greifen Sie darauf über UIRouter.stateRegistry zu.

UI-Router 1.0 enthält auch Future States, die das verzögerte Laden von Statusdefinitionen und sogar die Synchronisierung per URL verarbeiten.

+0

Danke für den Beitrag Zukunft Staaten, Chris! Ich wähle dieses wegen des Wertes, aber lasse meine andere Antwort unten, weil dieser Blogbeitrag auch einige interessante Leckerbissen darauf hat. –

+0

@ChadRobinson +1 für Sie zu –

+1

Ich testete diese Lösung und es funktioniert gut, ich hatte kleines Problem, weil ich _'index.resource.DYNAMIC-STATE-NAME.view'_ verwendet und es war wahrscheinlich aufgrund dynamischer Zustände Schlange wurde als übergeordneter Status identifiziert, sobald ich den Status-Namen in _'index.resource.DYNAMIC-STATE-NAMEView_ änderte, es funktionierte korrekt. – khorvat

4

Ja, es ist möglich, dies zu tun, aber da Caching-Layer beteiligt sind, ist es komplex. Alex Feinberg hat hier eine Lösung auf seinem Blog dokumentiert:

http://alexfeinberg.wordpress.com/2014/03/08/dynamically-populating-angular-ui-router-states-from-a-service/

Das hintere Ende des Artikels enthält ein Beispiel einen Zustand zu schaffen, durch die stateProvider mit:

app.stateProvider.state(ent.lob.name.toLowerCase(), { 
    url: '/' + ent.lob.name.toLowerCase(), 
    controller: ent.lob.name.toLowerCase() + 'Controller', 
    templateUrl: 'lobs/views/' + ent.lob.name.toLowerCase() + '.html' 
}); 
+0

Es gibt einige großartige Punkte in dem Artikel, aber für mich ist es etwas seltsam, das App-Objekt mit _stateProvider_ zu erweitern. Danke – khorvat

13

Chris T es genagelt! Der Anbieter ist der Weg zu gehen.Sie müssen nicht auf das Fenster Objekt schlagen, Sparer, mehr geschützt usw.

Kreuz Referenzierung seine Antwort mit diesem Artikel hat mich sehr geholfen: http://blog.xebia.com/2013/09/01/differences-between-providers-in-angularjs/#provider

Die Lösung macht einen spezifischen Module $ stateProvider während des Config Block für andere Module während ihrer Laufblöcke zugänglich.

In meiner Situation erzeuge ich dynamisch Dashboard-Status abhängig von den Berechtigungen eines Benutzers.

Während meines Config-Blocks wird mein Provider gesetzt und übergibt den stateProvider des Moduls (auf den später zugegriffen wird).

//in dashboard.module.js 
 

 
var dashboardModule = angular.module('app.modules.dashboard',[ 
 
     'app.modules.dashboard.controllers', 
 
     'app.modules.dashboard.services', 
 
     'app.modules.dashboard.presentations.mileage' 
 
    ]) 
 

 
    .provider('$dashboardState', function($stateProvider){ 
 
     this.$get = function(PATHS, $state){ 
 
      return { 
 
       addState: function(title, controllerAs, templatePrefix) { 
 
        $stateProvider.state('dashboard.' + title, { 
 
         url: '/' + title, 
 
         views: { 
 
          '[email protected]': { 
 
           templateUrl: PATHS.DASHBOARD + (templatePrefix ? templatePrefix + '/' : '/') + title + '/' + title + '.view.html', 
 
           controller: controllerAs ? controllerAs : null 
 
          } 
 
         } 
 
        }); 
 
       } 
 
      } 
 
     } 
 
    });

Das wird mein Dashboard-Zustand Provider zur Verfügung zu anderen Modulen machen, anstatt sie auf dem Fenster schlagend.

Dann kann ich im Run Block (Controller) meines Benutzermoduls auf den Statusanbieter des Dashboards zugreifen und Zustände dynamisch injizieren.

var UserControllers = angular.module('app.modules.user.controllers', []) 
 

 
.controller("UserLoginController", ["$state", "$dashboardState", function($state, $dashboardState){ 
 

 
    $dashboardState.addState('faq', null, 'content'); 
 

 
    $state.go('dashboard.faq'); 
 

 
}]);

+0

Bis jetzt der einfachste Weg, brauche AMD nicht (wie Ui-Router Extras). Nur müssen Sie sicherstellen, dass Sie den Anbieter in einem neuen Modul hinzufügen, andernfalls wird nicht funktionieren. –

+0

Hallo, ich habe versucht, dies zu implementieren, aber ich bekomme einen Fehler, unbekannte Anbieter zu sagen. Wie registriere ich den Provider in Config? Ich möchte den Anbieter in einen Controller injizieren. – ChaoticTwist