How to add active class on current menu item page? - javascript

In my Meteor app I need to add class to navigation item when page is active.
How can I do that?

Template.header.helpers({
getActiveClass: function(routeName) {
var active = Router.current() && Router.current().route.getName() === routeName;
return active && 'active';
}
});
<li class="{{getActiveClass 'home'}}">
Home
</li>
Note if you want to make the element active for more than one route you have to modify the getActiveClass helper a little bit.

Add Package zimme:iron-router-active
Use as follows:
class="{{isActiveRoute regex='<route>'}}"
For example
<li class="{{isActiveRoute regex='dashboard'}}">
<a href="{{pathFor route='dashboard'}}"><i class="fa fa-th-large"></i> <span
class="nav-label">Dashboard</span> </a>
</li>
So whenever the Route is active, Link will be Active.

Related

Angular - how to use one function to manage multiple toggles / click events?

Please see attached image.
So, this is a navbar, where clicking on any of the tabs, the content below the nav will change based on which tab is selected.
Here is code for an example of how the function works for when click event is handled when Bespoke Manufacturing is clicked:
toggleBespoke() {
this.showBespoke = true;
this.showHow = false;
this.showCasting = false;
this.showForging = false;
this.showInjection = false;
this.showPressing = false;
this.showTurning = false;
}
As you can see, it's simple, the about showAbout variable is set to true whilst all the others are manually set to false.
ngClass is used which gives the blue highlighted effect so only one of the tabs gets highlighted when selected as only one can be true whilst others are false.
The same logic is then applied to the 6 other tabs.
But this is my question, what is the way to prevent code duplication and handle such click events in one function only?
You can use a property in your component which stores the active tab.
export class AlarmsComponent {
activeTab = 'bespoke';
}
And then you can use it in your template like this:
<ul class="tabs">
<li>
<a (click)="activeTab = 'bespoke'"
[ngClass]="{active: activeTab === 'bespoke'}"
>
Bespoke manufacturing
</a>
</li>
<li>
<a (click)="activeTab = 'how'"
[ngClass]="{active: activeTab === 'how'}"
>
How it works
</a>
</li>
</ul>
<div class="tab-bespoke" *ngIf="activeTab === 'bespoke'">
Bespoke manufacturing tab content
</div>
<div class="tab-how" *ngIf="activeTab === 'how'">
How it works tab content
</div>
Another solution (dirtier than the previous one) is to create a single function executed on click passing the $event param.
For instance you have something like the following to manage the nav item:
<li class="nav-item"><a id="bespoke" class="nav-link" href="#" tabindex="-1" (click)="onClick($event)">BESPOKE MANUFACTURING</a> </li>
And inside the class you have onClick function as the following:
onClick(ev){
let clickedId = ev.target.id;
//clickedId is the id of the clicked element and you can add class accordingly
if(clickedId === 'bespoke'){
//the user clicked the bespoke item
}
}
Create a variable to store the current active tab, in interaction with tab set current clicked tab to activeTab, then apply active inactive class using this variable ,for example in
app.component.ts
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
activeTab: string = 'tab1';
isActive(tabName){
return this.activeTab === tabName;
}
makeActive(tab){
this.activeTab = tab;
}
}
in Html
app.component.html
<ul class="nav nav-tabs">
<li class="nav-item">
<a [ngClass]="{'nav-link': true, 'active':isActive('tab1')}" (click)="makeActive('tab1')">Tab 1</a>
</li>
<li class="nav-item">
<a [ngClass]="{'nav-link': true, 'active':isActive('tab2')}" (click)="makeActive('tab2')">Tab 2</a>
</li>
<li class="nav-item">
<a [ngClass]="{'nav-link': true, 'active':isActive('tab3')}" (click)="makeActive('tab3')">Tab 3</a>
</li>
<li class="nav-item">
<a [ngClass]="{'nav-link': true, 'active':isActive('tab4')}" (click)="makeActive('tab4')">Tab 4</a>
</li>
</ul>
<div>
<div class="tab-bespoke" *ngIf="isActive('tab1')">
tab 1 content
</div>
<div class="tab-bespoke" *ngIf="isActive('tab2')">
tab 2 content
</div>
<div class="tab-bespoke" *ngIf="isActive('tab3')">
tab 3 content
</div>
<div class="tab-bespoke" *ngIf="isActive('tab4')">
tab 4 content
</div>
</div>
here is the running sample https://stackblitz.com/edit/angular-bootstrap-4-starter-cbrzm5
I'd go with the framework and actually use proper routing instead of hiding content by hand.
as a bonus, you'll get the current tab get set to automatically when the user refresh the page.

Adding an active state to list item using angular

I have the following HTML markup:-
<ul class="dropdown-menu">
<li ng-repeat="track in songTracks track by $index" ng-class="{active: $index===selectedIndex}">
<a ng-click="setSongTrack(track)">
{{track.name}}
</a>
</li>
</ul>
In Angular, I use this:-
$scope.setSongTrack = setSongTrack;
$scope.selectedIndex = 0;
$scope.index= function(i) {
$scope.selectedIndex=i;
};
Which passes to DASHJS like so:-
function setSongTrack(track) {
musicPlayer.setSongTrack(track);
$scope.selectedIndex = track;
}
musicPlayer being the instance of DASHJS, which parses my audio tracks. This all works - I get a bunch of list elements with the track names, I can click them and independently load each track as expected. However, I need to add some visual way of informing the user which track is currently selected, which is probably best done by way of adding a CSS 'active' class.
Currently this just sets an 'active' class to the first list element, regardless if I click another and it changes the track. If I click another list item, the 'active' class is removed from the first list item. I need the 'active' class to only be on the currently selected track, i.e. the selected list item.
Now I'm stumped. I've read over a lot of similar SO questions and haven't located something which I can get to work.
Can anyone enlighten me? Fairly new to Angular and so, I'm still a bit of a noob with it.
Instead of using the index of the track to mark it as selected, use the track itself. Write a function like trackSelected() which takes a track, and use that to apply a class with ngClass. Eg...
HTML
<ul class="dropdown-menu">
<li ng-repeat="track in songTracks track by $index" ng-class="{ 'active': isSelected(track)} ">
<a ng-click="setSongTrack(track)" ng-bind="track.name">
</a>
</li>
</ul>
JS
$scope.selectedTrack = null;
$scope.setSongTrack = function(track) {
musicPlayer.setSongTrack(track);
$scope.selectedTrack = track;
}
$scope.isSelected = function(track) {
return $scope.selectedTrack === track;
}
This is because you may add or remove tracks from the list in your view at some point, and then the selected index will be invalid.
just go like this:
<ul class="dropdown-menu">
<li ng-repeat="track in songTracks track by $index" ng-class="{active: track===selectedTrack}">
<a ng-click="setSongTrack(track)">
{{track.name}}
</a>
</li>
</ul>
and in your js
$scope.selectedTrack = undefined;
$scope.setSongTrack = function (track) {
musicPlayer.setSongTrack(track);
$scope.selectedTrack = track;
}
This way you can also do stuff like presenting the selected track in your player like below just with one click, no need to fiddle with indexes and such.
<h1>{{selectedTrack.name}}</h1>
<p>
<span>{{selectedTrack.totalTime}}</span>
</p>
Here is a simple fiddle
Alternate Solution
Going the $index way should be like this(Just explaining to help you see what you did wrong)
<ul class="dropdown-menu">
<li ng-repeat="track in songTracks track by $index" ng-class="{active: $index===selectedIndex}">
<a ng-click="setSongTrackIndex($index)">
{{track.name}}
</a>
</li>
</ul>
Notice that i chanced setSongTrack(track) to setSongTrackIndex($index). Then you would of course change your js accordingly, like so:
function setSongTrackIndex(trackIndex) {
musicPlayer.setSongTrack(songTracks[trackIndex]);
$scope.selectedIndex = trackIndex;
}
$scope.setSongTrack = setSongTrack;
$scope.selectedIndex = 0;
If you need further explanation please comment.

How to show and hide side menu in angular2

In my application i have to implement hide and show side menu. By default the page menu is open while clicking the toggle menu i have to hide the side menu. How can i implement this.
what i have is:
app.component.html, nav.component.html
<div class="menu-toggler sidebar-toggler">
<span></span>
</div>
<ul>
<li class="nav-item ">
<a class="nav-link nav-toggle">
<i class="icon-diamond"></i>
<span class="title">Name</span>
<span class="arrow"></span>
</a>
</li>
</ul>
Myservice.ts
export class GlobalService {
public collapse;
constructor() { }
setValue(val: boolean) {
this.collapse = val;
}
getValue() {
return this.collapse;
}
EDIT
app.component.html
<div *ngIf="!toggle()"class="menu-toggler sidebar-toggler">
<span></span>
</div>
app.component.ts
import { GlobalService } from "path";
export class AppComponent {
toggle() {
this.globalService.setValue(false);
}
}
how can i hide this list(in nav.html) while clicking menu toggle (app.compnent.html)? Any help will really appreciable. i am new to angular.
If use of service is not the priority then you can simply maintain simple variable to do this task.
Your app.component.ts
export class AppComponent {
showMenu : boolean = true;
}
Your app.component.html
<div (click)="showMenu = !showMenu" class="menu-toggler sidebar-toggler"><span></span>
</div>
<ul *ngIf="showMenu">
<!-- used showMenu to hide/show -->
<li class="nav-item ">
<a class="nav-link nav-toggle">
<i class="icon-diamond"></i>
<span class="title">Name</span>
<span class="arrow"></span>
</a>
</li>
</ul>
hope this helps ...
For this ,
You can make a CommonService to store the state of menu or and use that Service to make toggle you menu.
You can also use #Input #Output , in case you are having parent child relation between components.
Method will depend on how is your project/file structure.
You can create a service and preferably make a static variable inside to get and set the visibility state of the menu. By this you could directly set and get the variable by using ComponentName.variableName.
to play with the visibility you could use(Sorry if there is any syntax errors)
1> Set the document.getelementbyid("idofelement").display= none or block
2>use *ngIf="someboolean" where you should set the boolean in your ts file

GET Basename of URL then put active class to navbar

Example Link: http://localhost/test/page.php
I have a JavaScript code that will put an active class to a navbar if the url of that href ==== current_url.
Current JavaScript (Only puts active class to sidebar)
<script type="text/javascript">
jQuery(function($) {
var path = window.location.href; // because the 'href' property of the DOM element is the absolute path
$('ul a').each(function() {
if (this.href === path) {
$(this).addClass('sub-menu active');
$(this).parent().closest("li").addClass('active');
$(this).parent().parent().closest("li").addClass('active');
}
});
});
</script>
I want to make it work also if the link has a page.php?success. There will also be an active class as long as the page.php is there regardless of what is after the ?.
I've tried the following script below to extract the basename but now it doesn't work at all, pages with or without ?.
Tried script (Supposed to put active class to sidebar even if the url has page.php?success in it.
<script type="text/javascript">
jQuery(function($) {
var patharray = window.location.pathname.split( '/' );
var reallink = patharray[2];
$('ul a').each(function() {
if (this.href === reallink) {
$(this).addClass('sub-menu active');
$(this).parent().closest("li").addClass('active');
$(this).parent().parent().closest("li").addClass('active');
}
});
});
</script>
With the example link above. The script returns page.php And the href's inside the navbar are just page1.php, page2.php etc... So I know it should work since the retrieved reallink is equal to the href of the navbar.
My sidebar
<li class="sub-menu"> // Sidebar with no submenu
<a class="" href="page1.php">
<i class="icon-calendar"></i>
<span>This is page 1</span>
</a>
</li>
<li class="sub-menu"> // Sidebar with a submenu
<a href="javascript:;" class="">
<i class="icon-group"></i>
<span>This has sub pages</span>
<span class="arrow"></span>
</a>
<ul class="sub">
<li><a class="" href="page2.php">This is page 2</a></li>
<li><a class="" href="page3.php">This is page 3</a></li>
</ul>
</li>
So the first JavaScript puts an active class both to the parent and the child if the href = url is met. But with the 2nd script nothing works.
I guess changing this line in the First script will make it work
var path = window.location.href.split( '?' )[0];

Make all direct parent list entries selected in mmenu

I'm working on a project where I'm about to use the jQuery plugin mmenu (http://mmenu.frebsite.nl/).
I already had to do some customisations to fit my needs but I don't know what to do with my current issue. In mmenu, when i click on an list entry I will be navigated to the given href and the clicked item becomes active by mmenus css class ".mm-selected". So far so good.
Now I want to additionally mark the parent list item (and thats parent, and so on until menu root) as selected. This should be so when the user goes one level up in the menu he should be able to see in which category he currently is.
Below is an example of the menus html structure after mmenu was applied. This shows the code for a menu with 4 main pages (index, page1, page2 and page3) and 3 subpages (2.1, 2.2, 2.3).
<nav id="nav" class="mm-menu mm-horizontal mm-offcanvas mm-hasheader mm-current mm-opened">
<ul class="mm-list mm-panel mm-opened mm-current" id="mm-0">
<li class="mm-selected">
Index
</li>
<li>
Page 1
</li>
<li>
<a class="mm-subopen mm-fullsubopen" href="#mm-1"></a>
<span>Page 2</span>
</li>
<li>
Page 3
</li>
</ul>
<ul class="mm-list mm-panel mm-highest" id="mm-1">
<li class="mm-subtitle">
<a class="mm-subclose" href="#mm-0">Page 2</a>
</li>
<li>
Page 2.1
</li>
<li>
Page 2.2
</li>
<li>
Page 2-3
</li>
</ul>
</nav>
It would be great if you had some idea where and how I could achive such functionality.
So, for the moment I did some jQuery hacking. This seems to work for my case mentioned above. It should also work for deeper menus as it's using recursion. If there's a better way to achieve this, please let me know.
var nav = $("#nav");
nav.find("li > a:not(.mm-subopen)").click(function () {
nav.find("li.active").removeClass("active");
selectParentEntry($(this));
});
var selectParentEntry = function (a) {
var li = a.parent(),
ul = li.parent(),
back = ul.find("li > a.mm-subclose").first(),
cID = "#" + ul.attr("id"),
pID = back.length ? back.attr("href") : null;
li.addClass("active");
if (pID != null) {
var subOpen = nav.find("ul" + pID + " > li > a.mm-subopen").filter(function () {
var self = $(this);
if (self.attr("href") === cID) return self;
}).first();
if (subOpen) selectParentEntry(subOpen);
}
};

Categories