jQuery function in directive not working - javascript

My jQuery function isn't working inside my directive.
This is my directive:
app.directive('responsiveNav', function () {
return {
restrict: 'E',
link: function (element) {
var pull = $('#pull');
var menu = $('.nav-bar ul ul');
var menuHeight = menu.height();
$(pull).on('click', function (e) {
e.preventDefault();
menu.slideToggle();
});
$(window).resize(function () {
var w = $(window).width();
if (w > 320 && menu.is(':hidden')) {
menu.removeAttr('style');
}
});
}
};
});
HTML:
<div class="header" responsive-nav>
<div class="nav-bar">
<ul style="padding:15 0 15 0;height:50px;">
<li style="border-right: none;">
<img src="assets/images/who-logo.png">
</li>
Menu
<ul style="float:right;list-style-type:none;padding:8.5 0 8.5 0;">
<li><a class="active" href="">Home</a></li>
<li>About us</li>
<li>Tickets</li>
<li>Event</li>
<li>Gallery</li>
<li>Video</li>
<li>Contact</li>
<li style="border-right: none;"><a><i class="fa fa-facebook" style="font-size: 1.5em;"></i></a></li>
<li style="border-right: none;"><a><i class="fa fa-instagram" style="font-size: 1.5em;"></i></a></li>
<li style="border-right: none;"><a><i class="fa fa-twitter" style="font-size: 1.5em;"></i></a></li>
</ul>
</ul>
</div>
</div>
The directive doesn't even react to the click on #pull and I have no errors in my console. Hope you understand the problem. Any help is welcome!

Your directive is restricted to Element by
restrict: 'E'
But you have put the directive as an attribute.
<div class="header" responsive-nav>
restrict: 'A' is one way to solve the problem.
Also I don't agree some of the ways you are using jquery here. Try to be angular as much as possible.
Please take some time to refer the angular directive documentation to make better use of this powerful feature of the framework.

Related

Toggle ng-class

I'm trying to toggle class "category-active" to an active category tab using ng-class and ng-click. Nothing seems to happen when I click the tabs. Not sure what I'm doing wrong. Please help.
HTML:
<body ng-app="app">
<div class="wrap" ng-controller="ctrl">
<h1>Bakery Menu</h1>
<div class="content">
<div class="categories">
<ul>
<li ng-class="{'category-active' : active}">
All
</li>
<li ng-class="{'category-active' : active}" ng-repeat="menu in menus">
<a href="" ng-repeat="(key,val) in menu" href="" ng-click="active = !active; categoryList(key)">{{menus}}
</a>
</li>
</ul>
</div>
</div>
</div>
</body>
JS:
angular.module('bakeryMenuApp')
.controller('mainCtrl', function($scope, dataService) {
dataService.getMenus(function(response) {
$scope.menus = response.data.menus;
$scope.category = 'all';
$scope.categoryList = function(value) {
$scope.category = value;
}
});
})
JSON:
{
"menus":[
{
"brownies":[
{
"name":"Baker's Choice Bars Assortment",
"price":"45",
"description":"A beautiful and delicious assortment of Magnolia Bakery’s double fudge brownies, chocolate chunk blondies and magic cookie bars.",
"image_url":"https://pantograph0.goldbely.com/s364/uploads/product_image/image/8346/bakers-choice-bars-assortment.1ddd25a1f59a89a1de2d0583dab50000.jpg",
"is_vegan":false,
"is_gluten_free":false
}
]
},
{
"cakes":[
{
"name":"Raseberry Lemon Cake",
"price":"50",
"description":"Vanilla crème fraîche cake layered with raspberry Swiss meringue buttercream and lemon curd filling, covered with raspberry buttercream.",
"image_url":"http://www.empirecake.com/_main_site/wp-content/uploads/2014/12/Rasberry_Lemon_01_final_drkr-600.jpg",
"is_vegan":false,
"is_gluten_free":false
}
]
}
]
}
I think it had to do with ng-repeat and scope. I changed the scope and used directive to solve it.
<ul>
<li ng-init="selected === 'all'" ng-class="{'category-active':selected==='all'}">
<a sibling href="" ng-click="selected = 'all'; categoryList('all')">All</a>
</li>
<li ng-init="active = false" ng-repeat="menu in menus">
<a sibling href="" ng-repeat="(key,val) in menu" href="" ng-click="categoryList(key)">{{key}}
</a>
</li>
</ul>
JS:
angular.module('bakeryMenuApp')
.directive('sibling', function () {
return {
link: function(scope, element, attrs) {
element.bind('click', function() {
element.parent().parent().children().removeClass('category-active');
element.parent().addClass('category-active');
})
},
}
});
You logic seems wrong. Try this:
<li ng-class="{'category-active':selected==='all'}">
All
</li>
<li ng-class="{'category-active':selected===menu}" ng-repeat="menu in menus">
<a href="" ng-repeat="(key,val) in menu" href="" ng-click="selected=menu; categoryList(key)">{{menus}}
</a>
</li>

Add/Remove class based on active URL

My HTML code looks like this:
<div id="sidebar-menu" class="main_menu_side hidden-print main_menu">
<div class="menu_section">
<ul class="nav side-menu">
<li>
<a>
<i class="fa fa-home"></i>home
<span class="fa fa-chevron-down"></span>
</a>
<ul class="nav child_menu" style="display: none">
<li>
Dashboard
</li>
<li>
dashbord2
</li>
</ul>
</li>
<li>
<a>
<i class="fa fa-edit"></i>form
<span class="fa fa-chevron-down"></span>
</a>
<ul class="nav child_menu" style="display: none">
<li>
general form
</li>
<li>
form validation
</li>
</ul>
</li>
</ul>
</div>
</div>
to add/remove class based on current url, i am using this:
$(function () {
var url = window.location.href;
$('#sidebar-menu a[href="' + url + '"]').parent('li').addClass('current-page');
$('#sidebar-menu a').filter(function () {
return this.href == url;
}).parent('li').addClass('current-page').parent('ul').slideDown().parent().addClass('active');
});
It works, but when i click this link
dashbord2
the class="current-page" doesn't change to current path url
How i fix this?
Your issue arises from the page not being reloaded when you click on the link with hash in it, while your code only executes on page load, or dom ready to be exact. The solution is to whether use window's hashchange event (not supported in < IE8) or, like #sirrocco mentioned, use click event with setTimeout to detect the change of hash:
function setCurrentMenuPage() {
var url = window.location.href;
var anchors = $('#sidebar-menu a');
anchors.parent('li').removeClass('current-page');
anchors.filter(function () {
return this.href == url;
}).parent('li').addClass('current-page').parent('ul').slideDown().parent().addClass('active');
}
$(function () {
setCurrentMenuPage();
$('#sidebar-menu a').on('click', function (e) {
if ($(this).attr('href').indexOf("#") >= 0) {
setTimeout(function () {
setCurrentMenuPage();
}, 100);
}
});
});
Hope that helps.

jQuery - using the same function (ToggleNav/Dropdown) on multiple ID's

I'm trying to make multiple dropdown menu's on my website and I am using this jQuery for this:
$(function() {
var pull = $('#pull');
menu = $('#nav');
menuHeight = menu.height();
$(pull).on('click', function(e) {
e.preventDefault();
menu.slideToggle();
});
});
Here's the html part:
<nav class="container">
<a href="#" id="pull" style="display:block;">
<h3>Menu</h3>
</a>
<ul id="nav" style="display:none;">
<li>Pizza</li>
<li>Pasta</li>
<li>Burger</li>
<li>Specials</li>
<li>Drinks</li>
</ul>
</nav>
It works wonderful if I only have one drop down menu but as soon as I add another one, only one of them (doesn't matter if it's two, three or more then) is actually dropping down.
I gave every Menu it's own ID and copied the code every time and replaced the ID's but this doesn't work.
Already looked into this (using the same function of different events ) or this (Jquery - use the same function for multiple requests) and other threads but i can't figure out how to apply this on my code...
Here's my Jsfiddle on what I'm trying to do: https://jsfiddle.net/thwdyccr/2/
Use classes instead of ids, and then you can make the same code work for all cases (fiddle):
$(function () {
var pull = $('.pull');
$(pull).on('click', function (e) {
e.preventDefault();
var menu = $(this).next();
menu.slideToggle();
});
});
<nav class="container"> <a href="#" class="pull" style="display:block;">
<h3>Menu1</h3>
</a>
<ul class="nav" style="display:none;">
<li>Pizza
</li>
<li>Pasta
</li>
<li>Burger
</li>
<li>Specials
</li>
<li>Drinks
</li>
</ul>
</nav>
<nav class="container"> <a href="#" class="pull" style="display:block;">
<h3>Menu2</h3>
</a>
<ul class="nav" style="display:none;">
<li>Pizza
</li>
<li>Pasta
</li>
<li>Burger
</li>
<li>Specials
</li>
<li>Drinks
</li>
</ul>
</nav>
Try this:
https://jsfiddle.net/thwdyccr/5/
Rather than using IDs - consider using a class instead - this'll save you lots of duplication in your code (as essentially it's all doing the same thing).
You can specify the target selector (e.g. the element you want to show) by traversing your structure with .parent() .children() or .find()
If you're wondering why I am storing $(this) in var element - it is because the browser has to figure out what $(this) is each time you use it - so it's good practice to store it in a variable.
HTML
<nav class="container">
<a href="#" class="pull" style="display:block;">
<h3>Menu1</h3>
</a>
<ul class="nav" style="display:none;">
<li>Bear</li>
<li>Pasta</li>
<li>Burger</li>
<li>Specials</li>
<li>Drinks</li>
</ul>
</nav>
<nav class="container">
<a href="#" class="pull" style="display:block;">
<h3>Menu2</h3>
</a>
<ul class="nav" style="display:none;">
<li>Fish</li>
<li>Pasta</li>
<li>Burger</li>
<li>Specials</li>
<li>Drinks</li>
</ul>
</nav>
JS
$(function() {
$(".pull").click(function(e) {
e.preventDefault();
var element = $(this);
element.parent('nav.container').children("ul.nav").slideToggle();
});
});
You shouldn't use id's for pull. Here's an updated fiddle https://jsfiddle.net/thwdyccr/2/.
Try utilizing Attribute Starts With Selector [name^="value"] [id^=pull] , e.target.parentElement.nextElementSibling to select next ul to call .slideToggle() on
$(function() {
var pull = $("[id^=pull]")
, menu = $("[id^=nav]")
, menuHeight = menu.height();
pull.on("click", function(e) {
e.preventDefault();
$(e.target.parentElement.nextElementSibling).slideToggle();
});
});
jsfiddle https://jsfiddle.net/wpvok7gy/1/

Nested transclude directive renders inner transcluded content in wrong place

I have a myList directive, which transcludes it's content. The problem occurs when I try and nest a <my-list> element inside another <my-list>.
JS Fiddle: http://jsfiddle.net/fqj5svhn/
The directive:
var MyListDirective = (function () {
function MyListDirective() {
this.restrict = 'E';
this.replace = true;
this.transclude = true;
this.scope = {
myListType: '='
};
this.controller = function () {
this.classes = 'my-class';
};
this.controllerAs = 'myList';
this.bindToController = true;
this.template = '<ul ng-class="myList.classes" ng-transclude></ul>';
}
return MyListDirective;
})();
angular.module('myApp', []).directive('myList', function () {
return new MyListDirective();
});
Example usage of the directive:
<div ng-app="myApp">
<my-list my-list-type="'someType'">
<li>foo</li>
<li>bar</li>
<li>
<my-list my-list-type="'anotherType'">
<li>cats</li>
<li>dogs</li>
</my-list>
</li>
</my-list>
</div>
What gets rendered:
<div ng-app="myApp" class="ng-scope">
<ul ng-class="myList.classes" ng-transclude="" my-list-type="'someType'" class="ng-isolate-scope my-class">
<li class="ng-scope">foo</li>
<li class="ng-scope">bar</li>
<li class="ng-scope">
<ul ng-class="myList.classes" ng-transclude="" my-list-type="'anotherType'" class="ng-isolate-scope my-class">
</ul>
</li>
<li class="ng-scope">cats</li>
<li class="ng-scope">dogs</li>
</ul>
</div>
As you can see the list items from the inner myList appear to be transcluded by the outer myList.
What I want to happen:
<div ng-app="myApp" class="ng-scope">
<ul ng-class="myList.classes" ng-transclude="" my-list-type="'someType'" class="ng-isolate-scope my-class">
<li class="ng-scope">foo</li>
<li class="ng-scope">bar</li>
<li class="ng-scope">
<ul ng-class="myList.classes" ng-transclude="" my-list-type="'anotherType'" class="ng-isolate-scope my-class">
<li class="ng-scope">cats</li>
<li class="ng-scope">dogs</li>
</ul>
</li>
</ul>
</div>
Suggestions?
It is happening because when browser renders the page it expects <li> to be inside <ul>, but it your case it is inside <my-list> which is an invalid markup. All these things happen before Angular bootstraps and runs directives. There is no way you can predict how the browser would interpret your markup when it's invalid, in this particular case it pushes <li>'s out to be together.
In this fiddle I've replaced <ul> and <li> with <div>, which does not have any requirements for nesting, and transclusion works just fine.

When User Open One DropDown Close Other DropDowns

I Want When User Click On One DropDown All Other open DropDown Get Closed . I looked for answer in google but that is not working for my dropdown i know it's simple but i am unable to this pls help me !!
<div class="hh_drop_down">
<ul class="hh_main">
<li class="hh_main_menu">
Chemicals
<ul class="hh_inner">
<li>Additives / Boosters</li>
<li>Anti-Allergen</li>
<li>Concrete</li>
</ul>
</li>
<li class="hh_main_menu" >
<a class="hh_sf" href="#">Equipment</a>
<ul class="hh_inner">
<li>Deodorization</li>
<li>Duct Cleaning Equipment</li>
<li>Hard Surface</li>
</ul>
</li>
<li class="hh_main_menu" >
<a class="hh_sf" href="#">Accessories</a>
<ul class="hh_inner">
<li>Bonnets/Pads</li>
<li>Brush/Rake/Sponge</li>
<li>Carpet Rakes</li>
</ul>
</li>
</ul>
</div>
And jquery i am using in this :
<script>
$(document).ready(function(){
$(".hh_main").on('click' , '.hh_sf' , function(event){
event.preventDefault();
if($(this).next().hasClass('hh_inner')) {
$(this).next().slideToggle();
}
});
});
</script>
Try this:
HTML:
<div class="hh_drop_down">
<ul class="hh_main">
<li class="hh_main_menu">
Chemicals
<ul class="hh_inner expanded">
<li>Additives / Boosters</li>
<li>Anti-Allergen</li>
<li>Concrete</li>
</ul>
</li>
<li class="hh_main_menu">
<a class="hh_sf" href="#">Equipment</a>
<ul class="hh_inner expanded">
<li>Deodorization</li>
<li>Duct Cleaning Equipment</li>
<li>Hard Surface</li>
</ul>
</li>
<li class="hh_main_menu">
<a class="hh_sf" href="#">Accessories</a>
<ul class="hh_inner expanded">
<li>Bonnets/Pads</li>
<li>Brush/Rake/Sponge</li>
<li>Carpet Rakes</li>
</ul>
</li>
</ul>
</div>
JQuery:
<script>
$(document).ready(function () {
$(".hh_sf").next().addClass("collapsed").slideUp();
$(".hh_main").on('click', '.hh_sf', function (event) {
event.preventDefault();
var currentClass = $(this).next().prop('class');
if (currentClass == "hh_inner expanded") {
$(this).next().removeClass("expanded");
$(this).next().addClass("collapsed");
$(this).next().slideUp();
} else {
$(".expanded").slideUp().addClass("collapsed").removeClass("expanded");
$(this).next().removeClass("collapsed");
$(this).next().addClass("expanded");
$(this).next().slideDown();
}
});
});
</script>
JsFiddle
I opened dropmenu with show and hide and made event on li you can use different way
try this :
JQuery :
$(".hh_main_menu").click(
function(){
$(this).next(".hh_inner").toggle();
if($(this).siblings(".hh_main_menu").children(".hh_inner").css("display")=="block")
{
$(this).siblings(".hh_main_menu").children(".hh_inner").hide();
}
} );

Categories

Resources