[英]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.