Cara kembali ke halaman terakhir

369

Apakah ada cara cerdas untuk kembali ke halaman terakhir di Angular 2?

Sesuatu seperti

this._router.navigate(LASTPAGE);

Misalnya, halaman C memiliki Go Backtombol,

  • Halaman A -> Halaman C, klik, kembali ke halaman A.

  • Halaman B -> Halaman C, klik, kembali ke halaman B.

Apakah router memiliki informasi riwayat ini?

Hongbo Miao
sumber

Jawaban:

672

Sebenarnya Anda dapat memanfaatkan layanan Lokasi bawaan, yang memiliki API "Kembali".

Di Sini (dalam 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();
  }
}

Sunting : Seperti yang disebutkan oleh @ charith.arumapperuma Locationharus diimpor dari @angular/commonsehingga import {Location} from '@angular/common';garis ini penting.

Amir Sasson
sumber
75
Lokasi harus diimpor dari "angular2 / router" di rilis Angular 2. yang lebih lama, dalam rilis yang lebih baru, harus dari "@ angular / common".
charith.arumapperuma
2
Jika Anda memilikinya di dalam framework, saya tidak melihat alasan untuk menggunakan window "asli" ".history.back (); " yang merupakan fitur HTML5 ( developer.mozilla.org/en-US/docs/Web/API/Window/history )
Amir Sasson
7
Untuk apa nilainya, dokumentasi API Angular2 resmi untuk Locationmenyatakan: "Catatan: lebih baik menggunakan layanan Router untuk memicu perubahan rute. Gunakan Lokasi hanya jika Anda perlu berinteraksi dengan atau membuat URL yang dinormalisasi di luar perutean." Jawaban @ Sasxa rupanya menunjukkan cara yang digunakan Routeruntuk melakukan ini. Namun, Locationmetode ini jelas lebih nyaman. Adakah yang tahu mengapa Routermetode ini mungkin lebih benar daripada Locationmetode ini?
Andrew Willems
2
@Andrew: Saya mengalami masalah, bahwa Anda tidak dapat kembali dua kali, jika Anda menggunakan this.location.back (). Anda akan melompat kembali ke situs awal.
Johannes
1
@ yt61, tidak yakin, mungkin kegunaan kembali? atau jika Anda bisa mendapatkan halaman yang ditentukan dari berbagai rute, jadi Anda tidak tahu sebelumnya rute untuk kembali ke.
Amir Sasson
111

Dalam versi final Angular 2.x / 4.x - inilah dokumen 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
sumber
1
Saat menavigasi kembali ke layar sebelumnya, kita dapat mempertahankan nilai input yang dimasukkan tanpa menggunakan objek dalam layanan.
Vignesh
Bagaimana menampilkan kembali animasi saat location.back () menjalankan?
Pangkalan Salju
48

<button backButton>BACK</button>

Anda dapat menempatkan ini ke arahan, yang dapat dilampirkan ke elemen yang dapat diklik:

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();
    }
}

Pemakaian:

<button backButton>BACK</button>
hansmaad
sumber
itu luar biasa!
Rafael de Castro
1
Jika Anda me-refresh halaman ini, dan mengklik tombol yang memicu "this.location.back ()", itu hanya akan memicu refresh halaman. Apakah ada cara yang bisa dideteksi modul Lokasi jika jalur sebelumnya ada?
Henry LowCZ
pekerja yang baik! ;)
elciospy
Perlu diingat jika pengguna pergi langsung ke halaman di mana tombol Kembali ada dan jika dia mengklik tombol .. maka dia akan dibuang dari aplikasi ke halaman sebelumnya sesuai dengan riwayat browser (platform).
hastrb
Untuk pembaca masa depan, lihat dokumen API
hastrb
24

Diuji dengan Angular 5.2.9

Jika Anda menggunakan jangkar bukan tombol Anda harus membuat sebuah link yang pasif dengan href="javascript:void(0)"membuat sudut Lokasi bekerja.

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
sumber
Saya akan menyarankan membuat arahan 'clickPreventDefault' daripada menggunakan javascript:void(0). Sesuatu seperti ... @Directive({ selector: '[clickPreventDefault]' }) export class ClickPreventDefaultDirective { @HostListener("click", ["$event"]) onClick($event: Event) { $event.preventDefault(); } }
bmd
Terima kasih @bmd, ini cara yang lebih rumit tapi berhasil juga. Solusi lain yang berhasil adalah jangan gunakan herf: <a (click)="goBack()"> meskipun cara ini tidak lulus Validator HTML.
JavierFuentes
20

Anda dapat menerapkan routerOnActivate()metode pada kelas rute Anda, ini akan memberikan informasi tentang rute sebelumnya.

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

Kemudian Anda dapat menggunakan router.navigateByUrl()dan meneruskan data yang dihasilkan dari ComponentInstruction. Sebagai contoh:

this._router.navigateByUrl(prevInstruction.urlPath);
Sasxa
sumber
Apakah ini masih berlaku untuk Angular 2.1.0?
smartmouse
1
@smartmouse Saya rasa tidak, ada dokumentasi untukrouterOnActivate
Bojan Kogoj
4
Tautan routerOnActivate () dalam jawaban ini rusak. Sepertinya ini bukan cara untuk melakukannya dalam versi rilis.
rmcsharry
14

Juga berfungsi untuk saya ketika saya harus kembali seperti pada sistem file. PS @angular: "^ 5.0.0"

<button type="button" class="btn btn-primary" routerLink="../">Back</button>
Shevtsiv Andriy
sumber
7
Saya berharap ini akan berhasil, tetapi ini bergerak kembali ke Rute berikutnya di atasnya - bukan ke rute Anda sebelum menavigasi ke halaman. Baik untuk mengetahui ini ada, tetapi jika Anda memiliki beberapa titik masuk untuk komponen Anda, metode ini hanya akan pernah kembali ke rute di atasnya, bukan dari mana Anda berasal.
Scott Byers
Ketika saya menulis "ketika saya harus kembali seperti dalam sistem file" :) Bagi saya, perilaku ini juga tidak terduga.
Shevtsiv Andriy
12

Saya membuat tombol yang bisa saya gunakan kembali di mana saja di aplikasi saya.

Buat komponen ini

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();
  }
}

Kemudian tambahkan ke template apa pun saat Anda membutuhkan tombol kembali.

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

Catatan: Ini menggunakan Bahan Sudut, jika Anda tidak menggunakan perpustakaan itu maka hapus mat-buttondan color.

Todd Skelton
sumber
Apakah pendekatan ini bekerja dengan outlet bernama router? Katakanlah saya memiliki beberapa halaman dan hanya ingin kembali pada salah satunya, apakah ini akan berhasil?
rrd
Anda harus menggunakan pendekatan yang berbeda untuk situasi itu. Jika Anda memiliki tombol kembali yang sama di dua outlet router yang berbeda, mereka mungkin akan melakukan hal yang sama dan kembali ke outlet router terakhir yang diubah.
Todd Skelton
Untuk outlet bernama, saya menemukan bahwa pendekatan ini berhasil: this.router.navigate (['../'], {relatifTo: this.route})
rrd
Bagaimana cara menggunakan komponen ini di dalam komponen lain?
RN Kushwaha
12

Setelah semua jawaban yang luar biasa ini, saya harap jawaban saya menemukan seseorang dan membantu mereka. Saya menulis layanan kecil untuk melacak sejarah rute. Ini dia.

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
sumber
Setelah mencoba kurang lebih semua solusi, saya menemukan ini adalah cara yang lebih konsisten untuk melakukan itu
A. D'Alfonso
Bagaimana jika saya membuka halaman pada tautan tertentu dan saya ingin itu akan kembali ke halaman yang ada di halaman pohon?
Ivan
8

Cara saya melakukannya saat menavigasi ke halaman lain menambahkan param kueri dengan melewati lokasi saat ini

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

Baca param kueri ini di komponen Anda

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

Jika returnUrl hadir, aktifkan tombol kembali dan ketika pengguna mengklik tombol kembali

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

Ini harus dapat menavigasi ke halaman sebelumnya. Alih-alih menggunakan location.back saya merasa metode di atas lebih aman mempertimbangkan kasus di mana pengguna langsung mendarat ke halaman Anda dan jika ia menekan tombol kembali dengan location.back akan mengarahkan pengguna ke halaman sebelumnya yang tidak akan menjadi halaman web Anda.

Puneeth Rai
sumber
Perlu mengimpor ActivatedRoute dan menggunakannya sebagai pengganti Router pada langganan queryParams (misalnya, this.route.queryParams.subscribe), tetapi sebaliknya, tampaknya berfungsi!
Stephen Kaiser
bagi saya itu bekerja dengan baik dengan router itu sendiri bahkan di sudut 4
Puneeth Rai
1
Jawaban terbaik, tetapi dalam Angular 5 (hingga x?) Anda perlu menyuntikkan objek "ActivatedRoute" dan menggunakan queryParams pada objek ini, seperti yang sudah dinyatakan oleh Stephen Kaiser.
Satria
8

Di RC4:

import {Location} from '@angular/common';
Tomasz Bielawa
sumber
3

Untuk kembali tanpa menyegarkan halaman, Kita bisa melakukannya dalam html seperti di bawah ini javascript: history.back ()

<a class="btn btn-danger" href="javascript:history.back()">Go Back</a>
Singhak
sumber
Saya akan merekomendasikan menggunakan Locationlayanan sebagai gantinya. API resmi
hastrb
2

Sejak beta 18:

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

Albert
sumber
2

Solusi lain

window.history.back();

Džan Operta
sumber
Bekerja untuk saya location.back () juga berfungsi tetapi tidak saya kompilasi dengan --prod
Alex