我的面包屑有什么问题 - Angular 11?
What is wrong with my breadcrumbs - Angular 11?
我正在尝试使用 XNG-Breadcurmb 在我的 Angular 11 中创建面包屑。我试图理解文档并根据我的理解实现它。
根据上面的 GIF,我缺少第 2 页和第 3 页之间的连接。
预期
用户列表 --> 用户仪表板 --> 完成列表
当点击用户仪表板时,我应该返回用户仪表板页面然后用户列表
当前行为
当我单击卡片时(单击已完成列表按钮或未完成列表按钮),用户仪表板消失了。我不知道我哪里不见了。
团队,很抱歉没有添加 stackblitz,由于某些原因我被阻止访问 stackblitz 或任何代码沙箱
到目前为止我有
app.routing.ts
import { HomeComponent } from './components/home/home.component';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: '', component: HomeComponent },
{
path: 'home', component: HomeComponent,
data: {
breadcrumb: {
label: 'my home',
info: 'home',
routeInterceptor: (routeLink) => {
console.log(routeLink);
return routeLink;
},
},
},
},
{
path: 'customers',
loadChildren: () => import('./feature/customer/customer.module').then(m => m.CustomerModule),
data: {
breadcrumb: {
label: 'Users List',
},
},
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
customer.routing.module.ts
import { IncompleteUsersComponent } from './components/incomplete-users/incomplete-users.component';
import { CompletedUsersComponent } from './components/completed-users/completed-users.component';
import { CustomerTabSelectionComponent } from './components/customer-tab-selection/customer-tab-selection.component';
import { CustomersListComponent } from './components/customers-list/customers-list.component';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CustomerDashboardComponent } from './components/customer-dashboard/customer-dashboard.component';
const routes: Routes = [
{
path: '', component: CustomersListComponent,
/* data: {
breadcrumb: 'Customer List'
} */
data: {
breadcrumb: {
disable: true,
},
},
},
{
path: 'dashboard/:id', component: CustomerDashboardComponent, data: {
breadcrumb: 'User Dashboard'
}
},
{
path: 'user-tab/:id', component: CustomerTabSelectionComponent, data: {
breadcrumb: 'Users tab'
},
},
{
path: 'cmp-users/:id', component: CompletedUsersComponent, data: {
breadcrumb: 'Completed Users list'
}
},
{
path: 'icmp-users/:id', component: IncompleteUsersComponent, data: {
breadcrumb: 'In-completed Users list'
}
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class CustomerRoutingModule { }
客户列表-component.ts
import { UsersService } from './../../users.service';
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-customers-list',
templateUrl: './customers-list.component.html',
styleUrls: ['./customers-list.component.scss']
})
export class CustomersListComponent implements OnInit {
userList;
constructor(private userService: UsersService, private router: Router) { }
ngOnInit(): void {
this.loadUsers();
}
loadUsers(): void {
this.userService.getUsersList().subscribe((response) => {
if (response) {
this.removeDuplicateUsers(response);
}
}, err => {
console.log('Error', err);
});
}
removeDuplicateUsers(data): void {
this.userList = data.filter((v, i, a) => a.findIndex(t => (t.userId === v.userId)) === i);
console.log('user list', this.userList);
}
gotoUserDashboard(item): void{
console.log('href clicked', item);
this.router.navigate(['customers/dashboard/' + item.userId]);
}
}
客户-list.html
<div class="wrapper">
<div class="lbl-container">
<span class="lbl">User Id</span>
<span class="lbl">Status</span>
</div>
<div class="data-container" *ngFor="let user of userList">
<span class="lbl"><a href="javascript:void(0);" (click)="gotoUserDashboard(user)">{{user.userId}}</a></span>
<span class="lbl">{{user.completed === false ? 'Not Complete': 'Completed'}}</span>
</div>
</div>
客户-dashboard.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { UsersService } from '../../users.service';
@Component({
selector: 'app-customer-dashboard',
templateUrl: './customer-dashboard.component.html',
styleUrls: ['./customer-dashboard.component.scss']
})
export class CustomerDashboardComponent implements OnInit {
totalComplete;
totalInComplete;
userInfo;
constructor(private activatedRoute: ActivatedRoute, private router: Router, private userService: UsersService) {
this.activatedRoute.params.subscribe(data => {
const userId = data.id;
this.getUserInfoByUserId(userId);
console.log(userId);
});
}
ngOnInit(): void {
}
getUserInfoByUserId(userId): void {
console.log('user data', userId);
this.userService.getUserByID(userId).subscribe((response) => {
if (response) {
console.log(response);
this.userInfo = response;
this.totalComplete = response.filter((t) => t.completed === true).length;
this.totalInComplete = response.filter((f) => f.completed === false).length;
console.log('totalComplete', this.totalComplete);
console.log('total In-Complete', this.totalInComplete);
}
}, err => {
console.log(err);
});
}
gotoUserbyStatus(e): void{
console.log('click', this.userInfo);
console.log('event', e.target.value);
const extra = { tab: e.target.value, userId : this.userInfo[0].userId };
// this.router.navigate(['customers/customer-tab/' + this.userInfo[0].userId], { state: extra });
this.router.navigate(['customers/user-tab/' + this.userInfo[0].userId], { state: extra });
}
}
customer.dashboard.html
<div class="task-wrapper" >
<div class="completed">
<h2>Completed</h2>
<h4>{{totalComplete}}</h4>
<div class="list">
<button (click)="gotoUserbyStatus($event)" value="completeLst">Completed List</button>
</div>
</div>
<div class="incompleted">
<h2>In-Completed</h2>
<h4>{{totalInComplete}}</h4>
<div class="list">
<button (click)="gotoUserbyStatus($event)" value="inCompleteLst">In-Completed List</button>
</div>
</div>
</div>
客户-tab.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { UsersService } from '../../users.service';
@Component({
selector: 'app-customer-tab-selection',
templateUrl: './customer-tab-selection.component.html',
styleUrls: ['./customer-tab-selection.component.scss']
})
export class CustomerTabSelectionComponent implements OnInit {
userId;
tabFocus = '';
constructor(private activatedRoute: ActivatedRoute, private router: Router, private userService: UsersService) {
this.activatedRoute.params.subscribe(data => {
if (data && data.id){
const userId = data.id;
console.log('params', userId);
}
});
const routerData = this.router.getCurrentNavigation().extras.state;
console.log('extra', routerData);
this.userId = routerData.userId;
this.tabFocus = routerData.tab;
}
ngOnInit(): void {
}
onTabClick(event): void{
console.log('tab click event', event.target.value);
const focusTab = event.target.value;
if (focusTab === 'completed'){
// this.router.navigate(['customers/customer-tab/' + this.userInfo[0].userId], { state: extra });
this.router.navigate(['customers/cmp-users/' + this.userId]);
} else if (focusTab === 'incompleted'){
this.router.navigate(['customers/icmp-users/' + this.userId]);
}
}
}
客户-tab.html
<div class="container-fluid">
<div class="row">
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link" id="completed-tab" data-bs-toggle="tab" data-bs-target="#completed"
type="button" role="tab" aria-controls="completed" aria-selected="true"
[ngClass]="[tabFocus === 'completeLst' ? 'active' : '']" (click)="onTabClick($event)"
value="completed">completed</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="incompleted-tab" data-bs-toggle="tab" data-bs-target="#incompleted"
type="button" role="tab" aria-controls="incompleted" aria-selected="false"
[ngClass]="[tabFocus === 'inCompleteLst' ? 'active' : '']" (click)="onTabClick($event)"
value="incompleted">incompleted</button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade" id="completed" role="tabpanel" aria-labelledby="completed-tab"
[ngClass]="[tabFocus === 'completeLst' ? 'show active' : '']">
<app-completed-users></app-completed-users>
</div>
<div class="tab-pane fade" id="incompleted" role="tabpanel" aria-labelledby="incompleted-tab"
[ngClass]="[tabFocus === 'inCompleteLst' ? 'show active' : '']">
<app-incomplete-users></app-incomplete-users>
</div>
</div>
</div>
</div>
并试了一下 native solution ,但我还是没能做到,因为我对路由器事件没有很好的理解(那是我的错)。
所以请求大家帮助我,
谢谢
库(默认情况下)利用路由层次结构来设置面包屑。这是目前您的路线层次结构的可视化
routes hierarchy
如您所见,用户仪表板既不是已完成列表的后代,也不是任何module
或component
路线.
最简单的解决方案是将 CustomerDashboardComponent
、CustomerTabSelectionComponent
、CompletedUsersComponent
和 IncompleteUsersComponent
重构为另一个组件的子组件。您最终将得到以下路由结构:
const routes: Routes = [
{path: '', component: CustomersListComponent},
{
path: 'users', component: UsersComponent,
data: { breadcrumb: 'User Dashboard' },
children: [
{path: '', redirectTo: 'dashboard/:id', pathMatch: 'exact'},
{
path: 'dashboard/:id', component: CustomerDashboardComponent
},
{
path: 'user-tab/:id', component: CustomerTabSelectionComponent,
data: { breadcrumb: 'Users tab' },
},
{
path: 'cmp-users/:id', component: CompletedUsersComponent,
data: { breadcrumb: 'Completed Users list' }
},
{
path: 'icmp-users/:id', component: IncompleteUsersComponent,
data: { breadcrumb: 'In-completed Users list' }
}
]
}
];
注意:如果父路由路径有一个,则您不需要在任何具有空路径的后代上使用面包屑。如果两者都已定义,则子项(空路径)将覆盖父项 source
我正在尝试使用 XNG-Breadcurmb 在我的 Angular 11 中创建面包屑。我试图理解文档并根据我的理解实现它。
根据上面的 GIF,我缺少第 2 页和第 3 页之间的连接。
预期
用户列表 --> 用户仪表板 --> 完成列表
当点击用户仪表板时,我应该返回用户仪表板页面然后用户列表
当前行为
当我单击卡片时(单击已完成列表按钮或未完成列表按钮),用户仪表板消失了。我不知道我哪里不见了。
团队,很抱歉没有添加 stackblitz,由于某些原因我被阻止访问 stackblitz 或任何代码沙箱
到目前为止我有
app.routing.ts
import { HomeComponent } from './components/home/home.component';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: '', component: HomeComponent },
{
path: 'home', component: HomeComponent,
data: {
breadcrumb: {
label: 'my home',
info: 'home',
routeInterceptor: (routeLink) => {
console.log(routeLink);
return routeLink;
},
},
},
},
{
path: 'customers',
loadChildren: () => import('./feature/customer/customer.module').then(m => m.CustomerModule),
data: {
breadcrumb: {
label: 'Users List',
},
},
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
customer.routing.module.ts
import { IncompleteUsersComponent } from './components/incomplete-users/incomplete-users.component';
import { CompletedUsersComponent } from './components/completed-users/completed-users.component';
import { CustomerTabSelectionComponent } from './components/customer-tab-selection/customer-tab-selection.component';
import { CustomersListComponent } from './components/customers-list/customers-list.component';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CustomerDashboardComponent } from './components/customer-dashboard/customer-dashboard.component';
const routes: Routes = [
{
path: '', component: CustomersListComponent,
/* data: {
breadcrumb: 'Customer List'
} */
data: {
breadcrumb: {
disable: true,
},
},
},
{
path: 'dashboard/:id', component: CustomerDashboardComponent, data: {
breadcrumb: 'User Dashboard'
}
},
{
path: 'user-tab/:id', component: CustomerTabSelectionComponent, data: {
breadcrumb: 'Users tab'
},
},
{
path: 'cmp-users/:id', component: CompletedUsersComponent, data: {
breadcrumb: 'Completed Users list'
}
},
{
path: 'icmp-users/:id', component: IncompleteUsersComponent, data: {
breadcrumb: 'In-completed Users list'
}
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class CustomerRoutingModule { }
客户列表-component.ts
import { UsersService } from './../../users.service';
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-customers-list',
templateUrl: './customers-list.component.html',
styleUrls: ['./customers-list.component.scss']
})
export class CustomersListComponent implements OnInit {
userList;
constructor(private userService: UsersService, private router: Router) { }
ngOnInit(): void {
this.loadUsers();
}
loadUsers(): void {
this.userService.getUsersList().subscribe((response) => {
if (response) {
this.removeDuplicateUsers(response);
}
}, err => {
console.log('Error', err);
});
}
removeDuplicateUsers(data): void {
this.userList = data.filter((v, i, a) => a.findIndex(t => (t.userId === v.userId)) === i);
console.log('user list', this.userList);
}
gotoUserDashboard(item): void{
console.log('href clicked', item);
this.router.navigate(['customers/dashboard/' + item.userId]);
}
}
客户-list.html
<div class="wrapper">
<div class="lbl-container">
<span class="lbl">User Id</span>
<span class="lbl">Status</span>
</div>
<div class="data-container" *ngFor="let user of userList">
<span class="lbl"><a href="javascript:void(0);" (click)="gotoUserDashboard(user)">{{user.userId}}</a></span>
<span class="lbl">{{user.completed === false ? 'Not Complete': 'Completed'}}</span>
</div>
</div>
客户-dashboard.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { UsersService } from '../../users.service';
@Component({
selector: 'app-customer-dashboard',
templateUrl: './customer-dashboard.component.html',
styleUrls: ['./customer-dashboard.component.scss']
})
export class CustomerDashboardComponent implements OnInit {
totalComplete;
totalInComplete;
userInfo;
constructor(private activatedRoute: ActivatedRoute, private router: Router, private userService: UsersService) {
this.activatedRoute.params.subscribe(data => {
const userId = data.id;
this.getUserInfoByUserId(userId);
console.log(userId);
});
}
ngOnInit(): void {
}
getUserInfoByUserId(userId): void {
console.log('user data', userId);
this.userService.getUserByID(userId).subscribe((response) => {
if (response) {
console.log(response);
this.userInfo = response;
this.totalComplete = response.filter((t) => t.completed === true).length;
this.totalInComplete = response.filter((f) => f.completed === false).length;
console.log('totalComplete', this.totalComplete);
console.log('total In-Complete', this.totalInComplete);
}
}, err => {
console.log(err);
});
}
gotoUserbyStatus(e): void{
console.log('click', this.userInfo);
console.log('event', e.target.value);
const extra = { tab: e.target.value, userId : this.userInfo[0].userId };
// this.router.navigate(['customers/customer-tab/' + this.userInfo[0].userId], { state: extra });
this.router.navigate(['customers/user-tab/' + this.userInfo[0].userId], { state: extra });
}
}
customer.dashboard.html
<div class="task-wrapper" >
<div class="completed">
<h2>Completed</h2>
<h4>{{totalComplete}}</h4>
<div class="list">
<button (click)="gotoUserbyStatus($event)" value="completeLst">Completed List</button>
</div>
</div>
<div class="incompleted">
<h2>In-Completed</h2>
<h4>{{totalInComplete}}</h4>
<div class="list">
<button (click)="gotoUserbyStatus($event)" value="inCompleteLst">In-Completed List</button>
</div>
</div>
</div>
客户-tab.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { UsersService } from '../../users.service';
@Component({
selector: 'app-customer-tab-selection',
templateUrl: './customer-tab-selection.component.html',
styleUrls: ['./customer-tab-selection.component.scss']
})
export class CustomerTabSelectionComponent implements OnInit {
userId;
tabFocus = '';
constructor(private activatedRoute: ActivatedRoute, private router: Router, private userService: UsersService) {
this.activatedRoute.params.subscribe(data => {
if (data && data.id){
const userId = data.id;
console.log('params', userId);
}
});
const routerData = this.router.getCurrentNavigation().extras.state;
console.log('extra', routerData);
this.userId = routerData.userId;
this.tabFocus = routerData.tab;
}
ngOnInit(): void {
}
onTabClick(event): void{
console.log('tab click event', event.target.value);
const focusTab = event.target.value;
if (focusTab === 'completed'){
// this.router.navigate(['customers/customer-tab/' + this.userInfo[0].userId], { state: extra });
this.router.navigate(['customers/cmp-users/' + this.userId]);
} else if (focusTab === 'incompleted'){
this.router.navigate(['customers/icmp-users/' + this.userId]);
}
}
}
客户-tab.html
<div class="container-fluid">
<div class="row">
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link" id="completed-tab" data-bs-toggle="tab" data-bs-target="#completed"
type="button" role="tab" aria-controls="completed" aria-selected="true"
[ngClass]="[tabFocus === 'completeLst' ? 'active' : '']" (click)="onTabClick($event)"
value="completed">completed</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="incompleted-tab" data-bs-toggle="tab" data-bs-target="#incompleted"
type="button" role="tab" aria-controls="incompleted" aria-selected="false"
[ngClass]="[tabFocus === 'inCompleteLst' ? 'active' : '']" (click)="onTabClick($event)"
value="incompleted">incompleted</button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade" id="completed" role="tabpanel" aria-labelledby="completed-tab"
[ngClass]="[tabFocus === 'completeLst' ? 'show active' : '']">
<app-completed-users></app-completed-users>
</div>
<div class="tab-pane fade" id="incompleted" role="tabpanel" aria-labelledby="incompleted-tab"
[ngClass]="[tabFocus === 'inCompleteLst' ? 'show active' : '']">
<app-incomplete-users></app-incomplete-users>
</div>
</div>
</div>
</div>
并试了一下 native solution ,但我还是没能做到,因为我对路由器事件没有很好的理解(那是我的错)。
所以请求大家帮助我,
谢谢
库(默认情况下)利用路由层次结构来设置面包屑。这是目前您的路线层次结构的可视化 routes hierarchy
如您所见,用户仪表板既不是已完成列表的后代,也不是任何module
或component
路线.
最简单的解决方案是将 CustomerDashboardComponent
、CustomerTabSelectionComponent
、CompletedUsersComponent
和 IncompleteUsersComponent
重构为另一个组件的子组件。您最终将得到以下路由结构:
const routes: Routes = [
{path: '', component: CustomersListComponent},
{
path: 'users', component: UsersComponent,
data: { breadcrumb: 'User Dashboard' },
children: [
{path: '', redirectTo: 'dashboard/:id', pathMatch: 'exact'},
{
path: 'dashboard/:id', component: CustomerDashboardComponent
},
{
path: 'user-tab/:id', component: CustomerTabSelectionComponent,
data: { breadcrumb: 'Users tab' },
},
{
path: 'cmp-users/:id', component: CompletedUsersComponent,
data: { breadcrumb: 'Completed Users list' }
},
{
path: 'icmp-users/:id', component: IncompleteUsersComponent,
data: { breadcrumb: 'In-completed Users list' }
}
]
}
];
注意:如果父路由路径有一个,则您不需要在任何具有空路径的后代上使用面包屑。如果两者都已定义,则子项(空路径)将覆盖父项 source