ng-click fires twice in directive controlled navigation - angularjs

I have a directive that I am using to render my navigation but there are two ng-clicks in it and both of them fire twice when clicked. I have read similar questions on here but still can't work it out. Any input would be much appreciated.
The html element
<nav ng-cloak ig-nav class="navbar navbar-default" role="navigation"></nav>
The js
.controller('navCtrl',
['$scope', function($scope){
console.log('navCtrl');
$scope.usermenu = false;
$scope.toggleMenu = function() {
var nv = !$scope.usermenu;
console.log(nv);
$scope.usermenu = nv;
};
}])
.directive('igNav', function() {
return {
restrict: 'A',
templateUrl: 'partials/nav.html',
controller: 'navCtrl'
};
})
And the nav template
<ul class="nav navbar-nav navbar-right">
<li ng-if="auth.user"><!--i class="icon-plus"></i--><span class="glyphicon glyphicon-plus"></span> Add</li>
<li ng-if="auth.user"><!--i class="icon-share"></i--><span class="glyphicon glyphicon-share"></span> Share</li>
<li ng-if="auth.user" class="dropdown" ng-class="{open: usermenu}">
{{user.name}} <strong class="caret"></strong>
<ul class="dropdown-menu">
<li><!--i class="icon-align-left"></i--><span class="glyphicon glyphicon-align-left"></span> Activity</li>
<li><!--i class="icon-truck"></i--><span class="glyphicon glyphicon-paperclip"></span> Shares</li>
<li class="divider"> </li>
<li><!--i class="icon-cog"></i--><span class="glyphicon glyphicon-cog"></span> My Profile</li>
<li><!--i class="icon-signout"></i--><span class="glyphicon glyphicon-minus-sign"></span> Logout</li>
</ul>
</li>
<li ng-if="!auth.user"><!--i class="icon-signin"></i--><span class="glyphicon glyphicon-user"></span> Login</li>
</ul>
As it has worked in charliefl's plnkr there must be some other reason it is firing twice. Here is some more info I thought was irrelevant but perhaps it is after all.
The app is running firebase and angularfire 0.5.
$route has been included.
Angular is manually inialized.
ignav is included inside a base level controller (applied to the HTML tag)

Despite working in the fiddle in my app it was still firing twice.
After a bit of reorganising the simple fix was moving the ng-click from the <a> to its parent <li>
<li ng-if="auth.user" ng-click="toggleMenu()" class="dropdown" ng-class="{open: usermenu}">
{{user.name}} <strong class="caret"></strong>
<ul class="dropdown-menu">
<li><!--i class="icon-align-left"></i--><span class="glyphicon glyphicon-align-left"></span> Activity</li>
<li><!--i class="icon-truck"></i--><span class="glyphicon glyphicon-paperclip"></span> Shares</li>
<li class="divider"> </li>
<li><!--i class="icon-cog"></i--><span class="glyphicon glyphicon-cog"></span> My Profile</li>
<li><!--i class="icon-signout"></i--><span class="glyphicon glyphicon-minus-sign"></span> Logout</li>
</ul>
</li>

Related

How to use custom directives in html

I have created one custom directive to add active class for clicked li in menu list based on url.
.directive('addActive', [function() {
return{
...
link : function(scope, element, attrs){
pageUrl = location.pathname;
$('#sidebar-left .nav li.active').removeClass("active");
if (pageUrl) {
debugger
console.log($('.nav li:has(a[href="' + pageUrl + '"])'))
$('.nav li:has(a[href="' + pageUrl + '"])').addClass("active");
}
}
}
}]);
directive code defines that when a menu is clicked, active class should be added for current url.
how can I use this directive in html code?
Html:
<div id="sidebar-left" class="col-xs-2 col-sm-2">
<ul class="nav main-menu">
<li class="dropdown ng-scope" ng-repeat="parent in menu">
<a href="/employee/Home" class="dropdown-toggle" ng-click="tabName(parent.name)">
<i class="fa fa-home"></i>
<span class="hidden-xs ng-binding">Home</span>
</a>
</li>
<li class="dropdown ng-scope" ng-repeat="parent in menu">
<a href="/documents/doc_details" class="dropdown-toggle" ng-click="tabName(parent.name)">
<i class="fa fa-file-text"></i>
<span class="hidden-xs ng-binding">Documents</span>
</a>
</li>
<li class="dropdown ng-scope" ng-repeat="parent in menu">
<a href="#" class="dropdown-toggle" ng-click="tabName(parent.name)">
<i class="fa fa-money"></i>
<span class="hidden-xs ng-binding">Pay & Benifits</span>
</a>
<ul class="dropdown-menu">
<li ng-repeat="child in parent.children" class="ng-scope">
slips
</li>
</ul>
</li>
</ul>
</div>
Please guys any help?
you are missing the most important information about your directive: the 'restrict' attribute indicates how should the directive can be used in your html. For instance: using retrict: 'E', means that your directive can be used as an html element
<add-active></add-active>
But i guess that in you situation, your restrict value is 'A', and you should use it as an attribute:
<div add-active></div>
for more info you can see the angularJS directive's documentation here:
https://docs.angularjs.org/guide/directive
but i agree with the folks above me that in this case, you probably just need to use ng-class (that is also a directive).
I think Yaniv's answer is what you need.
But I suggest you try ng-class.
In your code, you are trying to use the url so I think this might help you:
How to highlight a current menu item?

Model updates in directive do not update view

angular.module('myApp')
.component('sideNav', {
controller: function SideNavController($scope) {
$scope.navigation = {};
$scope.click = function(key) {
$scope.navigation[key] = !$scope.navigation[key];
}
},
templateUrl: 'components/side-nav/side-nav.html',
})
to be used as simply
<side-nav></side-nav>
The template is
<!-- other li items -->
<li ng-init="navigation.charts = false"
ng-click="click('charts')">
<a href="#">
<i class="fa fa-bar-chart-o fa-fw"></i>
Charts {{ navigation.charts }}
<span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level"
ng-show="navigation.charts">
<li>
Charts
</li>
<li>
Graphs
</li>
</ul>
</li>
navigation.charts is correctly initialized to false and hence the li > ul is hidden. Clicking the top level li item updates the navigation object but the view does not update. I was expecting the li > ul element to get displayed.
Plunkr: https://plnkr.co/edit/UJpdFErwVUzsCd65hlW0?p=preview
Clicking on the link reloads the page and re-initializes the directive. Try modifying to:
<li ng-init="navigation.charts = false"
ng-click="$event.preventDefault(); click('charts')">
You can actually add href="javascript:void(0)"
<ul>
<li ng-click="click('charts')">
<a href="javascript:void(0)">
<i class="fa fa-bar-chart-o fa-fw"></i>
Charts {{ navigation.charts }}
<span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level"
ng-show="navigation.charts">
<li>
Charts
</li>
<li>
Graphs
</li>
</ul>
This actually happens as you put href="#" which I think refresh the page.

UI-Router 1.0.0-beta.2 and UI-Bootstrap 2.1.4 dropdown not closing

I'm using ui-route ui-sref in my links with the navbar using UI-Bootstrap dropdowns and if I use the anchor tag with href, the dropdown closes on click, but the anchor tags with ui-sref does not close the dropdown. I've got the following plnkr with it showing the bug.
Angular Code
angular.module('app', ['ui.bootstrap', 'ui.router'])
.config(appRoute)
.controller('myController', myController);
appRoute.$inject = ['$stateProvider'];
function appRoute($stateProvider) {
$stateProvider.state('index', {
url: '/index',
template: '<h1>indexRoute</h1>'
})
.state('other', {
url: '/other',
template: '<h1>otherRoute</h1>'
})
}
function myController() {
var ctrl = this;
ctrl.title = 'Title';
ctrl.user = 'User#user.com';
ctrl.test = test;
ctrl.test2 = test2;
function test() {
console.log('TEST LINK!')
}
function test2() {
console.log('TEST 2')
}
}
HTML
<body ng-controller="myController as $ctrl" style="{padding-top: 70px;}">
<nav id="isec-menu" class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<div class="intelisecure-header">
<span>{{$ctrl.title}}</span>
</div>
</div>
<div class="collapse navbar-collapse navbar-right">
<ul class="nav navbar-nav">
<li id="usermenu" class="dropdown user-menu-dropdown" uib-dropdown="">
<a href="" class="uib-dropdown-toggle username" uib-dropdown-toggle="">
<i class="fa fa-user fa-fw"></i>
{{$ctrl.user}} <span class="caret"></span>
</a>
<ul class="dropdown-menu" uib-dropdown-menu="" role="menu">
<li role="menuitem">
<a href="/index" ng-click="$ctrl.test()">
<i class="fa fa-fw fa-sign-out menu-icon"></i>
<span class="menu-text">index href</span>
</a>
</li>
<li role="menuitem">
<a ui-sref="other" ng-click="$ctrl.test2()">
<i class="fa fa-fw fa-sign-out menu-icon"></i>
<span class="menu-text">other sref</span>
</a>
</li>
<li role="menuitem">
<a href="" ng-click="$ctrl.logout()">
<i class="fa fa-fw fa-sign-out menu-icon"></i>
<span class="menu-text">Logout</span>
</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<ui-view>
<div>
test
</div>
</ui-view>
</body>
Not perfectly built, I was trying to see if I could replicate the issue with my
https://plnkr.co/edit/Rz3AbgnYnWI34DjuByY6?p=preview
Apparently this was a known issue and was resolved by updating to UI-Router 1.0.0-beta.3

Angular UI dropdown z-index in modal

In this plunk I have an Angular UI modal with a dropdown. The dropdown has the uib-dropdown dropdown-append-to-body directives to show the complete list even though it's in a div with overflow:hidden.
If you click on the button, you will see that the dropdown list is behind the modal. How to fix the z-index?
HTML
<button ng-click="openModal()">Open modal</button>
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h4 class="modal-title">The Title</h4>
</div>
<div style="background-color:orange;overflow-y:hidden;height:30px">
<div class="btn-group" uib-dropdown dropdown-append-to-body>
<button id="btn-append-to-body" type="button" class="btn btn-primary" uib-dropdown-toggle="">
Dropdown on Body <span class="caret"></span>
</button>
<ul class="dropdown-menu" uib-dropdown-menu="" role="menu" aria-labelledby="btn-append-to-body">
<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>
</script>
Javascript
var app = angular.module('app', ['ui.bootstrap']);
app.controller('ctl', function ($scope,$uibModal) {
$scope.openModal = function() {
$scope.modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html',
scope: $scope
});
};
});
Add this class to your CSS file
.dropdown-menu.model-top{
z-index:39999;
}
HTML
<ul class="dropdown-menu model-top" uib-dropdown-menu="" role="menu" aria-labelledby="btn-append-to-body"></ul>
NB: inline CSS not work, the are replacing the style attribute with their own styles, like position, height
use z-index like this:
<div class="btn-group" uib-dropdown dropdown-append-to-body>
<button id="btn-append-to-body" type="button"
class="btn btn-primary" uib-dropdown-toggle>
Dropdown on Body <span class="caret"></span>
</button>
<ul class="dropdown-menu" uib-dropdown-menu role="menu"
aria-labelledby="btn-append-to-body"
style="z-index:39999">
<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>

AngularJs :Expand and collapse in directive

I have this code :
<div >
<ul class="nav nav-pills nav-stacked" data-ng-repeat="filter in filters">
<li class="" >
<a class="" data-toggle="collapse" href="#collapse{{filter.year}}">
{{filter.year}}
</a>
<ul class="nav nav-pills nav-stacked panel-collapse collapse" id="collapse{{filter.year}}">
<li>January</li>
</ul>
</li>
</ul>
</div>
I would like that when I click the years the second show the data...
But it doesn't work
Try ng-href instead:
Quoted from the doc:
Using Angular markup like {{hash}} in an href attribute will make the
link go to the wrong URL if the user clicks it before Angular has a
chance to replace the {{hash}} markup with its value. Until Angular
replaces the markup the link will be broken and will most likely
return a 404 error.
Use angularui toggle collapse (http://angular-ui.github.io/bootstrap/). In the outer ul set ng-click="isCollapsed = !isCollapsed" and in the inner ul set collapse="isCollapsed".
module.directive('collapseDirective', function(){
return {
restrict: 'EA',
transclude: 'true',
link: function(scope, element, attrs){
scope.isCollapsed = true;
};
}
});
<div collapse-directive>
<ul class="nav nav-pills nav-stacked" data-ng-repeat="filter in filters">
<li>
<a ng-click={isCollapsed=!isCollapsed} class="" data-toggle="collapse" href="#collapse{{filter.year}}">
{{filter.year}}
</a>
<ul collapse=isCollapsed class="nav nav-pills nav-stacked panel-collapse collapse" id="collapse{{filter.year}}">
<li>January</li>
</ul>
</li>
</ul>
</div>

Resources