Jak zaimplementować history.back () w angular.js


191

Mam dyrektywę, która jest nagłówkiem strony z przyciskiem Wstecz i chcę po kliknięciu wrócić do poprzedniej strony. Jak to zrobić w sposób kątowy?

Próbowałem:

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

a to jest dyrektywa js:

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

ale nic się nie dzieje. Zajrzałem do interfejsu API angular.js o $ location, ale nie znalazłem nic o przycisku Wstecz lub history.back().


1
Wspomniałeś, że to działało dla ciebie. Czy to prowadzi do różnych stron w Twojej aplikacji, czy po prostu przywraca przeglądarkę? Wygląda na to, że zwraca mi przeglądarkę.
Chookoos,

Jeśli ustawiłeś AngularJS na używanie trybu HTML5, przejście na dowolną stronę już w historii przeglądarki użyje wersji buforowanej i nie przeładuje jej. Projekt, nad którym pracuję, wykorzystuje mieszankę starego i nowego kodu, a poprzednia strona zmienia się po zapisaniu danych w AngularJS. To nie jest opcja uaktualnienia pierwszej strony do korzystania z AngularJS, więc musiałem załadować trzecią stronę inną niż AngularJS, aby przekierować z powrotem na pierwszą. Nie jest to miłe rozwiązanie, ale działa.
CJ Dennis,

Odpowiedzi:


262

Musisz użyć funkcji link w swojej dyrektywie:

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

Zobacz jsFiddle .


Ale mam dwa przyciski w nagłówku, jeden dla domu i jeden dla tyłu, jeśli rozumiem twój kod, element w funkcji linku to element, który został kliknięty w historii spraw. Powrót będzie dotyczył również przycisku home? (Co nie jest dobre )
baba-dev

Trochę zmieniłem przykład. Teraz są dwa przyciski (wstecz i do przodu). Teraz używa jQuery, co oznacza zakres. $ Apply () jest potrzebne po kliknięciu.
asgoth 28.12.12

8
Ten kod jest nie do przetestowania, naprawdę powinieneś użyć obiektu „$ window” zamiast „window”.
Arbiter,

Czy to działa z IE8? Nie wierzę, że ma historię
Neil,

5
@Neil, Angular z dumą nie obsługuje IE8. Więc nie.
Rap

133

Kątowe trasy śledzą lokalizację przeglądarki, więc po prostu window.history.back()kliknięcie czegoś by działało.

HTML:

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

JS:

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

Zwykle tworzę funkcję globalną o nazwie „$ back” na kontrolerze aplikacji, którą zwykle umieszczam na tagu body.

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

W takim razie gdziekolwiek w mojej aplikacji mogę po prostu zrobić <a ng-click="$back()">Back</a>

(Jeśli chcesz, aby był bardziej testowalny, wstrzyknij usługę $ window do kontrolera i użyj $window.history.back()).


9
Odradzam umieszczanie czegokolwiek w „funkcji globalnej”. Jest bardzo wiele rzeczy, które mogą przytrafić się stanowi globalnemu . W tym przypadku jest to głównie zmienność. Kod pochodzący od strony trzeciej (lub innego programisty, jeśli pracujesz w dużym zespole), powiedzmy, dyrektywa lub usługa mogą łatwo zmodyfikować zakres $. $ Z powrotem dla jego dzieci. Co może być trudne do debugowania. Zdecydowanie lepszą praktyką jest wstrzykiwanie usługi do każdego komponentu i udostępnianie funkcjonalności tam, gdzie jest to konieczne. Przykład jest tylko „globalny dla aplikacji”, ale istnieje ryzyko
Ben Lesh

Źródło: Miałem rzeczy, które utknąłem w zasięgu globalnej aplikacji, gryzą mnie zbyt wiele razy, aby liczyć, i przestałem używać tej techniki na rzecz usług. Które wciąż można podeptać, ale o wiele łatwiej jest je przekopać.
Ben Lesh

65

Idealnie użyj prostej dyrektywy, aby utrzymać kontrolery wolne od zbędnego okna $

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

Użyj w ten sposób:

<button back>Back</button>

Cieszę się, że pokazałeś zależność od okna - to ważne.
Chris Smith

20

Kolejną miłą i wielokrotnego użytku rozwiązaniem jest utworzenie dyrektywę jak to :

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

użyj tego w następujący sposób:

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

1
Wydaje się, że zadziała po zmianie kolejności zamykających nawiasów i zmianie nazwy dyrektywy i elementu attr, aby pasowały do ​​siebie.
remarsh

18

W przypadku, gdy jest to przydatne ... Uderzyłem w „Osiągnięto iteracje 10 $ digest (). Przerwanie!” błąd podczas korzystania z $ window.history.back (); z IE9 (działa oczywiście w innych przeglądarkach).

Mam go do pracy przy użyciu:

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

Inne odpowiedzi wykorzystują zwykły window. Wygląda na to, że korzystasz z $windowusługi Angular. Może to jest podstawowa przyczyna?
superjos,

7
Mam ten sam błąd w IE9 i to rozwiązało problem. Zobacz github.com/angular/angular.js/issues/1417 Ma rację, używając $ window, wszystkie inne odpowiedzi są w tym punkcie „błędne”, patrz docs.quarejs.org/api/ng.$window
tanguy_k

Masz pomysł, dlaczego 100ms? To dość opóźnienie, czy działa mniej?
Kevin

@Kevin The 100ms to tylko czas, który uważałem za rozsądny i nie jestem zauważalny. Rzeczywiście może działać mniejsze opóźnienie.
Rob Bygrave,

Podobne problemy występują w najnowszym Chrome podczas korzystania z domyślnej nawigacji Angular w mojej aplikacji, a opóźnienie też nie pomoże. Pomogło tylko wyłączenie zarządzania nawigacją Angulara.
Domi

3

Lub możesz po prostu użyć kod :

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

Lubić:

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

1
wygląda to źle na tak wielu poziomach, por. ten post na blogu sprzed prawie 10 lat
Rocco,

1

Wystąpił błąd składniowy. Spróbuj tego i powinno działać:

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

1

Kątowy 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

Dla mnie moim problemem było to, że musiałem nawigować wstecz, a następnie przejść do innego stanu. Tak więc używanie $window.history.back()nie działało, ponieważ z jakiegoś powodu przejście miało miejsce przed historią.back (), więc musiałem zawinąć swoje przejście w funkcję limitu czasu.

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

To naprawiło mój problem.


0

W AngularJS2 znalazłem nowy sposób, może to jest to samo, ale w tej nowej wersji:

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

(...)

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

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

Po mojej funkcji widzę, że moja aplikacja przechodzi do poprzedniej strony z lokalizacją usgin z angular2 / routera.

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


Działa, musisz go zaimportować z @ angular / common, a nie @ angular / router.
splot
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.