เปลี่ยนพารามิเตอร์เส้นทางโดยไม่ต้องโหลดซ้ำใน Angular 2


115

ฉันกำลังสร้างเว็บไซต์อสังหาริมทรัพย์โดยใช้ Angular 2, Google Maps ฯลฯ และเมื่อผู้ใช้เปลี่ยนศูนย์กลางของแผนที่ฉันจะทำการค้นหา API ที่ระบุตำแหน่งปัจจุบันของแผนที่รวมทั้งรัศมี สิ่งนี้คือฉันต้องการสะท้อนค่าเหล่านั้นใน url โดยไม่ต้องโหลดซ้ำทั้งหน้า เป็นไปได้หรือไม่ ฉันพบวิธีแก้ปัญหาบางอย่างโดยใช้ AngularJS 1.x แต่ไม่มีอะไรเกี่ยวกับ Angular 2


ฉันคิดว่าถ้าคุณใช้ [routerLink] = "['/ route', {param1: value1}] มันจะไม่โหลดหน้านี้ซ้ำ
Toolkit

แต่ฉันจะเพิ่มพารามิเตอร์การค้นหาอื่นได้อย่างไร
Toolkit

2
☝️จะทำให้เกิดการโหลดหน้าซ้ำ
LifterCoder

โปรดทราบว่าหากคุณใช้ SSR เพื่อทำให้เว็บไซต์ของคุณเข้ากันได้กับ SEO นี่เป็นปัญหาที่น่าสงสัย
Jonathan

@ โจนาธานเหรอ? เนื่องจาก Angular เข้ามาแทนที่การกำหนดเส้นทางเมื่อมีการแสดงผลเพจแบบคงที่ฉันคิดว่ามันยังคงเป็นคำถามที่ถูกต้องแม้ว่าจะใช้ SSR ก็ตาม
adam0101

คำตอบ:


92

คุณสามารถใช้location.go(url)ซึ่งโดยพื้นฐานแล้วจะเปลี่ยน url ของคุณโดยไม่เปลี่ยนเส้นทางการสมัคร

โปรดทราบว่าสิ่งนี้อาจทำให้เกิดผลกระทบอื่น ๆ เช่นการเปลี่ยนเส้นทางไปยังเส้นทางลูกจากเส้นทางปัจจุบัน

คำถามที่เกี่ยวข้องซึ่งอธิบายว่าlocation.goจะไม่เกี่ยวข้องกับRouterการเปลี่ยนแปลงที่เกิดขึ้น


2
เส้นทางของฉันมีพารามิเตอร์ชื่อ 'ค้นหา' ซึ่งได้รับฟิลด์การค้นหาเวอร์ชันซีเรียลไลซ์เมื่อสถานะรายการโหลดขึ้นเป็นครั้งแรกฉันอ่านพารามิเตอร์เหล่านั้นโดยใช้ this._routeParams.get ('search'), deserialize ตัวกรอง และทำการค้นหา หากผู้ใช้เปลี่ยนช่องค้นหาไม่ว่าจะโดยใช้แผนที่หรือแง่มุมการค้นหาฉันก็แค่สร้าง URL ที่ถูกต้องโดยใช้วิธีการสร้างคำสั่ง var ของเราเตอร์ = this._router.generate (['รายการ', {search: serializedFields}] ) จากนั้นใช้ this._location.go (instruction.urlPath) เพื่อแก้ไข url โดยไม่ต้องโหลดสถานะซ้ำ
Marcos Basualdo

20
หากมีใครสงสัยให้นำเข้า {Location} จาก "angular2 / platform / common";
Kesarion

18
import { Location } from '@angular/common';ใน Angular 4
tehCivilian

2
คุณปฏิเสธผู้สร้างเช่นconstructor(private location: Location){ }
Pankaj Parkar

2
@AdrianE ปัญหาเป็นส่วนใหญ่อาจที่คุณพิมพ์ลงในขณะที่คุณควรจะได้พิมพ์location.go() this.location.go()เมื่อคุณปล่อยthis.คุณจะเรียกใช้อินเทอร์เฟซตำแหน่งของ typescript
georg-un

95

ใน RC6 คุณสามารถทำสิ่งต่อไปนี้เพื่อเปลี่ยน URL โดยไม่ต้องเปลี่ยนสถานะและด้วยเหตุนี้จึงรักษาประวัติเส้นทางของคุณ

    import {OnInit} from '@angular/core';

    import {Location} from '@angular/common'; 
    // If you dont import this angular will import the wrong "Location"

    @Component({
        selector: 'example-component',
        templateUrl: 'xxx.html'
    })
    export class ExampleComponent implements OnInit {
        
        constructor( private location: Location )
        {}

        ngOnInit() {    
            this.location.replaceState("/some/newstate/");
        }
    }

สิ่งนี้ไม่ได้ผลสำหรับฉัน มันพยายามที่จะโหลดเส้นทาง ข้อผิดพลาดของคอนโซล:Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'some/newstate'
Inigo

2
รวมสิ่งนี้เข้ากับการสร้าง url ตามที่ @golfadas แนะนำและเรามีผู้ชนะ!
crowmagnumb

63

ใช้location.go(url)เป็นวิธีที่จะไป แต่แทนที่จะ hardcoding URL router.createUrlTree()ให้พิจารณาการสร้างโดยใช้

ระบุว่าคุณต้องการทำการเรียกเราเตอร์ต่อไปนี้: this.router.navigate([{param: 1}], {relativeTo: this.activatedRoute})แต่หากไม่ต้องโหลดคอมโพเนนต์ซ้ำก็สามารถเขียนใหม่เป็น:

const url = this.router.createUrlTree([], {relativeTo: this.activatedRoute, queryParams: {param: 1}}).toString()

 this.location.go(url);

9
คำตอบนี้ช่วยแก้ปัญหาของฉันได้ คำถามหนึ่ง URL ที่สร้างขึ้นข้างต้นมีพารามิเตอร์ที่คั่นด้วย ";" (อัฒภาค) เราควรทำอย่างไรเพื่อแยกพารามิเตอร์แต่ละตัวในแบบสอบถามด้วย "&"?
Amarnath

2
นี่คือการประกาศ createUrlTree (คำสั่ง: any [], navigationExtras ?: NavigationExtras) คุณต้องใช้ queryParams ที่อยู่ navigationExtras ไม่ใช่ commads createUrlTree ([], {relativeTo: this.activatedRoute, queryParams: {param: 1}})
kit

เพียงเพื่อชี้แจงสิ่งที่ @kit พูดให้ทำสิ่งนี้:this.router.createUrlTree([], {relativeTo: this.activatedRoute, queryParams: {param: 1}}).toString()
bluegrounds

12

สำหรับใครก็ตามเช่นฉันที่พบว่าคำถามต่อไปนี้อาจเป็นประโยชน์

ฉันมีปัญหาที่คล้ายกันและในตอนแรกได้ลองใช้ location.go และ location.replaceState ตามที่แนะนำในคำตอบอื่น ๆ ที่นี่ อย่างไรก็ตามฉันพบปัญหาเมื่อต้องไปที่หน้าอื่นในแอปเนื่องจากการนำทางสัมพันธ์กับเส้นทางปัจจุบันและเส้นทางปัจจุบันไม่ได้รับการอัปเดตโดย location.go หรือ location.replaceState (เราเตอร์ไม่รู้อะไรเลย เกี่ยวกับสิ่งเหล่านี้ทำกับ URL)

โดยพื้นฐานแล้วฉันต้องการโซลูชันที่ไม่ควรโหลดเพจ / ส่วนประกอบซ้ำเมื่อพารามิเตอร์เส้นทางเปลี่ยนไป แต่ DID อัปเดตสถานะเส้นทางภายใน

ฉันลงเอยด้วยการใช้พารามิเตอร์การค้นหา คุณสามารถดูข้อมูลเพิ่มเติมได้ที่นี่: https://angular-2-training-book.rangle.io/handout/routing/query_params.html

ดังนั้นหากคุณต้องการดำเนินการบางอย่างเช่นบันทึกคำสั่งซื้อและรับรหัสคำสั่งซื้อคุณสามารถอัปเดต URL ของหน้าเว็บดังที่แสดงด้านล่าง การอัปเดตตำแหน่งศูนย์กลางและข้อมูลที่เกี่ยวข้องบนแผนที่จะคล้ายกัน

// let's say we're saving an order. Initally the URL is just blah/orders
save(orderId) {
    // [Here we would call back-end to save the order in the database]

    this.router.navigate(['orders'], { queryParams: { id: orderId } });
    // now the URL is blah/orders?id:1234. We don't reload the orders
    // page or component so get desired behaviour of not seeing any 
    // flickers or resetting the page.
}

และคุณติดตามมันภายในวิธีการ ngOnInit เช่น:

ngOnInit() {
    this.orderId = this.route
        .queryParamMap
        .map(params => params.get('id') || null);
    // orderID is up-to-date with what is saved in database now, or if
    // nothing is saved and hence no id query paramter the orderId variable
    // is simply null.
    // [You can load the order here from its ID if this suits your design]
}

หากคุณต้องการไปที่หน้าคำสั่งซื้อพร้อมคำสั่งซื้อใหม่ (ยังไม่ได้บันทึก) คุณสามารถทำได้:

this.router.navigate(['orders']);

หรือหากคุณต้องการตรงไปที่หน้าคำสั่งซื้อสำหรับคำสั่งซื้อ (ที่บันทึกไว้) ที่มีอยู่คุณสามารถทำได้:

this.router.navigate(['orders'], { queryParams: { id: '1234' } });

10

ฉันมีปัญหาใหญ่ในการทำให้สิ่งนี้ทำงานในรุ่น RCx ของ angular2 แพ็กเกจ Location ถูกย้ายและรัน location.go () ภายใน constructor () จะไม่ทำงาน ต้องเป็น ngOnInit () หรือใหม่กว่าในวงจรชีวิต นี่คือตัวอย่างโค้ด:

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

@Component({
  selector: 'example-component',
  templateUrl: 'xxx.html'
})
export class ExampleComponent implements OnInit
{
  constructor( private location: Location )
  {}

  ngOnInit()
  {    
    this.location.go( '/example;example_param=917' );
  }
}

นี่คือแหล่งข้อมูลเชิงมุมในเรื่องนี้: https://angular.io/docs/ts/latest/api/common/index/Location-class.html https://angular.io/docs/ts/latest/api/ common / index / LocationStrategy-class.html


7

ฉันใช้วิธีนี้เพื่อรับมัน:

const queryParamsObj = {foo: 1, bar: 2, andThis: 'text'};

this.location.replaceState(
  this.router.createUrlTree(
    [this.locationStrategy.path().split('?')[0]], // Get uri
    {queryParams: queryParamsObj} // Pass all parameters inside queryParamsObj
  ).toString()
);

- แก้ไข -

ฉันคิดว่าฉันควรเพิ่มข้อมูลเพิ่มเติมสำหรับเรื่องนี้

หากคุณใช้this.location.replaceState()เราเตอร์ของแอปพลิเคชันของคุณไม่ได้รับการอัปเดตดังนั้นหากคุณใช้ข้อมูลเราเตอร์ในภายหลังจะไม่เท่ากับสิ่งนี้ในเบราว์เซอร์ของคุณ ตัวอย่างเช่นถ้าคุณใช้localizeServiceภาษาการเปลี่ยนแปลงหลังจากภาษาสวิทช์กลับใบสมัครของคุณไปยัง URL this.location.replaceState()สุดท้ายที่คุณได้รับก่อนที่จะเปลี่ยนมันด้วย

หากคุณไม่ต้องการพฤติกรรมนี้คุณสามารถเลือกวิธีการอื่นสำหรับอัปเดต URL เช่น:

this.router.navigate(
  [this.locationStrategy.path().split('?')[0]],
  {queryParams: queryParamsObj}
);

ในตัวเลือกนี้เบราว์เซอร์ของคุณยังไม่ฟื้นฟู แต่คุณURLเปลี่ยนแปลงยังถูกฉีดเข้าไปในใบสมัครของคุณดังนั้นเมื่อคุณเปลี่ยนภาษาที่คุณไม่ได้มีปัญหาเหมือนในRouterthis.location.replaceState()

แน่นอนคุณสามารถเลือกวิธีการตามความต้องการของคุณ อย่างแรกจะเบากว่าเนื่องจากคุณไม่ได้มีส่วนร่วมกับแอปพลิเคชันของคุณมากกว่าการเปลี่ยนแปลงURLในเบราว์เซอร์


3

สำหรับฉันแล้วมันเป็นการผสมผสานของทั้งสองอย่างกับ Angular 4.4.5

การใช้ router.navigate ยังคงทำลาย url ของฉันโดยไม่เคารพส่วน realtiveTo: activatedRoute

ฉันลงเอยด้วย:

this._location.go(this._router.createUrlTree([this._router.url], { queryParams: { profile: value.id } }).toString())

3

ใช้แอตทริบิวต์ queryParamsHandling: 'merge' ในขณะที่เปลี่ยน url

this.router.navigate([], {
        queryParams: this.queryParams,
        queryParamsHandling: 'merge',
        replaceUrl: true,
});

3
สิ่งนี้ทำให้ส่วนประกอบที่กำหนดเส้นทางในปัจจุบันถูกโหลดใหม่
btx
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.