In my Angular 5.2 app, profiles have two pages: Details and Activity. The default page for any profile is Details, so the routes are set up like this (full Typescript sample of the router config at the end of the post):
{ path: 'profile/:id', component: ProfileComponent,
children: [
{ path: 'details', component: ProfileDetailsComponent },
{ path: 'activity', component: ProfileActivityComponent },
{ path: '**', component: ProfileDetailsComponent }
]
}
ProfileComponent handles the root of both profile pages. It has a page header and a navigation bar, and includes a <router-outlet> element for the Profile Details/Activity Components (loaded depending on the route above). Its HTML looks like this:
<div> <!-- some header stuff --> </div>
<nav>
<ul>
<li><a routerLinkActive="active" routerLink="./details">Details</a></li>
<li><a routerLinkActive="active" routerLink="./activity">Activity</a></li>
</ul>
</nav>
<div class="page-content">
<!-- ProfileDetailsComponent or ProfileActivityComponent will be loaded here -->
<router-outlet></router-outlet>
</div>
As you can see I'm using the RouterLinkActive directive to give these tabs in the middle the active class when I'm on the right page. However, this runs into an issue:
active class when I'm on /users/profile/3/details.active class when I'm on /users/profile/3, even though that's functionally the same page — we still need to show you're on the Details page.If I instead write that link as the following...
<a routerLinkActive="active" routerLink="./">Details</a>
Then this gets the active class anywhere on the current route, even when I'm inside the Activity tab.
How can I get this link, which represents one (functional) page reachable via two URLs, to get the 'active' class on either URL? Is there a method I should be using other than routerLinkActive in this circumstance?
Currently to skirt this issue I have set up /users/profile/:id to redirect to /users/profile/:id/details, but I'd prefer to not have that redirect.
const routes: Routes = [
{ path: 'users', loadChildren: 'app/users/users.module#UsersModule' }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
(All the below-defined routes are relative to /users/ per the above route from app-routing.)
const routes: Routes = [
{ path: '', component: UserListComponent },
{ path: 'profile/:id', component: ProfileComponent,
children: [
{ path: 'details', component: ProfileDetailsComponent },
{ path: 'activity', component: ProfileActivityComponent },
{ path: '**', component: ProfileDetailsComponent }
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class UsersRoutingModule { }
The current patch fix (mentioned at the end of the problem section above) has that ** route instead set up with:
{ path: '**', redirectTo: 'details' }
...but as mentioned I'd really prefer to keep the /profiles/:id route available without direction.
Is hard to help without actually live testing the app, but try the following:
const routes: Routes = [
{ path: '', component: UserListComponent },
{ path: 'profile/:id', component: ProfileComponent,
children: [
{ path: '', component: ProfileDetailsComponent }
{ path: 'details', component: ProfileDetailsComponent },
{ path: 'activity', component: ProfileActivityComponent },
]
}
];
Also, add [routerLinkActiveOptions]="{exact:false}" to skip strict validation on the route:
<li><a routerLinkActive="active" routerLink="/details" [routerLinkActiveOptions]="{exact:false}>Details</a></li>
Edit1:
Based on your comment I'm confused, if /profile/:id should go to Details, then the Routes should not be like this instead?
const routes: Routes = [
{ path: '', component: UserListComponent },
{ path: 'profile/:id', component: ProfileDetailsComponent , // not ProfileComponent but: ProfileDetailsComponent
children: [
{ path: 'details', component: ProfileDetailsComponent },
{ path: 'activity', component: ProfileActivityComponent },
]
}
];
Sorry if I misunderstood, is my last working hour and my brain is fried... xD
Easiest solution is to track the route in your component by subscribing to Router events: Angular - Router: Router Events, and setting a bool based on the path (using plain ol' js/regex).
You can then set active class with [ngStyle]="{'active':customIsActive}", or shorthand [class.active]="customIsActive"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With