mat-nav-list: routerLinkActive class applied after click - css

I have a mat-nav-list in my application that displays the menu on the left. I have added routerLinkActive="selected-item" to it to highlight the currently selected menu item.
Whenever a menu item is clicked, the class is not applied. It gets applied only after I click somewhere else in the page.
Below is the snippet of my code:
<mat-nav-list (click)="menuItemClicked()" class="menu-list">
<a *ngFor="let menuItem of menuItems" mat-list-item
[routerLink]="menuItem.routerLink" routerLinkActive="selected-item">
<mat-icon [svgIcon]="menuItem.icon" matListIcon></mat-icon>
<span>{{ menuItem.label }}</span>
</a>
</mat-nav-list>
.selected-item {
border-top-left-radius: 7px;
border-bottom-left-radius: 7px;
background-color: #f47431;
}
Here's a Stackblitz which reproduces the issue: https://stackblitz.com/edit/angular-wuabhz?file=src/app/list-single-selection-example.html
Select one of the boot items and click somewhere else and you'll see the class selected-item gets applied.
Is there a way to overcome this issue or am I missing something?

#prerak-sola
I noticed the same.
The reason for this is that the item still have ':focus' until you click somewhere else.
You could
1. use the same color on the 'item-active' as mat-list-item:focus
(if you don't have a need for a darker shade or different color)
.active-link {
background-color: rgba(0,0,0,0.1);
}
.mat-nav-list .mat-list-item:focus{
/* default bg color */
background-color: rgba(0,0,0,0.87);
/* ovrride bg color to match your item-active*/
background-color: rgba(0,0,0,0.1);
}
<!-- list item is '<a mat-list-item>' -->
'a mat-list-item'
<mat-nav-list>
<a mat-list-item *ngFor="let link of links" [routerLink]="link.path" routerLinkActive="active-link">{{ link.name }}</a>
</mat-nav-list>
2. Or probably better wrap your list-item in a <mat-list-item>
note that the 'routerLinkActive' is placed in the <mat-list-item>
this will override the 'background-color' from .mat-list-item:focus
<!-- list item is '<mat-list-item>' -->
'a mat-list-item'
<mat-nav-list>
<mat-list-item *ngFor="let link of links" routerLinkActive="active-link">
<a matLine [routerLink]="link.path" style="width: 100%;">{{ link.name }}</a>
<button mat-icon-button>
<mat-icon>info</mat-icon>
</button>
</mat-list-item>
</mat-nav-list>
.active-link {
background-color: rgba(0,0,0,0.1);
}
// .mat-nav-list .mat-list-item:focus{
// background-color: rgba(0,0,0,0.1);
// }

Related

The first menu is not showing in mat-toolbar if its sub menu is empty by using angular material

I want to create a nested menus. The top menu bar has 4 elements.
DevFestFL
Disney
Orlando
Maleficent
The first one doesn't have child menu and the rest of them have children. Now the issue is the first menu is not showing or its color is eaten by the background color. I think that I may need to change the code but not sure.
<mat-menu #childMenu="matMenu" [overlapTrigger]="false">
<span *ngFor="let child of items">
<!-- Handle branch node menu items -->
<span *ngIf="child.children && child.children.length > 0">
<button mat-menu-item color="primary" [matMenuTriggerFor]="menu.childMenu">
<mat-icon>{{child.iconName}}</mat-icon>
<span>{{child.label}}</span>
</button>
<app-menu-item #menu [items]="child.children"></app-menu-item>
</span>
<!-- Handle leaf node menu items -->
<span *ngIf="!child.children || child.children.length === 0">
<button mat-menu-item [routerLink]="child.route">
<mat-icon>{{child.iconName}}</mat-icon>
<span>{{child.label}}</span>
</button>
</span>
</span>
</mat-menu>
StackBlitz Demo
Add below style in app.component.scss, It will fix the issue.
.menu-bar .mat-button.mat-primary {
color: white;
}
Check the modified working code.
https://stackblitz.com/edit/dynamic-nested-topnav-menu-j4hu3k?file=app/app.component.scss

VueJS Router Active Link Style to all elements inside the router-link

In my sidebar, there are some <router-link>and I want their style is to be different when they are active. I am using router active-class for the <router-link> but the other elements inside the router-link are not taking some css properties. Here is my <router-link> looks like;
<router-link tag="li" to="/dashboard" class="nav-item has-treeview" active-class="active">
<a class="nav-link" id="dashboard_tab">
<i class="sidebar-icons">dashboard</i>
<p class="sidebar-links" active-class="active-p">Dashboard</p>
</a>
</router-link>
And here is my .active class;
.active {
background-color: #FF7400;
border-color: #FF7400;
border-radius: 4px;
color: white;
}
Now when a specific link is clicked and active, I have orange background and some border around that router-link. But my problem is, I also want the color of the icon and the p element is to be white, but they are not being effected by the color: white; property. What am I missing? active-class is only working for the router-link element so I cannot use it in the i or p. What should i do?

How do I change the style of a single button inside a *ngFor in Ionic 3?

I am trying to change the style of the specific button I click in the *ngFor in the ion-col. Currently when I click on a button, the styles for all buttons changes at the same time.
Here are my codes:
<ion-col *ngFor="let item of displayRestaurant[0].seatTimeSlotAndDiscount | slice:indexStart:indexEnd; let i=index" no-padding>
<button ion-button style="border-radius:100px;height:70px;width:70px;text-align:center;" (click)="clickedDiscount(item)" [ngClass]="clickedDiscountBoolean ? 'discountClicked' : 'discountUnclicked'">
<p style="font-size: 10px; color:white;">{{item.percentageDiscount}}</p>
<p style="font-size:10px;color:white;">{{item.timeOfDiscount}}</p>
</button>
</ion-col>
SCSS:
.discountClicked{
border: 3px solid orange;
}
.discountUnclicked{
border:none;
}
.ts:
clickedDiscount(discount:Discount){
this.clickedDiscountBoolean = !this.clickedDiscountBoolean;
}
Originally it is like this:
Here is what my current codes do after I clicked on any of the buttons (The new style is applied to all):
What I am looking for is, when I click on any of the buttons, only that button's style will change, and the rest will not.
All your buttons look up for same condition. You need to unify that condition to be true for only one button. You can use index value for that :
<ion-col *ngFor="let item of displayRestaurant[0].seatTimeSlotAndDiscount | slice:indexStart:indexEnd; let i=index" no-padding>
<button ion-button style="border-radius:100px;height:70px;width:70px;text-align:center;"
(click)="clickedDiscount(item,i)"
[ngClass]="clickedIndex === i ? 'discountClicked' : 'discountUnclicked'">
<p style="font-size: 10px; color:white;">{{item.percentageDiscount}}</p>
<p style="font-size:10px;color:white;">{{item.timeOfDiscount}}</p>
</button>
</ion-col>
Then in your component
clickedDiscount(discount:Discount,index:number){
this.clickedIndex = index;
}

How to hover ion-card inside ion-list

I have an ion-list which have a button and card inside it, now I want to change the color of the button and card on hover but can't find a way to do it.
Here is my code. Thanks in advance
Html
<div [hidden] = hidden >
<ion-list>
<ion-card >
<button inset = true *ngFor="let item of items" (click)="open($event, item.name)" >
<ion-card>
<h2> <b>{{ item.name }} </b> </h2>
<p> Recommended for</p>
{{item.Description}}
</ion-card>
<br>
<br>
</button>
</ion-card>
</ion-list>
</div>
CSS
ion-card{
display: flex;
flex-direction: column;
width: 100% !important;
margin: 0 !important;
background-color:white;
box-shadow: none;
}
button.item:hover a{
background-color: slategray;
box-shadow: inset 0px 0px 0px 1px red;
}
First of all u can't hover on device but u can attach click events for that u need to use ngStyle in ur components to change color or show if its clicked.
<div [hidden] = hidden >
<ion-list *ngFor="let item of items">
<ion-card >
<ion-button (click)="open($event, item.name)" fill="clear" >
<ion-icon slot="icon-only" [name]="buttonIcon" [ngStyle]="{'color':color1}"></ion-icon>
</ion-button>
<ion-card>
<h2> <b>{{ item.name }} </b> </h2>
<p> Recommended for</p>
{{item.Description}}
</ion-card>
<br>
<br>
</button>
</ion-card>
</ion-list>
</div>
inside ur TS
buttonIcon: string = "md-add";
color1: string = "black";
open(event,item){
this.buttonIcon = "done-all"; // icon change name if u want to change icon too
this.color1 ="red"; // any color u want it to change to
//rest of your code
}
U can use the same ngstyle on ur ion card as well to change color.
U can also use ion-ripple-effect to show some sort of click feedback on cards.

angular-bootstrap dropdown on mouseenter and keep dropdown-menu from hiding before being clicked.

First, I'm aware of this posts:
Activating bootstrap dropdown menu on hover
Bootstrap Dropdown with Hover
How to make twitter bootstrap menu dropdown on hover rather than click
And others, but still not found the correct solution yet, here's what I did so far.
first I used the is-open attribute from the angular-bootstrap dropdown directive like this:
<span class="dropdown" dropdown is-open="status.isopen">
<a
href
class="dropdown-toggle"
ng-mouseenter="status.isopen = true"
ng-mouseleave="status.isopen = false"
>
hover me for a dropdown with angular-bootstrap
</a>
<ul
class="dropdown-menu"
>
<li ng-repeat="choice in items">
<a href>{{choice}}</a>
</li>
</ul>
</span>
that seemed to work but 2 bugs appeared:
the first is when dropdown-toggle element is clicked the dropdown menu is gone clicking again wont bring it back you have to mouseleave then mouse enter the dropdown-tooggle to get the dropdown-menu back.
the second is a css/html problem.
Usually the regular css solution for a dropdown is like this:
<a class="css-dropdown">
hover here with css.
<div class="css-dropdown-menu">
<p>item 1</p>
<p>item 2</p>
<p>item 3</p>
</div>
</a>
Notice the dropdown-menu now is inside the dropdown-toggle element which mean when moving with the mouse from the dropdown-toggle to the dropdown-menu it's moving from parent to child, so basically we still hovering over the dropdown-toggle since we are in it's child, which mean the dropdown-menu will still be visible, on other hand, the bootstrap dropdown works with the click event so having the dropdown-menu as a child of the dropdown-toggle is not needed, but now when someone wants to change the behavior to mouseenter/hover once the mouse leaves the dropdown-toggle the dropdown-menu disappear so we no longer have access to the dropdown-menu elements this is visible in this plunker
To fix the first bug, I just removed the dropdown directive then replaced the is-open with ng-class directive like this.
Change this:
<span class="dropdown" dropdown is-open="status.isopen">
to this:
<span class="dropdown" ng-class="{'open': status.isopen}">
The rest stays the same plunker that fixed the first bug.
The second bug is tricky, since the dropdown-menu is no longer a child of the dropdown-toggle the hover effect wont last while moving from the toggle to the menu, so I did this.
Changed this:
<ul class="dropdown-menu">
to this:
<ul
class="dropdown-menu"
ng-mouseenter="status.isopen = true"
ng-mouseleave="status.isopen = false"
>
That did it but another bug appeared when clicking the dropdown-menu item it stays open, so I kept hacking by doing this.
changed this:
<li ng-repeat="choice in items">
to this:
<li ng-repeat="choice in items" ng-click="status.isopen = false">
That give me the required behavior plunker.
That said, this is not a good solution since a lot of directives are involved here for a simple visual effect, the last plunker I provided contains a css solution with no Bootstrap or AngularJS involved, though it is the required behavior it is not the required html structure or visual result, what I need is to have a space between the dropdown-toggle and the dropdown-menu not a padding of the toggle element just an empty space, which make the css solution not valid in this situation.
So, my question is there a better way of doing this without adding a new plugin/library more clean and easily reusable solution for the hover drop down menu?
First, have the toggling on the top-most parent element (in this case, the <span>)
<span class="btn-group" dropdown is-open="status.isopen" ng-mouseenter="status.isopen = true" ng-mouseleave="status.isopen = false">
<a class="btn btn-primary dropdown-toggle" dropdown-toggle>
Button dropdown <span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
<li>Action</li>
<li>Another action</li>
<li>Something else here</li>
<li class="divider"></li>
<li>Separated link</li>
</ul>
</span>
This will allow the behavior you wanted - while still allowing clicking to show/hide the menu ;-)
However there's an annoyance: if you move the mouse cursor slower and pass the small gap between the toggle and menu, it will hide the menu.
So secondly, add a small CSS to remove the gap
.dropdown-menu {
margin-top: 0;
}
See the action in this plunker.
I know you want a solution without adding a new plugin/library, but you (or others seeking for this behavior) might want to try using No Close from Dropdown Enhancements lib to keep the dropdown open even after clicking in one of its options:
Do not close the menu on click on radio add class .noclose.
<div class="btn-group">
<button data-toggle="dropdown" class="btn btn-default dropdown-toggle">
Checked option <span class="caret"></span>
</button>
<ul class="dropdown-menu noclose">
<li>
<input type="radio" id="gr1_1" name="gr1" value="1">
<label for="gr1_1">Option 1</label>
</li>
<li>
<input type="radio" id="gr1_2" name="gr1" value="2">
<label for="gr1_2">Option 2</label>
</li>
<li>
<input type="radio" id="gr1_3" name="gr1" value="3">
<label for="gr1_3">Option 3</label>
</li>
</ul>
</div>
Also add a CSS solution for the hovering problem:
.btn-group:hover .dropdown-menu.noclose {
display: block;
}
.dropdown-menu.noclose {
margin-top: 0px;
}
And, of course, don't forget to import the libs:
<script src="./js/dropdowns-enhancement.min.js"></script>
<link href="./css/dropdowns-enhancement.css" rel="stylesheet"\>
In your case I suggest you to study the Dropdown Enhancements's source code to see how it works and maybe find a more suitable solution.
Try adding this line to your css:
.btn-group:hover>.dropdown-menu { display: block; margin-top: 0; }
You'll have to remove your is-open, ng-mouseenter and ng-mouseleave directives.
Below is the solution I came up with, while working on the same issue.
I used a simple custom directive that:
binds the mouseenter and mouseleave events to the dropdown in order correctly to show/hide the menu.
dynamically adds a custom CSS class to the dropdown menu in order to prevent the menu from disappearing when moving the cursor from the button to the menu. Note that this solution has the advantage of not removing the visual gap between the button and menu.
prevents the menu from disappearing when the button is clicked.
The CSS rule uses a before pseudo-element to fill the gap between the button and the menu. I added the border property which can be uncommented to easily get a visual feedback.
.dropdown-hover-menu::before {
content: '';
position: absolute;
left: 0;
width: 100%;
top: -3px;
height: 3px;
/*border: 1px solid black;*/
}
The HTML structure of the snippet is based on the available examples in the dropdown section of the angular-ui bootstrap documentation
angular.module('app', ['ui.bootstrap'])
.directive('dropdownHover', function() {
return {
require: 'uibDropdown',
link: function(scope, element, attrs, dropdownCtrl) {
var menu = angular.element(element[0].querySelector('.dropdown-menu')),
button = angular.element(element[0].querySelector('.dropdown-toggle'));
menu.addClass('dropdown-hover-menu');
element.bind('mouseenter', onMouseenter);
element.bind('mouseleave', onMouseleave);
button.bind('click', onClick);
function openDropdown(open) {
scope.$apply(function() {
dropdownCtrl.toggle(open);
});
}
function onMouseenter(event) {
if (!element.hasClass('disabled') && !attrs.disabled) {
openDropdown(true);
}
};
function onMouseleave(event) {
openDropdown(false);
};
function onClick(event) {
event.stopPropagation();
}
scope.$on('$destroy', function() {
element.unbind('mouseenter', onMouseenter);
element.unbind('mouseleave', onMouseleave);
button.unbind('click', onClick);
});
}
};
});
.dropdown-hover-menu::before {
content: '';
position: absolute;
left: 0;
width: 100%;
top: -3px;
height: 3px;
/*border: 1px solid black;*/
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.3/ui-bootstrap-tpls.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div ng-app="app">
<div class="btn-group" uib-dropdown dropdown-hover>
<button type="button" class="btn btn-primary dropdown-toggle">
Button dropdown <span class="caret"></span>
</button>
<ul class="dropdown-menu" uib-dropdown-menu role="menu">
<li role="menuitem">Action
</li>
<li role="menuitem">Another action
</li>
<li role="menuitem">Something else here
</li>
<li class="divider"></li>
<li role="menuitem">Separated link
</li>
</ul>
</div>
</div>

Resources