簡體   English   中英

Angular routerLink 導航到“嵌套”頁面上的錯誤路徑

[英]Angular routerLink navigating to wrong path on 'nested' pages

我正在 Angular 12 中構建一個基本的筆記應用程序,其中筆記存儲在 Firebase 中。 筆記包含文本,但也可以作為更多筆記的父節點,例如:

Note
Note
|- Note
  |- Note
  |- Note
    |- Note
|- Note
Note

您可以從/notes/{{note.id}}查看筆記的子筆記列表,並在/edit/{{note.id}}編輯筆記本身。 如果/notes/的 id 為空,它會抓取所有頂級筆記。

問題:一切正常,直到我嘗試查看層次結構第二級的注釋列表。 routerLink 似乎將/edit/{{note.id}}/notes/{{note.id}}到導航堆棧中,例如:

Note1
|- Note2 <-- click '>' button on note2 in list view
  |- Note3 <-- expect to see note3 in list view

我沒有查看notes/2 ,而是轉到edit/2 在瀏覽器中單擊返回到我想要的正確路線notes/2 ,允許我在列表視圖中看到 note3 。 為什么點擊圖標按鈕時會添加/edit/{{note.id}}到路由器?

編輯:StackBlitz 鏈接在這里演示這個問題: https ://stackblitz.com/edit/angular-hcmvab

相關代碼片段如下:

app-routing.module.ts

const routes: Routes = [
  { path: '', redirectTo: 'notes', pathMatch: 'full' },
  { path: 'login', component: LoginComponent },
  { path: 'notes',
    children: [
      { path: '', component: NotesComponent },
      { path: ':id', component: NotesComponent },
    ],
  },
  { path: 'edit/:id', component: NoteDetailsComponent }
];

note.component.ts

export class NotesComponent implements OnInit {
  parentID = this.route.snapshot.paramMap.get('id');
  notes: any;

  constructor(
    private route: ActivatedRoute,
    private notesService: NotesService
  ) {}

  ngOnInit(): void {
    this.retrieveNotes();
  }

  retrieveNotes(): void {
    this.notesService
      .getChildNotes(this.parentID)
      .snapshotChanges()
      .pipe(
        map((changes: any) =>
          changes.map((c: any) => ({
            id: c.payload.doc.id,
            ...c.payload.doc.data(),
          }))
        )
      )
      .subscribe((data) => {
        this.notes = data;
      });
  }
}

note.component.html

<mat-list>
  <mat-list-item *ngFor="let note of notes" [routerLink]="['/edit', note.id]">
    <mat-icon fontSet="material-icons-outlined" mat-list-icon>description_outlined</mat-icon>
    <div mat-line>{{note?.title}}</div>
    <div class="spacer"></div>
    <button mat-icon-button *ngIf="note.children.length > 0" [routerLink]="['/notes', note.id]">
      <mat-icon>arrow_forward_ios</mat-icon>
    </button>
  </mat-list-item>
</mat-list>

問題是你把一個[routerLink]放在另一個里面。 您應該將[routerLink]屬性從<mat-list-item>到另一個位置,例如其中的按鈕。 您這樣做的方式可能是首先激活按鈕單擊,然后單擊整個列表項。

嘗試更改為:

     <mat-list-item *ngFor="let note of notes" >
        <mat-icon fontSet="material-icons-outlined" mat-list-icon>description_outlined</mat-icon>
        <div mat-line>{{note?.title}}</div>
        <div class="spacer"></div>
        <button mat-icon-button [routerLink]="['/notes', note.id]">
          <mat-icon>Some-Edit-Icon</mat-icon>
        </button>
        <button mat-icon-button *ngIf="note.children.length > 0" [routerLink]="['/notes', note.id]">
          <mat-icon>arrow_forward_ios</mat-icon>
        </button>
      </mat-list-item>
    </mat-list>

不僅僅是調整你喜歡的方式。 您可能遇到的另一個問題是您將notes.id傳遞給訪問子筆記的[routerLink] 也許你應該放一個*ngFor並通過children.id代替

如果此解決方案不起作用,請創建一個 stackBlitz 以便我們可以更清楚地看到問題。

您正在尋找的是具有可變數量參數的路由。 類似於/note/a/b/c/d/e 實現這一點的一種方法是使用帶有自定義 url 匹配器的路由,如果它以/note (或您選擇的前綴)開頭,則接受該路由,並收集所有其余的段並將它們傳遞給組件。

以下是路由的定義方式:

const variableRouteMatcher: UrlMatcher = (
  segments: UrlSegment[]
): UrlMatchResult => {
  if (segments.length >= 1 && segments[0].path === 'note') {
    const fullPath = segments
      .slice(1)
      .map(r => r.path)
      .join('/');
    return {
      consumed: segments,
      posParams: {
        fullPath: new UrlSegment(fullPath, {})
      }
    };
  }
  return null;
};

const routes: Routes = [
  { matcher: variableRouteMatcher, component: NoteComponent }
];

工作StackBlitz示例

編輯(基於評論)在查看您的 stackblitz 之后,我看到了兩個問題,一個是 Cantarzo 在他的回答中指出的,即另一個鏈接元素中有一個鏈接元素。

但更嚴重的錯誤是您的notes組件不監聽其路由參數的變化,它獲取路由的快照,然后永遠使用它。 請記住,Angular 在路由中重用組件,因此每當您導航到注釋時都會使用相同的NoteComponent實例。

這意味着第一次導航到筆記時,它會獲取其父 ID,然后無論您走到哪里,父 ID 都保持不變。

要解決這個問題,您必須訂閱激活路由參數的更改並相應地更新您的父 ID(以及您的子注釋)

查看你的分叉 stacklitz

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM