So implementieren Sie history.back () in angle.js

190

Ich habe eine Direktive, bei der es sich um einen Site-Header mit der Schaltfläche "Zurück" handelt, und ich möchte mit einem Klick zur vorherigen Seite zurückkehren. Wie mache ich das im Winkel?

Ich habe versucht:

<header class="title">
<a class="back" ng-class="icons"><img src="../media/icons/right_circular.png" ng-click="history.back()" /></a>
<h1>{{title}}</h1>
<a href="/home" class="home" ng-class="icons"><img src="../media/icons/53-house.png" /></a>   
</header>

und das ist die richtlinie js:

myApp.directive('siteHeader', function () {
    return {
        restrict: 'E',
        templateUrl: 'partials/siteHeader.html',
        scope: {
            title: '@title',
            icons: '@icons'
        }
    };
});

aber nichts passiert. Ich habe in der angular.js-API nach $ location gesucht , aber nichts über back button oder gefunden history.back().

baba-dev
quelle
1
Sie haben erwähnt, dass dies für Sie funktioniert hat. Führt es Sie zu verschiedenen Seiten in Ihrer App oder kehrt der Browser zurück? Es sieht so aus, als würde es mir den Browser zurückgeben.
Chookoos
Wenn Sie AngularJS auf den HTML5-Modus eingestellt haben, wird beim Aufrufen einer Seite, die sich bereits im Browserverlauf befindet, die zwischengespeicherte Version verwendet und nicht neu geladen. Das Projekt, an dem ich arbeite, verwendet eine Mischung aus altem und neuem Code. Die vorherige Seite ändert sich, nachdem die Daten mit AngularJS gespeichert wurden. Es ist keine Option, die erste Seite zu aktualisieren, um AngularJS zu verwenden, daher musste ich eine dritte Seite laden, die nicht AngularJS ist, um zur ersten Seite umzuleiten. Keine schöne Lösung, aber es funktioniert.
CJ Dennis

Antworten:

262

Sie müssen eine Link-Funktion in Ihrer Direktive verwenden:

link: function(scope, element, attrs) {
     element.on('click', function() {
         $window.history.back();
     });
 }

Siehe jsFiddle .

Asgoth
quelle
Aber ich habe 2 Schaltflächen in meiner Kopfzeile, eine für Home und eine für Back. Wenn ich Ihren Code verstehe, ist das Element in der Link-Funktion das Element, auf das in diesem Fall angeklickt wurde. Backback gilt auch für Home-Schaltflächen? (Was nicht gut ist )
Baba-Dev
Ich habe das Beispiel ein wenig geändert. Jetzt gibt es zwei Tasten (vor und zurück). Es verwendet jetzt jQuery, was bedeutet, dass der Bereich. $ Apply () beim Klicken benötigt wird.
Asgoth
8
Dieser Code ist nicht testbar. Sie sollten wirklich das Objekt '$ window' anstelle von 'window' verwenden.
Schiedsrichter
Funktioniert das mit IE8? Ich glaube nicht, dass es Geschichte hat
Neil
5
@Neil, Angular unterstützt IE8 stolz nicht. Also nein.
Rap
133

Winkelrouten überwachen den Standort des Browsers. window.history.back()Wenn Sie also einfach auf etwas klicken, funktioniert dies.

HTML:

<div class="nav-header" ng-click="doTheBack()">Reverse!</div>

JS:

$scope.doTheBack = function() {
  window.history.back();
};

Normalerweise erstelle ich auf meinem App-Controller eine globale Funktion namens '$ back', die ich normalerweise auf das Body-Tag setze.

angular.module('myApp').controller('AppCtrl', ['$scope', function($scope) {
  $scope.$back = function() { 
    window.history.back();
  };
}]);

Dann kann ich überall in meiner App einfach machen <a ng-click="$back()">Back</a>

(Wenn Sie möchten, dass es besser testbar ist, fügen Sie den $ window-Dienst in Ihren Controller ein und verwenden Sie ihn. $window.history.back())

Andrew Joslin
quelle
9
Ich würde empfehlen, nichts in eine "globale Funktion" zu setzen. Es gibt sehr viele Dinge, die dem globalen Staat passieren können . In diesem Fall ist es hauptsächlich die Volatilität. Code von Drittanbietern (oder einem anderen Entwickler, wenn Sie in einem großen Team sind), beispielsweise einer Direktive oder einem Dienst, kann den $ scope. $ Back für seine Kinder leicht ändern. Welches könnte schwer zu debuggen sein. Es ist definitiv besser, in jede Komponente einen Service einzufügen und die Funktionalität bei Bedarf bereitzustellen. Das Beispiel ist nur "global für die App", aber es besteht das Risiko
Ben Lesh
Quelle: Ich hatte Dinge, die ich in einer "globalen" App steckte. $ Scope hat mich zu oft gebissen, um sie zu zählen, und ich habe aufgehört, diese Technik zugunsten von Diensten zu verwenden. Was immer noch getrampelt werden kann, aber es ist viel einfacher herauszufinden.
Ben Lesh
65

Verwenden Sie im Idealfall eine einfache Anweisung, um Controller von redundanten $ -Fenstern freizuhalten

app.directive('back', ['$window', function($window) {
        return {
            restrict: 'A',
            link: function (scope, elem, attrs) {
                elem.bind('click', function () {
                    $window.history.back();
                });
            }
        };
    }]);

Verwenden Sie wie folgt:

<button back>Back</button>
Darren
quelle
Ich bin froh, dass du die $ window-Abhängigkeit gezeigt hast - das ist wichtig.
Chris Smith
20

Eine andere schöne und wiederverwendbare Lösung besteht darin, eine Richtlinie wie diese zu erstellen :

app.directive( 'backButton', function() {
    return {
        restrict: 'A',
        link: function( scope, element, attrs ) {
            element.on( 'click', function () {
                history.back();
                scope.$apply();
            } );
        }
    };
} );

dann benutze es einfach so:

<a href back-button>back</a>
Pleerock
quelle
1
Scheint zu funktionieren, wenn Sie die schließenden Locken neu anordnen und die Direktive und das Element attr so umbenennen, dass sie miteinander übereinstimmen.
Remarsh
18

Für den Fall, dass es nützlich ist ... Ich habe die "10 $ Digest () - Iterationen erreicht. Abbruch!" Fehler bei Verwendung von $ window.history.back (); mit IE9 (funktioniert natürlich auch in anderen Browsern).

Ich habe es zum Laufen gebracht mit:

setTimeout(function() {
  $window.history.back();
},100);
Rob Bygrave
quelle
Andere Antworten verwenden einfach window. Sie scheinen den $windowAngular-Dienst zu verwenden. Vielleicht ist dies die Grundursache?
Superjos
7
Ich habe den gleichen Fehler unter IE9 und dies löste das Problem. Siehe github.com/angular/angular.js/issues/1417 Er hat Recht mit der Verwendung von $ window, alle anderen Antworten sind in diesem Punkt "falsch", siehe docs.angularjs.org/api/ng.$window
tanguy_k
Irgendeine Idee warum 100ms? Das ist eine ziemliche Verzögerung, funktioniert es mit weniger?
Kevin
@ Kevin Die 100ms waren nur eine Dauer, die ich für vernünftig und imo nicht bemerkbar hielt. In der Tat könnte eine kleinere Verzögerung funktionieren.
Rob Bygrave
Ich erhalte ähnliche Probleme in Chrome, wenn ich die Angular-Standardnavigation in meiner App verwende, und die Verzögerung hilft auch nicht. Nur das Deaktivieren des Navigationsmanagements von Angular hat geholfen.
Domi
3

Oder Sie können einfach verwenden Code:

onClick="javascript:history.go(-1);"

Mögen:

<a class="back" ng-class="icons">
   <img src="../media/icons/right_circular.png" onClick="javascript:history.go(-1);" />
</a>
Arvind Kushwaha
quelle
1
das sieht auf so vielen Ebenen falsch aus, vgl. Dieser Blog-Beitrag von vor fast 10 Jahren
Rocco
1

Es ist ein Syntaxfehler aufgetreten. Versuchen Sie dies und es sollte funktionieren:

directives.directive('backButton', function(){
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('click', function () {
                history.back();
                scope.$apply();
            });
        }
    }
});
Ripan Kumar
quelle
1

Winkel 4:

/* typescript */
import { Location } from '@angular/common';
// ...

@Component({
  // ...
})
export class MyComponent {

  constructor(private location: Location) { } 

  goBack() {
    this.location.back(); // go back to previous location
  }
}
krmld
quelle
0

Für mich war mein Problem, dass ich zurück navigieren und dann in einen anderen Zustand wechseln musste. Die Verwendung $window.history.back()funktionierte also nicht, da der Übergang aus irgendeinem Grund vor history.back () erfolgte und ich meinen Übergang in eine Timeout-Funktion wie diese einschließen musste.

$window.history.back();
setTimeout(function() {
  $state.transitionTo("tab.jobs"); }, 100);

Dies hat mein Problem behoben.

deb2fast
quelle
0

In AngularJS2 habe ich einen neuen Weg gefunden, vielleicht ist es genau das Gleiche, aber in dieser neuen Version:

import {Router, RouteConfig, ROUTER_DIRECTIVES, Location} from 'angular2/router'; 

(...)

constructor(private _router: Router, private _location: Location) {}

onSubmit() {
    (...)
    self._location.back();
}

Nach meiner Funktion kann ich sehen, dass meine Anwendung von Angular2 / Router zur vorherigen Seite wechselt.

https://angular.io/docs/ts/latest/api/common/index/Location-class.html

Paul Leclerc
quelle
Es funktioniert, Sie müssen es von @ angle / common importieren, nicht von @ angle / router.
Plexus