Aktualisieren der URL in Angular JS ohne erneutes Rendern der Ansicht

79

Ich baue ein Dashboard-System in AngularJS auf und stoße auf ein Problem beim Festlegen der URL über $location.path

In unserem Dashboard haben wir eine Reihe von Widgets. Jedes zeigt eine größere maximierte Ansicht, wenn Sie darauf klicken. Wir versuchen, Deep Linking einzurichten, damit Benutzer mit einem maximierten Widget auf ein Dashboard verlinken können.

Derzeit haben wir 2 Routen, die wie /dashboard/:dashboardIdund aussehen/dashboard/:dashboardId/:maximizedWidgetId

Wenn ein Benutzer ein Widget maximiert, aktualisieren wir die URL mithilfe von $location.path. Dies führt jedoch dazu, dass die Ansicht erneut gerendert wird. Da wir alle Daten haben, möchten wir nicht die gesamte Ansicht neu laden, sondern nur die URL aktualisieren. Gibt es eine Möglichkeit, die URL festzulegen, ohne dass die Ansicht erneut gerendert wird?

HTML5Modeist auf eingestellt true.

Ian Muir
quelle
1
Wenn Sie möchten, dass Ihre Daten Routenänderungen auf der Clientseite überstehen, können Sie sie in einen Dienst übertragen.
Riko

Antworten:

132

Tatsächlich wird jedes Mal eine Ansicht gerendert, wenn Sie eine URL ändern. So funktioniert $ routeProvider in Angular, aber Sie können es maximizeWidgetIdals Querystring übergeben, der eine Ansicht nicht erneut rendert.

App.config(function($routeProvider) {
  $routeProvider.when('/dashboard/:dashboardId', {reloadOnSearch: false});
});

Wenn Sie auf ein Widget klicken, um es zu maximieren:

<a href="#/dashboard/1?maximizeWidgetId=1">Maximum This Widget</a>
or
$location.search('maximizeWidgetId', 1);

Die URL in der Adressleiste würde sich in ändern http://app.com/dashboard/1?maximizeWidgetId=1

Sie können sogar beobachten, wenn sich die Suche in der URL ändert (von einem Widget zum anderen).

$scope.$on('$routeUpdate', function(scope, next, current) {
   // Minimize the current widget and maximize the new one
});
codef0rmer
quelle
1
Wenn es akzeptiert wird, werde ich eine separate Frage ohne ": param" -Dinge erstellen. Einfach nur blöde Frage: Wie kann man die Ansicht nicht neu rendern?
OZ_
2
Ich denke, Angular-UI-Router wird in diesem Fall eine offensichtliche Wahl sein.
Codef0rmer
1
Ich benutze die $routeUpdateVeranstaltung. Ich denke, das $routeChangeStartwird ausgelöst, wenn man an einen anderen Ort zieht.
Lucassp
@kuchumovn: Leider sind wir noch im Jahr 2014. Angular 2.0 wird ein überarbeitetes Routing (wahrscheinlich Angular-UI-Router eingebaut) haben, das das tun würde, was Sie beabsichtigt haben.
Codef0rmer
1
@ codef0rmer, ich habe diese Antwort mehr als einmal gefunden. Vielen Dank! Tolle Antwort, immer noch nach all dieser Zeit!
Frosty
9

Sie können die reloadOnSearch-Eigenschaft von $ routeProvider auf false setzen.

Mögliche doppelte Frage: Können Sie einen Pfad ändern, ohne den Controller in AngularJS neu zu laden?

Grüße

bdavidxyz
quelle
Das sieht so aus, als wäre es ein Duplikat. Leider sieht es so aus, als hätten sie das gleiche Problem, solange es Teil des URL-Pfads ist und keine Abfragevariable, wird es aktualisiert.
Ian Muir
Nein, es ist kein Duplikat.
OZ_
Es handelt sich nicht um ein Duplikat, da es bei der verknüpften Frage darum geht, den Controller nicht neu zu laden und die Vorlage nicht neu zu laden. Durch die Lösung in der verknüpften Frage wird die Ansicht neu geladen.
Lajos Meszaros
6

Für diejenigen, die den vollständigen Pfad () ändern müssen, ohne dass die Controller neu geladen werden müssen

Hier ist das Plugin: https://github.com/anglibs/angular-location-update

Verwendung:

$location.update_path('/notes/1');
Daniel Garmoshka
quelle
3
danke, funktioniert. Aber vielleicht sollten Sie den ursprünglichen Standort nicht erweitern?
Rofrol
3

Für ein ähnliches Szenario verwenden wir Angular UI Router anstelle von integrierten Routen. Es scheint nicht, den Controller neu zu instanziieren und die gesamte Ansicht neu zu rendern.

DreamSonic
quelle
2
Haben Sie versucht, $state.transitionTo()statt zu verwenden $location.path()?
DreamSonic
1
Ich ändere $ location.path () überhaupt nicht, wo soll ich $state.transitionTo()dann schreiben ?
OZ_
Zitat: "Wenn ein Benutzer ein Widget maximiert, aktualisieren wir die URL mithilfe von location.path. Dies führt jedoch dazu, dass die Ansicht erneut gerendert wird." Anstatt den Pfad zu ändern, sollten Sie aufrufen, $state.transitionTo()wodurch der URL-Hash aktualisiert wird.
DreamSonic
Die Idee ist, dass Sie zwei verschachtelte Status haben sollten: einen für Ihr Dashboard und einen für Ihr maximiertes Widget. Wenn Sie vom übergeordneten Status zum untergeordneten Status navigieren, wird nur die untergeordnete Ansicht erneut gerendert, nicht die übergeordnete Ansicht.
DreamSonic
3

Mir ist klar, dass dies eine alte Frage ist, aber da ich anderthalb Tage gebraucht habe, um die Antwort zu finden, geht es weiter.

Sie müssen Ihren Pfad nicht in Abfragezeichenfolgen konvertieren, wenn Sie einen Angular-UI-Router verwenden .

Derzeit kann die Einstellung reloadOnSearch: falseeines Status aufgrund eines möglicherweise als Fehler angesehenen Status dazu führen, dass die Route geändert werden kann, ohne dass die Ansicht neu geladen werden muss. Der GitHub-Benutzer lmessinger war sogar so freundlich, eine Demo davon bereitzustellen. Sie finden den Link aus seinem oben verlinkten Kommentar.

Grundsätzlich müssen Sie nur Folgendes tun:

  1. Verwenden Sie ui-routeranstelle vonngRoute
  2. Erklären Sie in Ihren Bundesstaaten diejenigen, mit denen Sie möchten reloadOnSearch: false

In meiner App habe ich eine Kategorieauflistungsansicht, von der aus Sie mit einem Status wie dem folgenden zu einer anderen Kategorie gelangen können:

$stateProvider.state('articles.list', {
  url: '{categorySlug}',
    templateUrl: 'partials/article-list.html',
    controller: 'ArticleListCtrl',
    reloadOnSearch: false
  });

Das ist es. Hoffe das hilft!

ohanhi
quelle
2

Wie ich es implementiert habe:
(meine Lösung hauptsächlich für Fälle, in denen Sie die gesamte Route ändern müssen, nicht Unterteile)

Ich habe eine Seite mit Menü (menuPage) und Daten sollten bei der Navigation nicht bereinigt werden (es gibt viele Eingaben auf jeder Seite und der Benutzer wird sehr, sehr unglücklich sein, wenn Daten versehentlich verschwinden).

  1. Schalten Sie $ routeProvider aus
  2. Fügen Sie im mainPage-Controller zwei Divs mit einem benutzerdefinierten Direktivenattribut hinzu. Jede Direktive enthält nur 'templateUrl' und 'scope: true'.

     <div ng-show="tab=='tab_name'" data-tab_name-page></div>
    
  3. Der mainPage-Controller enthält Leitungen zur Simulation des Routings:

    if (!$scope.tab && $location.path()) {
        $scope.tab = $location.path().substr(1);
    }
    $scope.setTab = function(tab) {
        $scope.tab = tab;
        $location.path('/'+tab);
    };
    

Das ist alles. Es ist ein bisschen hässlich, für jede Seite eine eigene Direktive zu haben, aber die Verwendung von dynamischem templateUrl (als Funktion) in der Direktive führt zum erneuten Rendern der Seite (und zum Verlust von Eingabedaten).

OZ_
quelle
0

Wenn ich Ihre Frage richtig verstanden habe, möchten Sie,

  1. Maximieren Sie das Widget, wenn sich der Benutzer in / dashboard /: dashboardId befindet und das Widget maximiert.
  2. Sie möchten, dass der Benutzer zu / dashboard /: dashboardId /: maximizedWidgetId zurückkehren und das Widget weiterhin maximiert sehen kann.

Sie können nur die erste Route in der routerConfig konfigurieren und mithilfe von RouteParams feststellen , ob das maximierte Widget in den Parametern im Controller dieser konfigurierten Route übergeben wird, und die als Parameter übergebene Route maximieren. Wenn der Benutzer es zum ersten Mal maximiert, teilen Sie die URL für diese maximierte Ansicht mit der maximizedWidgetId auf der Benutzeroberfläche.

Solange Sie $ location (dies ist nur ein Wrapper über dem nativen Standortobjekt) verwenden, um den Pfad zu aktualisieren, wird die Ansicht aktualisiert.

Sivakumar Kailasam
quelle
1
Nicht nur $ location aktualisiert die Ansicht. ng-include wird auch, ohne $ location zu ändern.
OZ_
@OZ_ Ich habe ngInclude nicht vorgeschlagen, da dies nur eine Statusänderung innerhalb einer Ansicht ist. Ich schlage lediglich wahrscheinlich so etwas wie ng-if vor, das mit einer Funktion verbunden wäre, die routeParams
Sivakumar Kailasam
0

Ich habe eine Idee zu verwenden

window.history.replaceState ('Objekt', 'Titel', '/ neue URL');

Wenn Sie dies tun und ein Verdauungszyklus stattfindet, werden die Dinge völlig durcheinander gebracht. Wenn Sie es jedoch auf die richtige URL zurücksetzen, erwartet Angular, dass es in Ordnung ist. Theoretisch könnten Sie also die richtige URL speichern, die Angular erwartet, und sie zurücksetzen, bevor Sie wissen, dass ein Digest ausgelöst wird.

Ich habe das allerdings nicht getestet.

Keegan 82
quelle
-2

Mit dem folgenden Code können Sie die URL ohne Umleitung ändern, z . B.: Http: // localhost / # / 691? Foo? Bar? Blabla

for(var i=0;i<=1000;i++) $routeProvider.when('/'+i, {templateUrl: "tabPages/"+i+".html",reloadOnSearch: false});

Wenn Sie jedoch zu http: // localhost / # / 692 wechseln , werden Sie umgeleitet.

ABC
quelle
Ich verstehe nicht, warum ich hier eine weitere Antwort hinzufüge.
Gsamaras
1
Es ist eine Notiz zur Geschichte.
abc