Jak wrócić na ostatnią stronę

366

Czy istnieje sprytny sposób na powrót do ostatniej strony w Angular 2?

Coś jak

this._router.navigate(LASTPAGE);

Na przykład strona C ma Go Backprzycisk,

  • Strona A -> Strona C, kliknij ją, wróć do strony A.

  • Strona B -> Strona C, kliknij ją, wróć do strony B.

Czy router ma tę historię?

Hongbo Miao
źródło

Odpowiedzi:

669

W rzeczywistości możesz skorzystać z wbudowanej usługi lokalizacji, która posiada interfejs API „Wstecz”.

Tutaj (w TypeScript):

import {Component} from '@angular/core';
import {Location} from '@angular/common';

@Component({
  // component's declarations here
})
class SomeComponent {

  constructor(private _location: Location) 
  {}

  backClicked() {
    this._location.back();
  }
}

Edytować : Jak wspomniano przez @ charith.arumapperuma Locationnależy zaimportować z, @angular/commonwięc import {Location} from '@angular/common';linia jest ważna.

Amir Sasson
źródło
75
Lokalizacja powinna zostać zaimportowana z „angular2 / router” w starszych wersjach Angular 2. W nowszych wersjach powinna być z „@ angular / common”.
charith.arumapperuma
2
Jeśli masz to wbudowane w ramach, nie widzę żadnego powodu, aby używać „native” „window.history.back ();” która jest funkcją HTML5 ( developer.mozilla.org/en-US/docs/Web/API/Window/history )
Amir Sasson
7
Jeśli chodzi o to, co jest warte, oficjalna dokumentacja Angular2 API dla Locationstanów stwierdza: „Uwaga: lepiej jest użyć usługi routera, aby wywołać zmiany trasy. Użyj lokalizacji tylko wtedy, gdy musisz wchodzić w interakcje lub tworzyć znormalizowane adresy URL poza routingiem”. Odpowiedź @ Sasxa najwyraźniej pokazuje sposób, aby Routerto zrobić. Jednak Locationmetoda jest zdecydowanie wygodniejsza. Czy ktoś wie, dlaczego Routermetoda może być bardziej poprawna niż Locationmetoda?
Andrew Willems,
2
@Andrew: napotkałem problem polegający na tym, że nie możesz wrócić dwa razy, jeśli użyjesz this.location.back (). Wrócisz do początkowej strony.
Johannes,
1
@ yt61, nie jestem pewien, może ponowne użycie? lub jeśli możesz dotrzeć do określonej strony z różnych tras, więc nie znasz z góry trasy, do której chcesz wrócić.
Amir Sasson
111

W ostatecznej wersji Angular 2.x / 4.x - oto dokumentacja https://angular.io/api/common/Location

/* typescript */

import { Location } from '@angular/common';
// import stuff here

@Component({
// declare component here
})
export class MyComponent {

  // inject location into component constructor
  constructor(private location: Location) { }

  cancel() {
    this.location.back(); // <-- go back to previous location on cancel
  }
}
Hinrich
źródło
1
Wracając do poprzedniego ekranu, możemy zachować wprowadzone wartości bez użycia obiektu w serwisie.
Vignesh
Jak wyświetlić animację z powrotem podczas wykonywania location.back ()?
Snow Bases
48

<button backButton>BACK</button>

Możesz umieścić to w dyrektywie, którą można dołączyć do dowolnego klikalnego elementu:

import { Directive, HostListener } from '@angular/core';
import { Location } from '@angular/common';

@Directive({
    selector: '[backButton]'
})
export class BackButtonDirective {
    constructor(private location: Location) { }

    @HostListener('click')
    onClick() {
        this.location.back();
    }
}

Stosowanie:

<button backButton>BACK</button>
hansmaad
źródło
to cudownie!
Rafael de Castro,
1
Jeśli odświeżysz tę stronę i klikniesz przycisk, który wyzwala „this.location.back ()”, spowoduje to tylko odświeżenie strony. Czy jest jakiś sposób, aby moduł lokalizacji mógł wykryć, czy istnieje poprzednia ścieżka?
Henry LowCZ
dobra robota człowieku! ;)
elciospy
Pamiętaj, że jeśli użytkownik przejdzie bezpośrednio na stronę, na której istnieje przycisk Wstecz, a jeśli kliknie przycisk .., zostanie on wyrzucony z aplikacji na poprzednią stronę zgodnie z historią przeglądarki (platformy).
hastrb
Dla przyszłych czytelników
zapoznaj się z
23

Testowane z użyciem kątownika 5.2.9

Jeśli używasz kotwicę zamiast przycisku musisz zrobić to pasywny związek z href="javascript:void(0)"aby kątowa miejsce pracy.

app.component.ts

import { Component } from '@angular/core';
import { Location } from '@angular/common';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent {

  constructor( private location: Location ) { 
  }

  goBack() {
    // window.history.back();
    this.location.back();

    console.log( 'goBack()...' );
  }
}

app.component.html

<!-- anchor must be a passive link -->
<a href="javascript:void(0)" (click)="goBack()">
  <-Back
</a>
JavierFuentes
źródło
Sugerowałbym utworzenie dyrektywy „clickPreventDefault” zamiast używania javascript:void(0). Coś w stylu ... @Directive({ selector: '[clickPreventDefault]' }) export class ClickPreventDefaultDirective { @HostListener("click", ["$event"]) onClick($event: Event) { $event.preventDefault(); } }
bmd
Dziękuję @bmd, jest to bardziej skomplikowany sposób, ale także działa. Innym działającym rozwiązaniem jest nieużywanie herf: <a (kliknięcie )="goBack()"> chociaż w ten sposób nie przechodzą walidatory HTML.
JavierFuentes
20

Możesz zaimplementować routerOnActivate()metodę na swojej klasie trasy, która dostarczy informacji o poprzedniej trasie.

routerOnActivate(nextInstruction: ComponentInstruction, prevInstruction: ComponentInstruction) : any

Następnie możesz używać router.navigateByUrl()i przekazywać dane wygenerowane z ComponentInstruction. Na przykład:

this._router.navigateByUrl(prevInstruction.urlPath);
Sasxa
źródło
Czy nadal obowiązuje to dla Angular 2.1.0?
smartmouse
1
@smartmouse Nie sądzę, istnieje dokumentacjarouterOnActivate
Bojan Kogoj
4
Link routerOnActivate () w tej odpowiedzi jest uszkodzony. Wydaje się, że nie jest to sposób, aby to zrobić w wersji.
rmcsharry
14

Pracuj także dla mnie, gdy muszę cofnąć się jak w systemie plików. PS @ prostokątny: „^ 5.0.0”

<button type="button" class="btn btn-primary" routerLink="../">Back</button>
Shevtsiv Andriy
źródło
7
Miałem nadzieję, że to zadziała, ale przenosi się z powrotem do następnej Trasy nad nią - nie do trasy, którą byłeś przed przejściem do strony. Dobrze wiedzieć, że istnieje, ale jeśli masz wiele punktów wejścia dla swojego komponentu, ta metoda zawsze wróci tylko do trasy nad nią, a nie od miejsca, z którego się wywodzisz.
Scott Byers,
Kiedy piszę „kiedy muszę wrócić jak w systemie plików” :) Dla mnie to zachowanie było również nieoczekiwane.
Shevtsiv Andriy
12

Zrobiłem przycisk, którego mogę użyć ponownie w dowolnym miejscu w mojej aplikacji.

Utwórz ten komponent

import { Location } from '@angular/common';
import { Component, Input } from '@angular/core';

@Component({
    selector: 'back-button',
    template: `<button mat-button (click)="goBack()" [color]="color">Back</button>`,
})
export class BackButtonComponent {
    @Input()color: string;

  constructor(private location: Location) { }

  goBack() {
    this.location.back();
  }
}

Następnie dodaj go do dowolnego szablonu, gdy potrzebujesz przycisku Wstecz.

<back-button color="primary"></back-button>

Uwaga: używa to materiału kątowego, jeśli nie korzystasz z tej biblioteki, usuń mat-buttoni color.

Todd Skelton
źródło
Czy to podejście działa jednak z nazwanymi gniazdami routera? Powiedzmy, że mam kilka na stronie i chcę wrócić tylko na jednym z nich, czy to zadziała?
RRD
W tej sytuacji będziesz musiał zastosować inne podejście. Jeśli miałeś ten sam przycisk powrotu w dwóch różnych gniazdach routera, prawdopodobnie oba zrobią to samo i wrócą do ostatniego gniazda routera, które zostało zmienione.
Todd Skelton
Dla wymienionych wylotów, okazało się, że takie podejście działa: this.router.navigate ([ '../'], {relativeTo: this.route})
rrD
Jak korzystać z tego komponentu w innym komponencie?
RN Kushwaha
12

Po tych wszystkich niesamowitych odpowiedziach mam nadzieję, że moja odpowiedź znajdzie kogoś i pomoże mu. Napisałem małą usługę, aby śledzić historię trasy. Oto jest.

import { Injectable } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { filter } from 'rxjs/operators';

@Injectable()
export class RouteInterceptorService {
  private _previousUrl: string;
  private _currentUrl: string;
  private _routeHistory: string[];

  constructor(router: Router) {
    this._routeHistory = [];
    router.events
      .pipe(filter(event => event instanceof NavigationEnd))
      .subscribe((event: NavigationEnd) => {
        this._setURLs(event);
      });
  }

  private _setURLs(event: NavigationEnd): void {
    const tempUrl = this._currentUrl;
    this._previousUrl = tempUrl;
    this._currentUrl = event.urlAfterRedirects;
    this._routeHistory.push(event.urlAfterRedirects);
  }

  get previousUrl(): string {
    return this._previousUrl;
  }

  get currentUrl(): string {
    return this._currentUrl;
  }

  get routeHistory(): string[] {
    return this._routeHistory;
  }
}
Anjil Dhamala
źródło
Po wypróbowaniu mniej więcej wszystkich rozwiązań, uważam, że jest to bardziej spójny sposób
A. D'Alfonso
Co się stanie, jeśli otworzę stronę pod danym linkiem i chcę, aby wróciła do strony tej w drzewie strony?
Ivan
8

Sposób, w jaki to zrobiłem, przechodząc do innej strony, dodaje parametr zapytania, przekazując bieżącą lokalizację

this.router.navigate(["user/edit"], { queryParams: { returnUrl: this.router.url }

Przeczytaj ten parametr zapytania w swoim komponencie

this.router.queryParams.subscribe((params) => {
    this.returnUrl = params.returnUrl;
});

Jeśli returnUrl jest obecny, włącz przycisk Wstecz i gdy użytkownik kliknie przycisk Wstecz

this.router.navigateByUrl(this.returnUrl); // Hint taken from Sasxa

Powinno to umożliwić przejście do poprzedniej strony. Zamiast korzystać z location.back uważam, że powyższa metoda jest bezpieczniejsza, rozważ przypadek, w którym użytkownik bezpośrednio wyląduje na Twojej stronie, a jeśli naciśnie przycisk Wstecz z location.back, przekieruje użytkownika do poprzedniej strony, która nie będzie Twoją stroną internetową.

Puneeth Rai
źródło
Musisz zaimportować ActivatedRoute i użyć go zamiast routera w subskrypcji queryParams (np. This.route.queryParams.subscribe), ale poza tym wydaje się, że działa!
Stephen Kaiser,
dla mnie działa dobrze z samym routerem nawet w kanciastym 4
Puneeth Rai
1
Najlepsza odpowiedź, ale w Angular 5 (do x?) Musisz wstrzyknąć obiekt „ActivatedRoute” i użyć queryParams na tym obiekcie, jak już stwierdził Stephen Kaiser.
Satria
8

W RC4:

import {Location} from '@angular/common';
Tomasz Bielawa
źródło
3

Aby wrócić bez odświeżania strony, możemy to zrobić w html jak poniżej javascript: history.back ()

<a class="btn btn-danger" href="javascript:history.back()">Go Back</a>
Singhak
źródło
LocationZamiast tego poleciłbym skorzystanie z usługi. oficjalne API
hastrb
2

Od wersji beta 18:

import {Location} from 'angular2/platform/common';

Albert
źródło
2

Inne rozwiązanie

window.history.back();

Džan Operta
źródło
Działa dla mnie location.back () również działa, ale nie kompiluję z --prod
Alex