jquery click event is not working with angular.js ng-repeat - javascript

I have a nested (tertiary) menu list with a jquery click event on the back. jQuery click does not fire when the menu item is clicked. The jQuery event works well if the values inside the HTML are static.
HTML:
<div>
<ul class="collapsible-list" ng-controller="ViewCtrl">
<li class="collapsible-list-subnav" ng-repeat="view in views">
<a class="collapsible-list-parent">{{view.name}}</a>
<ul class="collapsible-list secondary">
<li class="collapsible-list-subnav">
<a class="collapsible-list-parent">Public Views</a>
<ul class="collapsible-list tertiary">
<li ng-repeat="publicview in view.publicviews">
<a>{{publicview.title}}</a>
</li>
</ul>
</li>
<li class="collapsible-list-subnav">
<a class="collapsible-list-parent">Private Views</a>
<ul class="collapsible-list tertiary">
<li ng-repeat="privateview in view.privateviews">
<a>{{privateview.title}}</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
Javascript:
define([ 'angular', 'controllers-module'], function(angular,
controllers) {
controllers.controller("ViewCtrl", [
"$scope",
"$rootScope",
"directiveBinder",
'$timeout',
'$stateParams',
'$resource',
'$state',
function($scope, $rootScope,directiveBinder, $timeout, $stateParams, $resource, $state) {
$scope.engines = [ {
name : 'name1',
publicviews : [ {
title : 'First public View'
} ],
privateviews : [ {
title : 'First private View'
} ]
}, {
name : 'name2',
publicviews : [ {
title : 'Second public View'
} ],
privateviews : [ {
title : 'Second private View'
} ]
} ];
$('.collapsible-list-parent').click(function(e) {
e.preventDefault();
$(this).next().slideToggle('fast');
if ($(this).parent().hasClass('open')) {
$(this).parent().removeClass('open');
} else {
$(this).parent().addClass('open');
}
});
});

Because the elements are added dynamically by ng-repeat the .click event is not binded to them. Try to use .delegate
$( "ul" ).delegate( ".collapsible-list-parent", "click", function() {
// code here
});

When we use ng-repeat and need to trigger a jquery click event just try this it worked for me.
$(document).on("click", ".className", function() {
//your code here...
});

I don't think using jQuery code in an angularjs controller is the right way to do this, a sample to do the same without the animation will be like
var app = angular.module('my-app', [], function() {
})
app.controller('ViewCtrl', function($scope) {
$scope.views = [{
name: 'name1',
publicviews: [{
title: 'First public View'
}],
privateviews: [{
title: 'First private View'
}]
}, {
name: 'name2',
publicviews: [{
title: 'Second public View'
}],
privateviews: [{
title: 'Second private View'
}]
}];
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="my-app">
<ul class="collapsible-list" ng-controller="ViewCtrl">
<li class="collapsible-list-subnav" ng-repeat="view in views">
<a class="collapsible-list-parent" ng-click="open = !open">{{view.name}}</a>
<ul class="collapsible-list secondary" ng-show="open">
<li class="collapsible-list-subnav">
<a class="collapsible-list-parent" ng-click="popen = !popen">Public Views</a>
<ul class="collapsible-list tertiary" ng-show="popen">
<li ng-repeat="publicview in view.publicviews">
<a>{{publicview.title}}</a>
</li>
</ul>
</li>
<li class="collapsible-list-subnav">
<a class="collapsible-list-parent" ng-click="ropen = !ropen">Private Views</a>
<ul class="collapsible-list tertiary" ng-show="ropen">
<li ng-repeat="privateview in view.privateviews">
<a>{{privateview.title}}</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
If you want to use animations you can make use of angularjs animation which uses css3 animations.

Related

Hide expanded sub menu when another one selected

And the I want to expand sub menu when user clicks on it with animation:
angular.module('testApp', ['ngAnimate'])
.controller('testController', ['$scope',
function($scope) {
$scope.workshops = [
{ name: "Workshop audience", id: 'audience' },
{ name: "Workshop catalog", id: 'catalog' },
{ name: "Add a workshop", id: 'add_wk' },
{ name: "Add/Edit categories", id: 'add_ctg' },
{ name: "Add/Edit difficulty level", id: 'add_lvl' },
{ name: "Add/Edit a target group", id: 'add_grp' }
];
}
])
.animation('.slide', function() {
var NG_HIDE_CLASS = 'ng-hide';
return {
beforeAddClass: function(element, className, done) {
if (className === NG_HIDE_CLASS) {
element.slideUp(done);
}
},
removeClass: function(element, className, done) {
if (className === NG_HIDE_CLASS) {
element.hide().slideDown(done);
}
}
}
});
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular-animate.js"></script>
<div ng-app="testApp" ng-controller="testController">
<ul>
<li class="nav-item" ng-class="{ active: isActive('/analysis/recommendation') }">
<a class="nav-link" ng-click="expand = !expand;">Analysis</a>
<ul class="slide" ng-show="expand">
<li>
<a ng-class="{active:isActive('/analysis/recommendation')}" href="#!analysis/recommendation">Recommendation</a>
</li>
</ul>
</li>
<li ng-class="{ active: isActive('/workshop/') }">
<a ng-click="expand2 = !expand2">Workshop </a>
<ul class="nav flex-column sub-menu slide" ng-show="expand2">
<li data-ng-repeat="workshop in workshops">
</li>
</ul>
</li>
</ul>
</div>
It works fine. All sub menus are displayed when I click on them, but how can I hide sub menus which are already expanded when I want to open a new one?
Here is fiddle
Does this work?
angular.module('testApp', ['ngAnimate'])
.controller('testController', ['$scope',
function($scope) {
$scope.workshops = [
{ name: "Workshop audience", id: 'audience' },
{ name: "Workshop catalog", id: 'catalog' },
{ name: "Add a workshop", id: 'add_wk' },
{ name: "Add/Edit categories", id: 'add_ctg' },
{ name: "Add/Edit difficulty level", id: 'add_lvl' },
{ name: "Add/Edit a target group", id: 'add_grp' }
];
$scope.expandToggle= function(subMenu){
if (subMenu == 'expand'){
$scope.expand = !$scope.expand;
if($scope.expand2){$scope.expand2 = false;}
}
if (subMenu == 'expand2'){
$scope.expand2 = !$scope.expand2;
if($scope.expand){$scope.expand = false;}
}
}
}
])
.animation('.slide', function() {
var NG_HIDE_CLASS = 'ng-hide';
return {
beforeAddClass: function(element, className, done) {
if (className === NG_HIDE_CLASS) {
element.slideUp(done);
}
},
removeClass: function(element, className, done) {
if (className === NG_HIDE_CLASS) {
element.hide().slideDown(done);
}
}
}
});
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular-animate.js"></script>
<div ng-app="testApp" ng-controller="testController">
<ul>
<li class="nav-item" ng-class="{ active: isActive('/analysis/recommendation') }">
<a class="nav-link" ng-click="expandToggle('expand')">Analysis</a>
<ul class="slide" ng-show="expand">
<li>
<a ng-class="{active:isActive('/analysis/recommendation')}" href="#!analysis/recommendation">Recommendation</a>
</li>
</ul>
</li>
<li ng-class="{ active: isActive('/workshop/') }">
<a ng-click="expandToggle('expand2')">Workshop </a>
<ul class="nav flex-column sub-menu slide" ng-show="expand2">
<li data-ng-repeat="workshop in workshops">
</li>
</ul>
</li>
</ul>
</div>

Recursive compose element in Aurelia

So let's say I've got this view and "Menu" is a collection of menu objects which may also have a collection of menu objects named Children as a property.
Here's the view -
<div class="collapse navbar-collapse navbar-right navbar-main-collapse">
<ul class="nav navbar-nav">
<li repeat.for="m of menu" class.bind="m.type=='child' ? 'dropdown' : ''" as-element="compose" data-type="${m.type}"
view="/client/landing/menubar/${m.type}menu"></li>
</ul>
</div>
And there are two views I'm using as my recursive menu, like so -
(View - no child collection)
<template>
<a href.bind="menu.link" data-info="${menu.type}">${menu.displayText}</a>
</template>
(View - with child collection)
<template>
${menu.displayText} <b class="caret"></b>
<ul class="dropdown-menu">
<li repeat.for="m of menu.children" data-info="${m.type}" class.bind="m.haschildren ? 'dropdown' : ''"
as-element="compose" view="/client/landing/menubar/${m.type}menu"></li>
</ul>
</template>
And the viewmodels for these two views both look like this -
import { customElement, bindable, inject } from "aurelia-framework";
#customElement("parentmenu")
export class ParentMenu {
#bindable menu;
}
I'm getting something. The views do display (although without recursion). The problem is that the repeat.for="m of menu" simply doesn't work below the bind in the first view.
Where have I gone wrong?
There's no need to use compose. Your menu could be a lot simpler, like:
<template bindable="model">
<ul>
<li repeat.for="item of model">
<a href.bind="item.link">${item.displayText}<a/>
<menu if.bind="item.children && item.children.length" model.bind="item.children"></menu>
</ul>
</template>
Usage:
<menu model.bind="menu"></menu>
JS:
menu = [
{
displayText: '1',
href: ''
},
{
displayText: '2',
children: [
{
displayText: '3',
href: ''
},
{
displayText: '4',
href: '',
children: [
{
displayText: '3',
href: ''
}
]
}
]
}
];

toggle show/hide of list items using angularjs

var myApp = angular
.module("myApp", [])
.controller("listController", function($scope) {
var foodList = [
{ name : 'Hyderbadi Koma',
types : [
{ name : "sweet" },
{ name : "extra chatpata" },
{ name : "chatpata" }
],
flag: 0
}]; ...
$scope.showhide = function(foodLists) {
if (foodLists.flag == 0)
foodLists.flag++;
else
foodLists.flag--;
};
});
...
<td class="leftSection">
<ul>
<li ng-repeat="foodItem in foodList" ng-click="showhide(foodItem)" class="clic">
{{ foodItem.name }}
<ul>
<li ng-repeat="foodType in foodItem.types" ng-hide="{{ foodItem.flag | filtering }}" class="unclic">
{{ foodType.name }} ///For watching variable flag {{foodItem.flag}}
</li>
</ul>
</li>
</ul>
...
Now here after tracing i found that "ng-click" is performing its action of changing the flag value from 1 to 0 and vice versa. Though I am not able to debug why ng-hide is not performing its action simultaneously, please help!
try this...
<td>
<ul ng-repeat="foodItem in foodList">
<li class="clic">
{{ foodItem.name }}
<ul ng-repeat="foodType in foodItem.types">
<li ng-hide="{{ foodItem.flag}}" class="unclic">
{{ foodType.name }}
</li>
</ul>
</li>
</ul>
</td>
https://plnkr.co/edit/sTWHI3SQeKgNN7QoOrrw

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>

Angular Bootstrap 3 nav-bar submenu will not fire

I have Angular 1.2.1 and Bootstrap 3.0.2
Plain vanilla nav menu with a drop down works fine but when I try to generate my menu using ng-repeat the submenu will not fire.
The HTML:
<ul class="nav navbar-nav" ng-repeat="data in main_menu">
<li ng-class="{'dropdown' : data.nodes}">
<a href="{{data.link}}" ng-class="{'dropdown-toggle' : data.nodes}">{{data.name}} <b class="caret" ng-if="data.nodes"></b>
<ul ng-if="data.nodes" ng-repeat="items in data.nodes" class="dropdown-menu">
<li>{{items.name}}</li>
</ul>
</li>
</ul>
In the Controller:
$scope.main_menu = [
{
name: 'Home',
class: '',
link: '/',
nodes: false
},
{
name: "DropDown",
class: 'dropdown-toggle',
link: '#',
nodes: [
{
name: "Node2",
class: '',
link: 'link'
},
{
name: "Node2",
class: '',
link: 'link'
},
{
name: "Node2",
class: '',
link: 'link'
},
{
name: "Node2",
class: '',
link: 'link'
}
]
}
];
The normal bootstrap html submenu function works fine ..
Any suggestion ?
After checking ..
The Angular html Block is not correct, with this adjustment it renders the correct html - the drop down still does not work
<ul class="nav navbar-nav" >
<li ng-repeat="data in main_menu" ng-class="{'dropdown' : data.nodes}">
{{data.name}} <b class="caret" ng-if="data.nodes"></b>
<ul ng-if="data.nodes" class="dropdown-menu">
<li ng-repeat="items in data.nodes">{{items.name}}</li>
</ul>
</li>
</ul>
Two steps:
Add attr data-toggle="dropdown" for link.
Update controller, change link: '#' to link: ''.

Categories

Resources