Weiterleiten des Benutzers in einen untergeordneten Status, wenn er mithilfe des UI-Routers in den übergeordneten Status wechselt

77

Folgendes berücksichtigen:

.state('manager.staffList', {url:'^/staff?alpha', templateUrl: 'views/staff.list.html', data:{activeMenu: 'staff'}, controller: 'staffListCtrl'})
.state('manager.staffDetail', {url:'^/staff/{id}' , templateUrl: 'views/staff.html', data:{activeMenu: 'staff'}, controller: 'staffDetailsCtrl'})
  .state('manager.staffDetail.view', {url:'/view',  templateUrl: 'views/staff.details.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.schedule', {url:'/schedule', templateUrl:'views/staff.view.schedule.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.history', {url:'/history' , templateUrl:'views/staff.view.history.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.log', {url:'/log', templateUrl:'views/staff.view.log.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.files', {url:'/files', templateUrl:'views/staff.view.files.html', data:{activeMenu: 'staff'}})
  .state('manager.staffDetail.edit', {url:'/edit',  templateUrl: 'views/staff.edit.html', data:{activeMenu: 'staff'}})

domain.com/staff/1234/viewWie gehe ich standardmäßig zum manager.staffDetail.view.scheduleuntergeordneten Status, wenn ich zu gehe ?

Meeker
quelle
Zu Ihrer Information , ich verwende derzeit die redirectTohier gefundene Methode stackoverflow.com/questions/29491079/…
Meeker
Bitte bearbeiten Sie dies NICHT, um mehr vertikalen Code zu erstellen. Der Code ist speziell formatiert, um die Kinderzustände im Vergleich zu ihren Eltern visuell darzustellen.
Meeker
@UdayHiwarale, das ist der gleiche Link, der bereits oben gepostet wurde
Meeker
Mein Fehler. Ich sah nicht.
Uday Hiwarale

Antworten:

136
  1. Fügen Sie zunächst eine Eigenschaft zum 'manager.staffDetail.view'Status von hinzu abstract:true. Dies ist nicht erforderlich, aber Sie möchten dies festlegen, da Sie niemals direkt in diesen Status wechseln würden, sondern immer in einen der untergeordneten Status.

  2. Führen Sie dann einen der folgenden Schritte aus:

    • Geben Sie dem 'manager.staffDetail.view.schedule'Status eine leere URL . Dadurch stimmt es mit derselben URL überein wie die URL des übergeordneten Status, da nichts an die übergeordnete URL angehängt wird.

      .state('manager.staffDetail.view.schedule', {url:'', ...

    • Wenn Sie die URL der untergeordneten Standardroute unverändert lassen möchten, richten Sie in Ihrer module.config eine Umleitung ein. Dieser Code hier leitet jeden Ort von '/staff/{id}/view'an den Ort von '/staff/{id}/view/schedule':

      $urlRouterProvider.when('/staff/{id}/view', '/staff/{id}/view/schedule');

Tim Kindberg
quelle
4
Bei der $urlRouterProviderUmleitung wurde beim Verwenden eines Links mit ein Fehler angezeigt ui-sref="manager.staffDetail.view", sodass ich ihn abstract: trueaus der übergeordneten Statusdeklaration entfernen musste .
Colllin
4
Die zweite Option funktioniert nicht für interne UI-Sref-Links (sie geht nicht in den Unterzustand)
Stepan Suworow
20

Überprüfen Sie dieses Beispiel , um die untergeordnete Standardansicht festzulegen . Beim Klicken auf Route 1Standardzustand ladenroute1.list

// For any unmatched url, send to /route1
$stateProvider
  .state('route1', {
      url: "/route1",
      abstract:true ,
      templateUrl: "route1.html"
  })
  .state('route1.list', {
      url: '',
      templateUrl: "route1.list.html",
      controller: function($scope){
        $scope.items = ["A", "List", "Of", "Items"];
      }
  })
  .state('route1.desc', {
      url: "/desc",
      templateUrl: "route1.desc.html",
      controller: function($scope){
        $scope.items = [];
      }
  })
  .state('route2', {
    url: "/route2",
    templateUrl: "route2.html"
  })
  .state('route2.list', {
    url: "/list",
    templateUrl: "route2.list.html",
    controller: function($scope){
      $scope.things = ["A", "Set", "Of", "Things"];
    }
  })
rab
quelle
Wenn route1.desckeine URL vorhanden ist, können Sie diese weiterhin erreichen $state.go, werden jedoch route1.liststandardmäßig auf /route1:) geladen. Dies ist nützlich, wenn Sie keinen direkten Zugriff auf den Status über die URL gewähren möchten
Andrei Cojea
2
Es gibt ein großes Problem damit, wenn wir den übergeordneten Zustand in ui-sref verwenden wollen
Kishore Relangi
Sie müssen href = "/ abstractroute" verwenden, um eine Verknüpfung zum übergeordneten
Eric Shell
Kann mir jemand erklären, warum der route1Status in diesem Beispiel eine templateUrl benötigt? Oder allgemeiner, warum sollte ein abstract:trueStaat eine Vorlage benötigen?
Gewähren Sie
Die Eltern des Kindes sollten die mitabstract:true
aRyhan
8

Ich bin auf dasselbe Problem gestoßen und habe festgestellt, dass diese Lösung funktioniert:

https://github.com/angular-ui/ui-router/issues/948#issuecomment-75342784

Dies wird aus @christopherthielen auf Github zitiert

"Deklarieren Sie Ihren Zustand vorerst nicht als abstrakt und verwenden Sie dieses Rezept:"

 app.run($rootScope, $state) {
    $rootScope.$on('$stateChangeStart', function(evt, to, params) {
      if (to.redirectTo) {
        evt.preventDefault();
        $state.go(to.redirectTo, params)
      }
    });
  }

  $stateProvider.state('parent' , {
      url: "/parent",
      templateUrl: "parent.html",
      redirectTo: 'parent.child'
  });

  $stateProvider.state('parent.child' , {
      url: "/child",
      templateUrl: "child.html"
  });

Hier ist eine Aufschlüsselung der Funktionsweise des Prozesses:

  1. Der Benutzer navigiert zum Status "Eltern".
  2. Das Ereignis "$ stateChangeStart" wird ausgelöst
  3. Der Listener für "$ stateChangeStart" fängt das Ereignis ab und übergibt "toState" (das ist "parent") und "event" an die Handlerfunktion
  4. Die Handlerfunktion prüft, ob "redirectTo" auf "toState" gesetzt ist.
  5. Wenn "redirectTo" NICHT gesetzt ist, passiert nichts und der Benutzer fährt mit dem Status "toState" fort.
  6. Wenn "redirectTo" festgelegt ist, wird das Ereignis abgebrochen (event.preventDefault) und $ state.go (toState.redirectTo) sendet sie an den in "redirectTo" angegebenen Status ("parent.child").
  7. Das Ereignis "$ stateChangeStart" wird erneut ausgelöst, diesmal jedoch "toState" == "parent.child" und die Option "redirectTo" sind nicht festgelegt, sodass "toState" fortgesetzt wird.
Chuck D.
quelle
kann das jemand erklären. Wird dies nicht zu einer Endlosschleife?
Kishore Relangi
Hallo Kishore, ich habe die Antwort aktualisiert, um zu erklären, wie es funktioniert. Es wird KEINE Endlosschleife geben, es sei denn, Sie geben den Status "Eltern" in der Option "RedirectTo" explizit an.
Chuck D
Ich habe es versucht, aber leider funktioniert das bei mir nicht. Ich benutze UI-Router v0.3.1
Hussain
7

Ziemlich spät, aber ich denke, Sie können in den gewünschten Zustand "umleiten".

.state('manager.staffDetail.view', {
    url:'/view',
    templateUrl: 'views/staff.details.html',
    controller: 'YourController'
})

app.controller('YourController', ['$state',
function($state) {
    $state.go('manager.staffDetail.view.schedule');
}]);

Sie können Ihren Controller direkt in die Statuskonfiguration schreiben.

nvcnvn
quelle
3
Ich habe das versucht, aber es wird Controller, Auflösungen und alles, was onStateChange ist, doppelt laden. Ich musste nur $ urlRouterProvider.when ('/ app / service', '/ app / service / list') verwenden
Meeker
Wird dies nur zweimal oder unendlich oft geladen, da der untergeordnete Status auch den übergeordneten Status erneut aufruft, da wir dort erneut zum untergeordneten Status umleiten.
Kishore Relangi
Wenn Ihre Navigation über das übergeordnete sref verfügt, funktioniert dies bei nachfolgenden Klicks nicht - nur beim ersten Laden des Controllers.
Jonathon Hill
3

Ich habe 'manager.staffDetial.view' in einen abstrakten Status geändert und die URL meines untergeordneten Standardstatus leer gelassen. ''

// Staff
.state('manager.staffList',    {url:'^/staff?alpha',      templateUrl: 'views/staff.list.html', data:{activeMenu: 'staff'}, controller: 'staffListCtrl'})
.state('manager.staffDetail',   {url:'^/staff/{id}', templateUrl: 'views/staff.html', data:{activeMenu: 'staff'}, controller: 'staffDetailsCtrl'})
.state('manager.staffDetail.view',   {url:'/view', abstract: true, templateUrl: 'views/staff.details.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.schedule', {url:'', templateUrl:'views/staff.view.schedule.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.history', {url:'/history', templateUrl:'views/staff.view.history.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.log', {url:'/log', templateUrl:'views/staff.view.log.html', data:{activeMenu: 'staff'}})
    .state('manager.staffDetail.view.files', {url:'/files', templateUrl:'views/staff.view.files.html', data:{activeMenu: 'staff'}})
.state('manager.staffDetail.edit',   {url:'/edit',  templateUrl: 'views/staff.edit.html', data:{activeMenu: 'staff'}})
Meeker
quelle
13
Sie haben also im Grunde genau das getan, was ich vorgeschlagen hatte ... warum geben Sie meiner Antwort dann nicht das richtige Häkchen? So kann ich die Wiederholungspunkte bekommen.
Tim Kindberg
Ich bin nicht sicher, ob Sie wissen, was das Wort "genau" bedeutet. In Ihrem Codebeispiel wurde jedoch die routeProvider-Methode verwendet. Ich habe mich dafür entschieden, das überhaupt nicht zu verwenden und stattdessen die Lösung im State Manager zu behalten. Auf diese Weise bleibt der Code sauber und fügt keine unnötigen zusätzlichen Codezeilen hinzu. Ihr Beispiel war eine mögliche Antwort, aber nicht die akzeptabelste.
Meeker
Es schien, als ob alles, was Sie getan haben, ich erwähnt hatte (obwohl der Code in meinem Beispiel nicht notwendig war). ME: "... du solltest es in einen abstrakten Zustand versetzen." SIE: "Ich habe 'manager.staffDetial.view' in einen abstrakten Zustand geändert ..." ME: "Oder eine andere Option ist, dem Zeitplan eine leere URL zu geben." SIE: "... und haben die URL meines untergeordneten Standardstatus leer gelassen". Ernsthaft keine harten Gefühle, ich bin froh, dass du es herausgefunden hast.
Tim Kindberg
1
Entschuldigung, Ihre Antwort war verwirrend und nicht zutreffend. Nachdem ich Ihre Erklärung gelesen habe, sehe ich, dass Sie die getrennten Optionen angegeben haben und dass ich am Ende eine Lösung hätte, wenn ich Ihre erste und letzte Option kombiniert und den mittleren Vorschlag weggelassen hätte. Ich denke, ich sehe, wohin Sie gehen, aber ich bin nicht sicher, ob es dem nächsten Leser helfen würde, wenn ich Ihre als Antwort markieren würde. Wenn Sie Ihre Antwort bearbeiten und Ihre Antwort klären möchten, gebe ich Ihnen gerne die Antwort.
Meeker
Ja, Sie haben Recht, ich habe die Antwort von meinem Telefon aus geschrieben ...: PI hat die Antwort aufgeräumt, ich hoffe, es macht jetzt mehr Sinn. Ich habe auch bemerkt , dass , wenn ich die Suche ui-Router auf Google dieses Themas das vierte Ergebnis ist, so ist es ist wichtig , dass wir haben es sehr klar sein.
Tim Kindberg
1

In "Angular-UI-Router": "0.2.13" glaube ich nicht, dass die Umleitungslösung von @ nfiniteloop funktioniert. Es hat funktioniert, nachdem ich auf 0.2.12 zurückgesetzt hatte (und möglicherweise den $ urlRouterProvider.when Aufruf vor dem $ stateProvider setzen musste?)

Siehe https://stackoverflow.com/a/26285671/1098564

und https://stackoverflow.com/a/27131114/1098564 für eine Problemumgehung (wenn Sie nicht zu 0.2.12 zurückkehren möchten)

Ab dem 28. November 2014 gibt https://github.com/angular-ui/ui-router/issues/1584 an, dass es in 0.2.14 wieder funktionieren sollte

sdoxsee
quelle
1

Dies ist spät, aber alle Antworten hier gelten nicht für die neueste Version von Angular-UI-Router für AngularJS. Ab dieser Version (speziell @ uirouter / anglejs # v1.0.x können Sie einfach redirectTo: 'childStateName'den zweiten Parameter von eingeben $stateProvider.state(). Zum Beispiel:

$stateProvider
.state('parent', {
  resolve: {...},
  redirectTo: 'parent.defaultChild'
})
.state('parent.defaultChild', {...})

Hier ist der relevante Dokumentabschnitt: https://ui-router.github.io/guide/ng1/migrate-to-1_0#state-hook-redirectto

Hoffentlich hilft das jemandem!

AndyPerlitch
quelle
0

Hier ist eine sehr einfache und transparente Alternative, indem Sie einfach den übergeordneten Status im UI-Router ändern:

  .state('parent_state', {
    url: '/something/:param1/:param2',
    templateUrl: 'partials/something/parent_view.html',  // <- important
    controller: function($state, $stateParams){
      var params = angular.copy($state.params);
      if (params['param3'] === undefined) {
        params['param3'] = 'default_param3';
      }
      $state.go('parent_state.child', params) 
    }
  })

  .state('parent_state.child', {
    url: '/something/:param1/:param2/:param3',
    templateUrl: '....',  
    controller: '....'
  })
Okigan
quelle
0

Fügen Sie Angular-UI-Router-Standard hinzu und fügen Sie das abstractund hinzudefault Optionen an den übergeordneten Zustand:

...

.state('manager.staffDetail.view', {abstract: true, default: '.schedule', url:'/view',  templateUrl: 'views/staff.details.html', data:{activeMenu: 'staff'}})
  .state('manager.staffDetail.view.schedule', {url:'/schedule', templateUrl:'views/staff.view.schedule.html', data:{activeMenu: 'staff'}})

...

Hinweis: Damit dies funktioniert, muss die übergeordnete Vorlage <ui-view/>irgendwo enthalten sein.

Jonathon Hill
quelle