Multiple RouterLinkActive trigger CSS class at the same time - html

I'm using multiple <a> tags to use routerLink.
When I first load my home page, the home icon (which is in aMenuItems) has the active class thanks to routerLinkActive and the rest of the array aMenuItems does not. This is a good behaviour.
However, both <a> tags in bottom-group has the active class triggered as the home icon. I tried to set the attribute exact in routerLinkActiveOptions to true but nothing changes.
As soon as I select another page other than home page, this bug disappears.
HTML:
<div class="top-group">
<a
*ngFor="let oItem of aMenuItems"
class="menu-item"
[routerLink]="oItem.link"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>
<mat-icon>{{oItem.icon}}</mat-icon>
<p>
{{oItem.designation}}
</p>
</a>
</div>
<div class="bottom-group">
<a
class="menu-item"
[routerLink]="routerLinkMarketPlace"*
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>
<mat-icon>apps</mat-icon>
<p>applications</p>
</a>
<a
class="menu-item"
[routerLink]="routerLinkSettings"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>
<mat-icon>settings</mat-icon>
<p>paramètres</p>
</a>
</div>

I found a solution to my problem:
In HTML, I replaced the routerLinkActive with a class condition using the attribute isActive from the router.
<a
class="menu-item"
[routerLink]="routerLinkSettings"
[class.active]="router.isActive(routerLinkSettings)"
[routerLinkActiveOptions]="{ exact: true }"
>
<mat-icon>settings</mat-icon>
<p>parameters</p>
</a>
You also need to inject the router in your .ts
constructor(private router: Router) {
super();
}
Hope it can help someone passing by !

Related

How to change nav "active" class on different pages with base.html

I have my navbar on my base.html, so I extend it on all other pages.
But I have a class "active" on the home page, so it also stays active in all other pages.
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="http://127.0.0.1:8000/backend/">
<i class="ni ni-shop text-primary"></i>
<span class="nav-link-text">Dashboard</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://127.0.0.1:8000/backend/clientes">
<i class="ni ni-ungroup text-orange"></i>
<span class="nav-link-text">Clients</span>
</a>
</li>
</ul>
How can I change the active class to a different menu item based on the page I am?
There's no one-size-fits-all answer to your question, it really depends on your project's structure, url hierarchy etc. But usually, the best solutions are either a custom template tag taking the request as argument (and/or other context variables or plain constants, depending on your own project's logic) to compute the current "section" and render the navbar accordingly.
Send name as variable and value with active.
def index(request):
# your code
context = {
'dashboard': 'active',
}
return render(request, 'index.html', context)
def clients(request):
# your code
context = {
'clients': 'active',
}
return render(request, 'clients.html', context)
Use variable like this:
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link {{ dashboard }}" href="http://127.0.0.1:8000/backend/">
<i class="ni ni-shop text-primary"></i>
<span class="nav-link-text">Dashboard</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ clients }}" href="http://127.0.0.1:8000/backend/clientes">
<i class="ni ni-ungroup text-orange"></i>
<span class="nav-link-text">Clients</span>
</a>
</li>
</ul>
OPTION 1
You can use django contex_processors.
add your settings.py
TEMPLATES = [
{
#other settings
'BACKEND': 'django.template.backends.django.DjangoTemplates',
#other settings
'OPTIONS': {
'context_processors': [
#other options
'context_file_path.defaults',
],
},
},
]
in your context_file.py
def defaults(request):
active_bar = "" # your active bar logic
return {
'active_bar': active_bar,
}
with this method, each request decide which bar active. And active_bar variable is being passed to your template. In your template you can add active class if active_bar variable equals your bar name. Like that:
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link {% if active_bar == 'dashboard' %}active{% endif %}" href="http://127.0.0.1:8000/backend/">
<i class="ni ni-shop text-primary"></i>
<span class="nav-link-text">Dashboard</span>
</a>
</li>
<li class="nav-item {% if active_bar == 'clients' %}active{% endif %}">
<a class="nav-link" href="http://127.0.0.1:8000/backend/clientes">
<i class="ni ni-ungroup text-orange"></i>
<span class="nav-link-text">Clients</span>
</a>
</li>
</ul>
OPTION 2
You can write a custom js file and add your base html. In this js file you can detect url and decide active pane. After that you can add active class to list pane.

class="js-dropdown" and class="js-dropdown-menu" broke after angular upgrade

We upgraded from Angular 4 to Angular 8.1 and a lot of our drop downs are broken. From what I can tell they all contain these two style classes: the class js-dropdown and js-dropdown-menu. We can't find where these style classes are coming from or how they work. It's hard to search these terms on google because there's no way to have a must-include for hyphens, that I know of. Here's an example of the html:
<div class="select-wrapper" id="searchOption">
<li class="dropdown nav__item is-parent" tabindex="0" style="outline: 0" (blur)="closeDropdown($event)">
<div class="select-dropdown js-dropdown">
<span class="selection">{{ searchType }}</span>
<i class="nav__icon nav__icon--dropdown"></i>
</div>
<ul class="details-search nav__menu js-dropdown-menu">
<li (click)="optionSelected($event, 1)">
<a class="nav__link">Option 1</a>
</li>
<li (click)="optionSelected($event, 2)">
<a class="nav__link">Option 2</a>
</li>
<li (click)="optionSelected($event, 3)">
<a class="nav__link">Option 3</a>
</li>
</ul>
</li>
</div>
Does anyone have any insight to the class js-dropdown and js-dropdown-menu and how to fix them after this upgrade?
Update: so i think i found out where the js-dropdown style class comes from.... it doesn't come from any style... it's just used as a label and component.js looks for that label to show or hide it. The now is that component.js function isn't getting called. Anyone know how to fix this?
$('#app-container').on('click', '.js-dropdown, .js-dropdown-menu > *', function(event){
event.preventDefault();
var that = this;
var parent = $(this).closest('.is-parent');
//is our dropdown open?
if(!parent.hasClass('is-open')){
//... then open it.
parent.addClass('is-open');
//handle clicking away
$(document).one('click', function closeMenu(docEvent){
//if the parent does not contain the clicked element...
if($(parent).has(docEvent.target).length === 0) {
//close it.
parent.removeClass('is-open');
} else {
// else, set up another listener to check the next user click.
$(document).one('click', closeMenu);
}
});
} else {
// ...else we close it.
parent.removeClass('is-open');
}
event.stopPropagation();});
Figured it out. We were not loading a components.js file (as well as other scripts) in the angular.json file. Our previous version of angular did not contain an angular.json file.

How to select between an actual routerLink and an internal anchor with Angular 8?

I have an array of items, which looks like this:
nav: any = [
{
name: 'Homepage',
url: 'homepage'
internal: false
},
{
name: 'Section 1',
hash: 'section-1'
internal: true
},
];
Now I need to ouput a list of a-elements. These should either contain a routerLink if internal is false – or they should become an internal anchor. I've tried:
<a class="link"
*ngFor="for item of nav"
[href]="item.internal ? '#' + item.hash : null"
[routerLink]="item.internal ? null : item.url">
{{ item.title }}
</a>
This renders homepage correctly, but Section 1 comes out wrongly:
<a class="link" href="/homepage">Homepage</a>
<a class="link" href="/">Section 1</a>
This is what I actually want:
<a class="link" href="/homepage">Homepage</a>
<a class="link" href="#section-1">Section 1</a>
How to achieve this correctly?
Try this...
<a class="link" *ngFor="for item of nav" [routerLink]="item.internal ? '#' + item.hash : item.url">
{{ item.title }}
</a>
The routerLink replaces by href after render.
why not conditionally, use one or the other?
<ng-container *ngIf="internal">
show appropriate link
</ng-container>
<ng-container *ngIf="!internal">
show appropriate link
</ng-container>

switching bootstrap class of hyperlinks with angular

I have several hyperlinks on the page
<a href="#" class="list-group-item list-group-item-action active" routerLink='/route1' >First Link</a>
<a href="#" class="list-group-item list-group-item-action" routerLink='/route2' >Second Link</a>
<a href="#" class="list-group-item list-group-item-action" routerLink='/route3' >Third Link</a>
First link is highlighted because has class "active". while pressing each link I have some actions, but the first link stays active anyway.
Now how can I move active class to the corresponding link that has being pressed ?
use routeLinkActive directive like this
First Link
Second Link
Third Link
Use ngClass for conditionally switching active element:
https://angular.io/api/common/NgClass
Add (click) action to every a element, and inside called function set active element:
First Link
Second Link
Third Link
in ts file:
activeItem: string;
setActiveItem(activeItem: string): void {
this.activeItem = activeItem;
}

Angular 6 routerLinkActive not working

I am building a site using Angular 6 and have been stuck for a few days now on a problem. I am trying to change text color (list items) on a navbar based on the active page. I have seen examples on how to do this using AngularJS and javascript. I have come across the routerActiveLink library documentation at https://angular.io/api/router/RouterLinkActive library for Angular 5+ which seems to be a simple solution, but it is not working for me. I have tried many different examples I have seen online and none have worked. Am I missing something? Here are some code snippets:
header.component.html
<div class="navbar-collapse collapse navbar-nav pull-right" id="navbar">
<ul class="navbar-nav" style="align-items: center;">
<li class="main-links" [routerLinkActive]="['active']">
<a class="al" [routerLink]="['home']" id="home-button" href="home">Home</a>
</li>
<li class="main-links">
<a class="al" routerLink="/about" routerLinkActive="active" id="about-button" href="about">About</a>
</li>
<li class="main-links">
<a class="al" id="blog-button" href="https://tspace.web.att.com/blogs/financelive/?lang=en_us" target="_blank">Blog</a>
</li>
<li class="main-links">
<a class="al" routerLink="/albums" routerLinkActive="active" id="albums-button" href="albums">Platinum Albums</a>
</li>
<li class="main-links">
<a class="al" routerLink="/programs" routerLinkActive="active" id="programs-button" href="programs">Development Programs</a>
</li>
<li class="main-links">
<a class="al" routerLink="/contact" routerLinkActive="active" id="contact-button" href="contact">Contact Us</a>
</li>
</ul>
This is my declaration for active in header.component.less:
.active {
color: #009fdb;
font-family: font-bold;
}
When I use [routerLinkActive] with the brackets, the page does not load at all, and when I user routerLink and routerLinkActive in the a tag, it does not register at all. Are there some imports I am missing. I have tried importing router, routerlinkactive, and routerlink from #angular/core.
I purposely left both different styles of using routerLinkActive in the code example. It was not like this when I actually ran it.
I have Angular 6, bootstrap 4.1.1, jquery 3, and popperjs installed.
After further review, I have discovered that routerLinkActive works correctly on elements inside the root app-module. I created a new module for my header and footer called UiModule and the functionality is not working inside the header. Any ideas on how to get routerLinkActive to work on this module?
Try importing RouterModule into your UiModule, it won't be able to make use of that imported in your app.module.ts file
import { RouterModule } from '#angular/router';
// some other imports here
#NgModule({
imports: [
RouterModule
],
exports: [
// export UI components
],
declarations: [
// declare UI components
]
})
When I had this issue, I imported everything right. It took me days before I figured the problem was from how I structured my HTML
<li class="nav-list">
<a routerLinkActive="active"
[routerLinkActiveOptions]="{exact: true}"
routerLink="/"
href="/">
<i class="material-icons nav-link-icon">person</i>
<span class="nav-link-text">Profile</span>
</a>
</li>
The problem there was that I was watching for the .active class to appear in the li element while it had always been appearing in the anchor element. Just be sure that is not what is happening in your case.