I'm trying to create breadcrumbs using XNG-Breadcurmb, in my Angular 11. I tried to understand the document and implement it based on my understanding.
As per the above GIF, I'm missing connection between 2nd and third page.
Expectation
Users List --> User Dashboard --> Completed List
When click on User Dashboard I should go back on User Dashboard page then User List
Current behavior
when i click on cards (either click on completed list btn or in-completed list btn), User Dashboard disappeared. i don't know where im missing.
Team, appologize for not adding stackblitz, due to some reason I'm blocked to access stackblitz or any code sandbox
so far i have
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 { }
Customer-list-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]);
}
}
Customer-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>
Customer-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>
Customer-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]);
}
}
}
Customer-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>
And given a try with this native solution , but again i couldn't make it because i didn't get good understanding about router event(That's my fault).
So requesting all to help me,
Thanks
The library (by default) utilizes the routes hierarchy to set up the breadcrumbs. Here is a visualization of your routes hierarchy at the moment routes hierarchy
As you can see, User Dashboard is neither a descendant of Completed List nor any module
or component
route.
The simplest solution is to refactor CustomerDashboardComponent
,CustomerTabSelectionComponent
,CompletedUsersComponent
, and IncompleteUsersComponent
to be children of another component . You will end up with following routes structure:
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' }
}
]
}
];
Note: you don't need breadcrumb on any descendant with empty path if parent route path has one. If both are defined, the child (with empty path) will overwrite the parent one source