I have an API that load Menu String Looks Like :
<li class="menu-title">
<span>Menus</span>
</li><ul><li class="submenu" [ngClass]="{ 'active' : urlComplete.mainUrl === 'users' }" mCode="SYSTEM" >
<a href="javascript:" [ngClass]="{ 'subdrop' : urlComplete.mainUrl === 'users' }" class="">
<i class='la la-windows'></i>
<span>
System
</span>
<span class="menu-arrow">
</span>
</a>
<ul style="display: none;" [ngStyle]="{ 'display' : urlComplete.mainUrl === 'users' ? 'block' : 'none' }" class=""><li routerLink="/users/user/list" class="" mCode="USERS" >
<a [ngClass]="{ 'active' : urlComplete.subUrl === 'user' }" href="javascript:" class="">
Users
</a>
</li><li routerLink="/users/user/create" class="" mCode="MENU" >
<a [ngClass]="{ 'active' : urlComplete.subUrl === 'menu' }" href="javascript:" class="">
Menus
</a>
</li> </ul>
</li>
</ul><li> <hr> </li>
I want to place this on Agular HTML page. Its shows fine but router link does not work. I understood that its not compile because of dynamic loading.
My front end code below :
ngAfterViewInit(): void {
this._getPermittedMenu();
}
_getPermittedMenu(){
let apiURL = this.baseUrl + "/common/getAuthMenus";
let queryParams: any = {};
this.loginService.sendGetRequest(apiURL,queryParams).subscribe((response: any) => {
// append response
let unFormattedData = response.data;
let data = unFormattedData.replace(/^\s+|\s+$/g, "");
//compile string to html element and sanitize it
this.menuData = this.sanitizer.bypassSecurityTrustHtml(data);
// this.menuData =(this.sanitizer.bypassSecurityTrustHtml(data));
// console.log("REques menu data");
// console.log(this.menuData);
});
}
and I m calling this from
<div id="sidebar-menu" [innerHTML]="menuData" class="sidebar-menu">
The problem is menus show but routerLink can not work link click
I provide some screenshots:
Related
I am building a single page application using vue.js with materialize and I have a navbar with tabs to navigate to different pages on my website. Materialize's tabs has an active property that displays which tab is currently selected. Every thing this far works perfectly.
This is materialize's tabs reference
The Issue
If you refresh the web page the tabs active property 'resets' to its default position. So I am trying to figure out how to persist the state of the navbar's active property and then reassign it to router-link.
My Code
<ul id="tabs" class="tabs tabs-transparent" :class="{ 'navbar--color': !changeNavColor }">
<li class="tab" id="home">
<router-link
id="home"
class="link"
:class="{ 'navbar--color': !changeNavColor }"
to="/"
>Home</router-link>
</li>
<li class="tab" id="services">
<router-link
id="services"
class="link"
:class="{ 'navbar--color': !changeNavColor }"
to="Services"
>Service</router-link>
</li>
<li class="tab" id="Preapproved">
<router-link
id="Preapproved"
class="link"
:class="{ 'navbar--color': !changeNavColor }"
to="PreApproved"
>Get Pre-Approved</router-link>
</li>
<li class="tab">
<router-link
id="cars"
class="link"
:class="{ 'navbar--color': !changeNavColor }"
to="Cars"
>inventory</router-link>
</li>
<li class="tab">
<router-link
id="testimonials"
class="link"
:class="{ 'navbar--color': !changeNavColor }"
to="Testimonials"
>Testimonals</router-link>
</li>
</ul>
if (localStorage.currentTab) {
this.currentTab = localStorage.currentTab;
var activeTab = document.getElementById(this.currentTab);
activeTab.classList.add("active");
console.log("saved");
}
$(document).ready(function() {
$("a").click(function(event) {
this.currentTab = event.target.id;
console.log(this.currentTab);
});
});
$(document).ready(function() {
$(".tabs").tabs();
});
window.addEventListener("scroll", this.onScroll);
},
beforeDestroy() {
window.removeEventListener("scroll", this.onScroll);
},
watch: {
currentTab(newTab) {
console.log("watch");
localStorage.currentTab = this.currentTab;
}
}
any help is appreciated
So I think you can use hash mechanism by using window.location.hash. You can put the data-toggle attribute in every tag anchor. And just check for location.hash !== ''
But the more Vue way would be through client side storage. Check the link its from vue docs. Although it is for the input field but you will get the idea of how to persist info by keeping a reference in client storage and on reload getting your desired state from there onward. Hope it helps.
Remove the indicator that is nested inside the first li, and the navigation works fine.
<ul id="tabs" class="tabs tabs-transparent">
<li id="tab" class="tab">
Home
<li class="indicator"></li> <!-- THIS RANDOM NESTED INDICATOR IS THE ISSUE -->
</li>
<li id="tab" class="tab">
Service
</li>
<li id="tab" class="tab">
Get Pre-Approved
</li>
<li id="tab" class="tab">
inventory
</li>
<li class="indicator" style="right: 488px; left: 0px;"></li> <!-- CORRECT INDICATOR, AUTOMATICALLY GENERATED BY MATERIALIZE -->
</ul>
This is how I ended up implementing this. First all of your router-links or <a> have to have unique id's
mounted() {
if (localStorage.currentTab) {
this.currentTab = localStorage.currentTab;
var element = document.querySelector(this.currentTab);
element.classList.add("active");
}
$(document).ready(function() {
$(".tabs").tabs();
$("a").click(function(event) {
this.currentTab = "#" + event.target.id;
localStorage.currentTab = this.currentTab;
});
});
},
watch: {
currentTab(newTab) {
localStorage.currentTab = this.currentTab;
}
}
Code:
<div class="input-dropdown-wrapper d-flex space-between vertical-center margin-right-12"
ng-class="{'active': historyController.showFilterHistoryDurationDropdown === true}"
ng-click="historyController.showFilterHistoryDurationDropdown = true"
when-clicked-off="historyController.showFilterHistoryDurationDropdown = false">
<p>
Show {{historyController.filter}}
</p>
<i class="fas fa-angle-down"></i>
<ul class="input-dropdown"
ng-if="historyController.showFilterHistoryDurationDropdown">
<li ng-class="{'active': historyController.filter === 'All'}"
ng-click="historyController.filter = 'All';
historyController.showFilterHistoryDurationDropdown = false">
Show All
</li>
<li ng-class="{'active': historyController.filter === 'In Progress'}"
ng-click="historyController.filter = 'In Progress';
historyController.showFilterHistoryDurationDropdown = false">
Show In Progress
</li>
<li ng-class="{'active': historyController.filter === 'Completed'}"
ng-click="historyController.filter = 'Completed';
historyController.showFilterHistoryDurationDropdown = false">
Show Completed
</li>
</ul>
</div>
All of this works perfectly. When the <div class="input-dropdown-wrapper...> gets clicked, the <ul> appears as it should.
What I don't understand is why the second part of the ng-click of each <li> doesn't work at all.
Specifically talking about this part: historyController.showFilterHistoryDurationDropdown = false".
Setting this value to false should hide the <ul>, just like when you click the <div>, it sets the value to true, causing the <ul> to appear.
If you are looking for some Toggle view solution, ng-click logic should toggle the showFilterHistoryDurationDropdown value Like :
ng-click="historyController.showFilterHistoryDurationDropdown
? historyController.showFilterHistoryDurationDropdown = false
: historyController.showFilterHistoryDurationDropdown = true"
So that when you click on the div having the ng-class will show the list (<ul>), on second click it will hide the list (<ul>)
So your final code should look something like:
<div class="input-dropdown-wrapper d-flex space-between vertical-center margin-right-12"
ng-class="{'active': historyController.showFilterHistoryDurationDropdown === true}"
ng-click="historyController.showFilterHistoryDurationDropdown ? historyController.showFilterHistoryDurationDropdown = false : historyController.showFilterHistoryDurationDropdown = true"
when-clicked-off="historyController.showFilterHistoryDurationDropdown = false">
<p>
Show {{historyController.filter}} <br>
showFilterHistoryDurationDropdown : {{historyController.showFilterHistoryDurationDropdown}}
</p>
<i class="fas fa-angle-down"></i>
<ul class="input-dropdown"
ng-if="historyController.showFilterHistoryDurationDropdown">
<li ng-class="{'active': historyController.filter === 'All'}"
ng-click="historyController.filter = 'All';
historyController.showFilterHistoryDurationDropdown = false">
Show All
</li>
<li ng-class="{'active': historyController.filter === 'In Progress'}"
ng-click="historyController.filter = 'In Progress';
historyController.showFilterHistoryDurationDropdown = false">
Show In Progress
</li>
<li ng-class="{'active': historyController.filter === 'Completed'}"
ng-click="historyController.filter = 'Completed';
historyController.showFilterHistoryDurationDropdown = false">
Show Completed
</li>
</ul>
Hope this helps.. :)
Here is my code:
Buttons:
<li ><a data-ng-click="Data1 = true;Data2 = false; search.status = ''" href="">ALL PROJECTS</a></li>
<li ><a data-ng-click="Data2 = true;Data1 = false" href="">NOTIFICATIONS</a></li>
Populated data on click of button:
<ul>
<li ng-show="Data1" dir-paginate="wd in workOrdersList | filter: search.status | filter: search.name | itemsPerPage: 10">
<a href="">
<h4>{{wd.name}}</h4>
</a>
<p>Status: {{wd.status}}</p>
</li>
<li ng-show="Data2">
<div ng-show="!notificationDataDashord.length">
<span>No Notifications</span>
</div>
</li>
</ul>
<dir-pagination-controls auto-hide="true"></dir-pagination-controls>
Inside the controller:
$scope.Data1 = true;
$scope.Data2 = false;
I am using pagination directive from this link:
https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination
Its a problem with the dirpagination that it doesnt update the collections after you load the data again.
See
https://github.com/michaelbromley/angularUtils/issues/208
https://github.com/michaelbromley/angularUtils/issues/137
As a work around obviously
<dir-pagination-controls ng-show="Data1" auto-hide="true"></dir-pagination-controls>
i create simple application. And i add rating feature.
I want to change the rating star class when click event is triggered from controller.
In my Controller i check if the rating of object == passed number from view, i return class name active.
After that, i still confused how i pass my return value.
Here is my View
<h3>{{ fruit.title }}</h3>
<div class="rating">
<ul>
<li ng-click="addRating(1,fruit)"><i class="glyphicon glyphicon-star-empty"></i></li>
<li ng-click="addRating(2,fruit)"><i class="glyphicon glyphicon-star-empty"></i></li>
<li ng-click="addRating(3,fruit)"><i class="glyphicon glyphicon-star-empty"></i></li>
<li ng-click="addRating(4,fruit)"><i class="glyphicon glyphicon-star-empty"></i></li>
<li ng-click="addRating(5,fruit)"><i class="glyphicon glyphicon-star-empty"></i></li>
</ul>
</div>
And here is my Controller :
var app = angular.module('totalBuahApp', []);
app.controller('fruitController', function($scope) {
$scope.fruits = [
{
title : 'Fresh Red Apple',
img : 'https://cdn0.iconfinder.com/data/icons/fruits/512/Apple.png',
description : 'Good for your daily consumption.',
price : 15000,
cartQty : 1,
rating : 0
},
{
title : 'Red Grape',
img : 'http://www.freepngimg.com/thumb/grape/4-grape-png-image-download-picture-thumb.png',
description : 'Like a king.',
price : 34000,
cartQty : 1,
rating : 0
}
];
$scope.total = $scope.fruits.length;
$scope.addRating = function(number, fruit) {
fruit.rating = number;
};
$scope.ratingClass = function(number) {
return (number == $scope.rating) ? "active" : "";
};
});
You can check my fullcode in
https://codepen.io/fanjavaid/pen/MaRWgG
Don't duplicate HTML for every star, use ngRepeat with ngClass:
<div class="rating">
<ul>
<li class="glyphicon glyphicon-star-empty"
ng-click="addRating($index + 1, fruit)"
ng-repeat="star in [0, 1, 2, 3, 4]"
ng-class="{active: fruit.rating >= $index + 1}"></li>
</ul>
</div>
Demo: https://codepen.io/anon/pen/RWOPad?editors=101
Replace your rating Div with the below div
<div class="rating">
<ul>
<li ng-click="addRating(1,fruit)"><i class="glyphicon glyphicon-star-empty" ng-class="{active:fruit.rating >= 1}"></i></li>
<li ng-click="addRating(2,fruit)"><i class="glyphicon glyphicon-star-empty" ng-class="{active:fruit.rating >= 2}"></i></li>
<li ng-click="addRating(3,fruit)"><i class="glyphicon glyphicon-star-empty" ng-class="{active:fruit.rating >= 3}"></i></li>
<li ng-click="addRating(4,fruit)"><i class="glyphicon glyphicon-star-empty" ng-class="{active:fruit.rating >= 4}"></i></li>
<li ng-click="addRating(5,fruit)"><i class="glyphicon glyphicon-star-empty" ng-class="{active:fruit.rating >= 5}"></i></li>
</ul>
and add .active class in your css.
Template:
<template name="header">
<div class="blog-masthead">
<div class="container">
<nav class="blog-nav">
<a class="blog-nav-item {{active}}" href="{{pathFor 'homePage'}}">Home</a>
{{#if currentUser}}
<a class="blog-nav-item {{active}}" href="#">{{Meteor.userId}}</a>
{{else}}
<a class="blog-nav-item {{active}}" href="{{pathFor 'loginPage'}}">Login</a>
<a class="blog-nav-item {{active}}" href="{{pathFor 'signUpPage'}}">Sign Up</a>
{{/if}}
<a class="blog-nav-item {{active}}" href="#">About</a>
</nav>
</div>
</div>
</template>
header.js
Template.header.events({
'click a': function(e) {
e.preventDefault();
this.active?"active":"";
}
});
I just want to make set click link's class as active. Clicked link class should look like class="blog-nav-item active".
The example below relies on iron-router and presents a reactive approach for adding the active class
First should modify the template to be:
<a class="blog-nav-item {{active 'homePage'}}" href="{{pathFor 'homePage'}}">Home</a>
And then the appropriate helper for it should be:
Template.name.helpers({
active: function(routeName) {
var curRoute = Router.current().route;
return curRoute.name === routeName ? 'active' : '';
}
});
Edit v1.0+
As of iron-router 1.0, A route's name is now accessible at
route.getName() (previously it was route.name).
In particular, you'll need to write return
curRoute.getName() === routeName ? 'active' : '';
Thank you #jrbedard for the notification
I guess this would be the "Meteor way" you wanted:
<template name="menu">
<ul>
<li class="{{#if isCurrentPage 'pageA'}}active{{/if}}">
Page A
</li>
<li class="{{#if isCurrentPage 'pageB'}}active{{/if}}">
Page B
</li>
<li class="{{#if isCurrentPage 'pageC'}}active{{/if}}">
Page C
</li>
</ul>
</template>
Router.onBeforeAction(function(){
Session.set('currentRouteName', Router.current().route.name)
})
Template.menu.helpers({
isCurrentPage: function(pageName){
return Session.equals('currentRouteName', pageName)
}
})
Router.current().route.name do evaluate to the current page name in the latest version of iron router, but I don't know if that's part of the public API one should use.
EDIT
Router.current() is apparently reactive, so all JavaScript code you need is the following:
Template.menu.helpers({
isCurrentPage: function(pageName){
return Router.current().route.name == pageName
}
})
You can solve it with JavaScript only:
Template.header.events({
'click .blog-nav-item': function(event, template){
// Remove the class 'active' from potentially current active link.
var activeLink = template.find('.blog-nav-item')
if(activeLink){
activeLink.classList.remove('active')
}
// Add the class 'active' to the clicked link.
event.currentTarget.classList.add('active')
}
})