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


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.