Come implementare history.back () in angular.js


191

Ho una direttiva che è l'intestazione del sito con il pulsante Indietro e voglio fare clic su per tornare alla pagina precedente. Come lo faccio in modo angolare?

Ho provato:

<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>

e questa è la direttiva js:

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

ma non succede nulla. Ho cercato nell'API angular.js circa $ location ma non ho trovato nulla sul pulsante Indietro o history.back().


1
Hai detto che questo ha funzionato per te. Ti porta a pagine diverse all'interno della tua app o semplicemente il browser torna indietro? Sembra che mi risponda al browser.
Chookoos,

Se hai impostato AngularJS per utilizzare la modalità HTML5, andando su qualsiasi pagina già nella cronologia del browser verrà utilizzata la versione memorizzata nella cache e non ricaricata. Il progetto a cui sto lavorando utilizza una combinazione di vecchio e nuovo codice e la pagina precedente cambia dopo che i dati sono stati salvati con AngularJS. Non è un'opzione per aggiornare la prima pagina per utilizzare AngularJS, quindi ho dovuto caricare una terza pagina non AngularJS per reindirizzare alla prima. Non è una bella soluzione, ma funziona.
CJ Dennis,

Risposte:


262

È necessario utilizzare una funzione di collegamento nella direttiva:

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

Vedi jsFiddle .


Ma ho 2 pulsanti nella mia intestazione uno per home e uno per back se capisco il tuo codice l'elemento nella funzione link è l'elemento che è stato cliccato nella case history.back si applicherà anche per il pulsante home? (Che non va bene )
baba-dev,

Ho cambiato un po 'l'esempio. Ora ci sono due pulsanti (avanti e indietro). Ora utilizza jQuery, il che significa che scope. $ Apply () è necessario al clic.
asgoth,

8
Questo codice non è testabile, dovresti davvero usare l'oggetto "$ window" invece di "window".
Arbitro

Funziona con IE8? Non credo che abbia una storia
Neil,

5
@Neil, Angular non supporta IE8 con orgoglio . Quindi no.
Rap

133

I percorsi angolari osservano la posizione del browser, quindi semplicemente usando window.history.back() facendo clic su qualcosa funzionerebbe.

HTML:

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

JS:

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

Di solito creo una funzione globale chiamata '$ back' sul mio controller di app, che di solito metto sul tag body.

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

Quindi ovunque nella mia app posso solo fare <a ng-click="$back()">Back</a>

(Se si desidera che sia più testabile, iniettare il servizio $ window nel controller e utilizzare $window.history.back()).


9
Consiglio di non mettere nulla in una "funzione globale". Ci sono molte cose che possono accadere allo stato globale . In questo caso è principalmente la volatilità di esso. Il codice di terze parti (o di un altro sviluppatore, se fai parte di una grande squadra), per esempio, una direttiva o un servizio potrebbe facilmente modificare il $ scope. $ Back per i suoi figli. Che potrebbe essere difficile da eseguire il debug. È sicuramente una buona pratica iniettare un servizio in ciascun componente ed esporre la funzionalità dove necessario. L'esempio è solo "globale per l'app", ma c'è rischio
Ben Lesh,

Fonte: ho avuto cose che ho bloccato in un'app "globale" $ scope mi ha morso troppe volte per contare, e ho smesso di usare quella tecnica a favore dei servizi. Che può ancora essere calpestato, ma è molto più facile uscire.
Ben Lesh,

65

Utilizzare idealmente una semplice direttiva per mantenere i controller liberi da $ window ridondante

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

Usa così:

<button back>Back</button>

Sono contento che tu abbia mostrato la dipendenza $ window - questo è importante.
Chris Smith,

20

Un'altra soluzione piacevole e riutilizzabile è quella di creare una direttiva come questa :

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

quindi usalo così:

<a href back-button>back</a>

1
Sembra funzionare una volta riordinato il curly di chiusura e rinominato la direttiva e l'elemento attr per abbinarsi l'un l'altro.
rimessa in servizio il

18

Nel caso sia utile ... Stavo colpendo le "10 $ digest () iterazioni raggiunte. Interruzione!" errore durante l'utilizzo di $ window.history.back (); con IE9 (funziona bene con altri browser ovviamente).

Ho funzionato usando:

setTimeout(function() {
  $window.history.back();
},100);

Altre risposte fanno uso di pianura window. Sembra che tu stia utilizzando il $windowservizio angolare. Forse questa è la causa principale?
superjos

7
Ho avuto lo stesso errore in IE9 e questo ha risolto il problema. Vedi github.com/angular/angular.js/issues/1417 Ha ragione sull'uso di $ window, tutte le altre risposte sono "sbagliate" su questo punto, vedi docs.angularjs.org/api/ng.$window
tanguy_k

Qualche idea sul perché 100ms? È un bel ritardo, funziona con meno?
Kevin,

@Kevin I 100ms erano solo una durata che pensavo fosse ragionevole e che non si notava. In effetti un ritardo minore potrebbe funzionare.
Rob Bygrave,

Ottengo problemi simili nell'ultimo Chrome quando utilizzo la navigazione predefinita Angular nella mia app e il ritardo non aiuta neanche. Solo la disabilitazione della gestione della navigazione di Angular ha aiutato.
Domi,

3

Oppure puoi semplicemente usare codice :

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

Piace:

<a class="back" ng-class="icons">
   <img src="../media/icons/right_circular.png" onClick="javascript:history.go(-1);" />
</a>

1
questo sembra sbagliato su così tanti livelli, cfr. questo post sul blog di quasi 10 anni fa
Rocco

1

Si è verificato un errore di sintassi. Prova questo e dovrebbe funzionare:

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

1

Angolare 4:

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

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

  constructor(private location: Location) { } 

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

0

Per me, il mio problema era che dovevo tornare indietro e poi passare a un altro stato. Quindi l'utilizzo $window.history.back()non ha funzionato perché per qualche motivo la transizione è avvenuta prima che history.back () si sia verificato, quindi ho dovuto concludere la mia transizione in una funzione di timeout in questo modo.

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

Questo risolto il mio problema.


0

In AngularJS2 ho trovato un nuovo modo, forse è la stessa cosa ma in questa nuova versione:

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

(...)

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

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

Dopo la mia funzione, posso vedere che la mia applicazione sta andando alla posizione d'uso della pagina precedente da angular2 / router.

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


Funziona, devi importarlo da @ angular / common, non @ angular / router.
plesso,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.