Змінюйте параметри маршруту, не перезавантажуючись у Angular 2


113

Я роблю веб-сайт нерухомості за допомогою Angular 2, Google Maps тощо. Коли користувач змінює центр карти, я здійснюю пошук в API, вказуючи поточне положення карти, а також радіус. Справа в тому, що я хочу відобразити ці значення в URL-адресі, не завантажуючи всю сторінку. Це можливо? Я знайшов деякі рішення, використовуючи AngularJS 1.x, але нічого про Angular 2.


я думаю, якщо ви використовуєте [routerLink] = "['/ route", {param1: value1}], він не перезавантажить сторінку
Toolkit

але як я можу додати ще один параметр запиту?
Інструментарій

2
☝️ це призведе до перезавантаження сторінки
LifterCoder

Лише зауважте, що якщо ви використовуєте SSR для того, щоб зробити свій сайт SEO сумісним, це суперечка.
Джонатан

@Jonathan, так? Оскільки Angular бере на себе маршрутизацію, коли статична сторінка буде надана, я думаю, що це все-таки актуальне питання навіть при використанні SSR.
adam0101

Відповіді:


91

Ви можете використовувати те, location.go(url)що в основному змінить URL-адресу, без зміни маршруту застосування.

ПРИМІТКА Це може спричинити інший ефект, як перенаправлення на дочірній маршрут з поточного маршруту.

Пов'язане запитання, яке описуєlocation.go, не буде інтимним,Routerщоб відбутися зміни.


2
У моєму маршруті є параметр під назвою "пошук", у якому отримують серіалізовану версію полів пошуку, коли стан переліку завантажується вперше, я читаю лише ці параметри, використовуючи this._routeParams.get ("пошук"), деріаріалізую фільтри і виконати пошук. Якщо користувач змінює поля пошуку, використовуючи карту чи грані пошуку, я просто будую правильний URL за допомогою методу створення інструкції var маршрутизатора = this._router.generate (['Лістинг', {search: serializedFields}] ), а потім використовуючи this._location.go (інструкція.urlPath) для зміни URL-адреси, не перезавантажуючи стан.
Маркос Базуальдо,

20
Якщо когось цікавить: імпортуйте {Location} з 'angular2 / platform / common';
Кесаріон

18
import { Location } from '@angular/common';у
куті

2
Ви декларували конструктора на кшталтconstructor(private location: Location){ }
Панкай Паркар

2
@ AdrianE проблема, швидше за все, ви ввели, location.go()поки ви повинні були ввести this.location.go(). Коли ви випромінюєте this., ви викликаєте інтерфейс розташування Typescript.
georg-un

94

Станом на 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'
Ініго

2
Поєднайте це зі створенням URL-адреси, як запропонував @golfadas, і у нас є переможець!
crowmagnumb

63

Використання location.go(url)- це шлях, але замість жорсткого кодування 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, що знаходиться в навігаціїExtras, а не comads. createUrlTree ([], {RelaTo: this.activateRoute, queryParams: {param: 1}})
комплект

просто для уточнення того, що сказав @kit, зробіть це:this.router.createUrlTree([], {relativeTo: this.activatedRoute, queryParams: {param: 1}}).toString()
bluegrounds

12

Для тих, хто як я знайшов це питання, наступне може бути корисним.

У мене була подібна проблема і спочатку спробував використовувати location.go та location.replaceState, як запропоновано в інших відповідях тут. Однак я зіткнувся з проблемами, коли мені довелося перейти на іншу сторінку програми, оскільки навігація була відносно поточного маршруту, а поточний маршрут не оновлювався location.go або location.replaceState (маршрутизатор нічого не знає про те, що вони роблять із URL-адресою)

По суті, мені було потрібне рішення, яке DIDN'T перезавантажує сторінку / компонент, коли параметр маршруту змінився, але 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 () всередині конструктора () не буде працювати. Це повинно бути 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()
);

- EDIT -

Я думаю, що для цього я повинен додати ще трохи інформації.

Якщо ви користуєтеся this.location.replaceState()маршрутизатором, ваша програма не оновлюється, тому якщо ви згодом використовуєте інформацію про маршрутизатор, це не дорівнює цьому у вашому браузері. Наприклад, якщо ви localizeServiceзмінюєте мову, після переключення мови додаток повернеться до останньої URL-адреси, де ви були до того, як змінити його this.location.replaceState().

Якщо ви не хочете такої поведінки, ви можете обрати інший метод оновлення URL-адреси, наприклад:

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

У цьому варіанті ваш веб-переглядач також не оновлюється, але ваша URLзміна також вводиться у Routerвашу програму, тому при переключенні мови у вас немає проблем, як в this.location.replaceState().

Звичайно, ви можете вибрати метод для своїх потреб. Перший - легший, оскільки ви не займаєтеся додатком більше, ніж змінюєте URLбраузер.


3

Для мене це насправді було поєднанням обох з кутовою 4.4.5.

Використання router.navigate продовжувало руйнувати мій URL, не дотримуючись realtiveTo: activeRoute частини.

Я закінчив:

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

3

Використовуйте атрибут queryParamsHandling: 'злиття' під час зміни URL-адреси.

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

3
Це призводить до перезавантаження поточного маршрутизованого компонента
btx
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.