Як перейти до батьківського маршруту з дочірнього маршруту?


89

Моя проблема досить класична. У мене є приватна частина програми, яка стоїть за login form. Коли вхід успішний, він переходить до дочірнього маршруту для програми адміністратора.

Моя проблема полягає в тому, що я не можу використовувати, global navigation menuтому що маршрутизатор намагається маршрутизувати в моєму, AdminComponentа не в моєму AppCompoment. Отже, моя навігація порушена.

Інша проблема полягає в тому, що якщо хтось хоче отримати прямий доступ до URL-адреси, я хочу перенаправити на батьківський маршрут "входу". Але я не можу змусити це працювати. Мені здається, що тези двох питань схожі.

Будь-яка ідея, як це можна зробити?


3
будь ласка, додайте код
Jiang YD

Відповіді:


153

Вам потрібне посилання / HTML або ви хочете прокласти імперативно / в коді?

Посилання : Директива RouterLink завжди трактує надане посилання як дельту до поточної URL-адреси:

[routerLink]="['/absolute']"
[routerLink]="['../../parent']"
[routerLink]="['../sibling']"
[routerLink]="['./child']"     // or
[routerLink]="['child']" 

// with route param     ../../parent;abc=xyz
[routerLink]="['../../parent', {abc: 'xyz'}]"
// with query param and fragment   ../../parent?p1=value1&p2=v2#frag
[routerLink]="['../../parent']" [queryParams]="{p1: 'value', p2: 'v2'}" fragment="frag"

З RouterLink пам’ятайте про імпорт та використання directivesмасиву:

import { ROUTER_DIRECTIVES } from '@angular/router';
@Component({
    directives: [ROUTER_DIRECTIVES],

Імператив : navigate()метод вимагає відправної точки (тобто, relativeToпараметр). Якщо жодного не передбачено, навігація абсолютна:

import { Router, ActivatedRoute } from '@angular/router';
...
constructor(private router: Router, private route: ActivatedRoute) {}
...
this.router.navigate(["/absolute/path"]);
this.router.navigate(["../../parent"], {relativeTo: this.route});
this.router.navigate(["../sibling"],   {relativeTo: this.route});
this.router.navigate(["./child"],      {relativeTo: this.route}); // or
this.router.navigate(["child"],        {relativeTo: this.route});

// with route param     ../../parent;abc=xyz
this.router.navigate(["../../parent", {abc: 'xyz'}], {relativeTo: this.route});
// with query param and fragment   ../../parent?p1=value1&p2=v2#frag
this.router.navigate(["../../parent"], {relativeTo: this.route, 
    queryParams: {p1: 'value', p2: 'v2'}, fragment: 'frag'});

// navigate without updating the URL 
this.router.navigate(["../../parent"], {relativeTo: this.route, skipLocationChange: true});

1
router.navigate(string)метод , здається, не існує в поточній версії кутового (2.2). Я шукав у документах і лише знайшов navigate(commands: any[], extras?: NavigationExtras) : Promise<boolean>. Або мені чогось зовсім не вистачає?
Помідор

2
@Tomato, потрібно розмістити [] навколо маршрутів. Наприклад, this.router.navigate (["../../ parent"], {relativeTo: this.route});
gye

2
як ви relativeToпередаєте дані, коли використовуєте [routerLink] у html замість typecript?
redfox05,

те саме із послугами?
oCcSking

З якоїсь причини в моєму випадку мені доводиться використовувати ../../../замість того, ../щоб переходити до батьківського ( '/users'від '/users/1').
nelson6e65

47

Здається, це працює для мене станом на весну 2017 року:

goBack(): void {
  this.router.navigate(['../'], { relativeTo: this.route });
}

Де ваш компонент ctor приймає ActivatedRouteта Routerімпортує наступним чином:

import { ActivatedRoute, Router } from '@angular/router';


4
Замість дати, було б корисніше згадати версію Angular, яку ви випадково використовуєте.
isherwood

@isherwood Я згоден. Вибачення. Якщо я добре пам’ятаю, я написав його для Angular 4.0.x, і він все ще функціонував у 4.3.x. На жаль, я зараз відійшов від Angular,
ne1410s,

@ ne1410s Велике спасибі не вистачало родичу: this.route
Ян Самз

Примітка: НЕ працюватиме з додатковими сегментами маршрутизатора на модулях, що ледаче завантажуються. ПРИКЛАД:: parentPath'work: queue' (у якій є діти) та зазначені діти завантажують дочірній модуль з параметрами. fullCurrentPath: 'робота / доставка / модуль / список'. Наведений вище код не може завантажитися parentPathз fullCurrentPath.
Дон Томас Бойл

32

Ви можете перейти до батьківського кореня таким чином

this.router.navigate(['.'], { relativeTo: this.activeRoute.parent });

Вам потрібно буде ввести поточний активний маршрут у конструктор

constructor(
    private router: Router,
    private activeRoute: ActivatedRoute) {

  }

2
Додавши якесь пояснення, ця відповідь стане більш корисною.
Сагар Зала,

Багато людей пропонують перейти до брата за допомогою this.router.navigate (["../ sibling"], {relativeTo: this.route}); Однак це вже не працює. Я знайшов цю відповідь, напевно. Замість того, щоб використовувати '../' для навігації до батьків. змінити відносно To from this.route to this.route. очевидний правильний шлях
Terry Lam

1
@ChrisLamothe: О так, я помилився. Це працює в загальному випадку. Однак це не працює на допоміжних маршрутах. Це означає, що this.router.navigate (['../ sibling']) працює, але не this.router.navigate ([{outlets: {'secondary': ['../sibling']}}]). У допоміжній маршрутизації я повинен використовувати this.router.navigate ([{outlets: {'secondary': ['sibling']}}], {relativeTo: this.activateRoute.parent}).
Terry Lam

2
Крім того, метод навігації з цієї відповіді this.router.navigate(['.'], {relativeTo: this.activeRoute.parent});буде правильно працювати у випадку, коли ви використовуєте один і той же компонент у двох шляхах: / users / create та / users / edit / 123. В обох випадках він перейде до батьків / користувачів. Звичайна навігація за допомогою this.router.navigate([".."], {relativeTo: this.activeRoute})буде працювати лише для користувачів / create, але не буде працювати для користувачів / edit / 123, оскільки вона буде переходити до неіснуючих / users / edit / route.
Роганік

1
+1 для альтернативи, але особисто я трохи переслідувач байтів і вклав би додаткову крапку в параметр, [".."] , щоб виключити посилання на батьківського, {relativeTo: this.route} .
Конрад Вільтерстен

7
constructor(private router: Router) {}

navigateOnParent() {
  this.router.navigate(['../some-path-on-parent']);
}

Роутер підтримує

  • абсолютні шляхи /xxx- запускаються на маршрутизаторі кореневого компонента
  • відносні шляхи xxx- запускаються на маршрутизаторі поточного компонента
  • відносні шляхи ../xxx- запускаються на батьківському маршрутизаторі поточного компонента

Хоча цей код може відповісти на питання, надання додаткового контексту щодо того, чому та / або як він відповідає на питання, суттєво покращило б його довгострокову цінність. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення.
Тобі Спейт

1
@TobySpeight Досить справедливо. Я припустив, що ../це досить добре відомо, але врешті-решт це все однозначно. Дякую за підказку.
Günter Zöchbauer

1
Дякую за відповідь, я працюю на цьому веб-сайті вже досить давно, тому Angular, як очевидно, був оновлений з тих пір. Я спробував це рішення в моїй поточній версії, і воно не працює. Дозвольте мені оновитись, і я прокоментую після цього.
Карл Буйсверт,

1
Я не отримую, щоб ваш код працював належним чином. Однак, додавши явно {relaTo: this.route} як другий параметр у виклику навігації , це працює. Я б доклав до дурної друкарської помилки, якби не те, що ваші відповіді зазвичай мають надзвичайну точність. Це, можливо, зміна поведінки маршрутизатора з моменту надання відповіді (3,6 року тому, що в Кутові роки - це як половина вічності)?
Конрад Вільтерстен

Це стара відповідь, і в цей час маршрутизатор сильно змінився. Я думаю, що моя відповідь просто застаріла, враховуючи те, що є кілька відповідей із більшою кількістю голосів. Я вже не так багато займаюся веб-інтерфейсом і не маю всіх деталей на маківці.
Гюнтер Цехбауер,

6

Щоб перейти до батьківського компонента незалежно від кількості параметрів у поточному маршруті або батьківському маршруті: оновлення Angular 6 21.01.19

   let routerLink = this._aRoute.parent.snapshot.pathFromRoot
        .map((s) => s.url)
        .reduce((a, e) => {
            //Do NOT add last path!
            if (a.length + e.length !== this._aRoute.parent.snapshot.pathFromRoot.length) {
                return a.concat(e);
            }
            return a;
        })
        .map((s) => s.path);
    this._router.navigate(routerLink);

Це додає додатковий бонус, оскільки ви є абсолютним маршрутом, який ви можете використовувати з однотоннім маршрутизатором.

(Angular 4+ точно, можливо Angular 2 теж.)


дивним чином, це завжди повертає порожній масив і досягає того самого результату this._router.navigate([]), що і під час this._router.navigate([[]])переходу до батьківського маршруту, лише тоді, коли батьківський маршрут не є кореневим.
Ashish Jhanwar

оновлений код для відображення змін у Angular 6 та правильного пошуку батьків із батьками та дітьми, які містять дітей у маршрутах.
Дон Томас Бойл

Ви впевнені, що це не щось специфічне для вашого випадку використання? Здавалося б, не додавання останнього шляху перетворило б ['замовлення', '123', 'елементи', 1] у просто ['замовлення'], що здається зовсім не правильним. У будь-якому випадку ми просто перейшли з кутового 5 на 7 і не торкнулися цього кодованого.
kayjtea

їх кількість div на моїй сторінці .. при натисканні кожного div я передаю парми запитів і завантажую компонент. тепер за допомогою кнопки повернення браузера я хочу повернутися назад, як це зробити?
Враджендра Сінгх Мандлой

4

Інший спосіб може бути таким

this._router.navigateByUrl(this._router.url.substr(0, this._router.url.lastIndexOf('/'))); // go to parent URL

і ось конструктор

constructor(
    private _activatedRoute: ActivatedRoute,
    private _router: Router
  ) { }

3

без особливих сумнівів:

this.router.navigate(['..'], {relativeTo: this.activeRoute, skipLocationChange: true});

параметр ".." робить навігацію на один рівень вище, тобто батьківську :)


Можливо, ви захочете згадати мету / потребу skipLocationChange .
Конрад Вільтерстен

1

Мої маршрути мають такий шаблон:

  • користувач / редагувати / 1 -> Редагувати
  • user / create / 0 -> Create
  • користувач / -> Список

Наприклад, коли я перебуваю на сторінці редагування, і мені потрібно повернутися до сторінки списку, я повернуся на 2 рівні вище за маршрутом.

Думаючи про це, я створив свій метод із параметром "рівень".

goBack(level: number = 1) {
    let commands = '../';
    this.router.navigate([commands.repeat(level)], { relativeTo: this.route });
}

Отже, щоб перейти від редагування до списку, я називаю метод так:

this.goBack(2);

0

додайте Location до свого конструктора з @angular/common

constructor(private _location: Location) {}

додати функцію повернення:

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

а потім на ваш погляд:

<button class="btn" (click)="back()">Back</button>

5
Це працює, лише якщо ви раніше були в батьківському маршруті. Батьківські маршрути не мають нічого спільного з історією браузера ...
leviathanbadger

він повертається назад, але не переходить до батьківського компонента
Ендрю Андрєєв

Це не слід використовувати, якщо користувач переходить до компонента із зовнішнього сайту, він буде повернутий на цей сайт. Цей код такий самий, як натискання НАЗАД
КНОПКИ В БРАУЗЕРІ

0

Якщо ви використовуєте директиву uiSref, ви можете це зробити

uiSref="^"

0

Моє рішення:

const urlSplit = this._router.url.split('/');
this._router.navigate([urlSplit.splice(0, urlSplit.length - 1).join('/')], { relativeTo: this._route.parent });

І Routerін’єкція:

private readonly _router: Router
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.