I'm writing a module that will create a dynamic menu on the fly. How to run a directive after adding new <li> with css class dropdown which is also added by ng-class.
The code:
angular.module('myapp', ['ui.bootstrap'])
.factory("menuService", ["$rootScope", function($rootScope) {
"use strict";
return {
menu: function() {
$rootScope.globalMenu;
},
setMenu: function(menu) {
$rootScope.globalMenu = menu;
}
};
}])
.controller("MainController", ["$scope", "menuService",
function($scope, menuService){
menuService.setMenu([{href:"#", label:"Dropdown",
dropdown:[{href:"/edit", label:"Edit"}]},
{href:'/', label:'test'}]);
$scope.bodyText = "Some text";
}]);
This is the code in html
<ul class="navbar-nav nav navbar-left">
<li ng-repeat="menu_element in globalMenu" ng-class="{dropdown: menu_element.dropdown != undefined}">
<a ng-href="{{menu_element.href}}" ng-class="{'dropdown-toggle': menu_element.dropdown != undefined}">
{{menu_element.label}}
<b class="caret" ng-if="menu_element.dropdown != undefined"></b>
</a>
<ul ng-if="menu_element.dropdown != undefined" class="dropdown-menu">
<li ng-repeat="sub_element in $parent.menu_element.dropdown">
<a ng-href="{{sub_element.href}}">{{sub_element.label}}</a>
</li>
</ul>
</li>
</ul>
Link to plunker:
http://plnkr.co/edit/pgH35mmsjLJqV4yJuSYq?p=preview
So what I want to do is the same or similar as for jQuery, there I would run $("li.dropdown").dropdown() after adding whole ul>li blocks. I'm new to Angular and I want to make this in the angular way.
I read about directives, how to use them. But I couldn't find how to apply directive in runtime. I've read about transclude: element in a directive (ui.bootstrap.dropdownToggle) doesn't have it enabled. I'm sure that there is a easy way, but couldn't find it myself...
Solved!
I've finally made it with ng-if and ng-repeat-start. With help in comments, I've found that ng-class does not run directives.
<ul class="navbar-nav nav navbar-left">
<span ng-repeat-start="menu_element in globalMenu"></span>
<li ng-if="menu_element.dropdown !== undefined">
<a ng-href="{{menu_element.href}}" class="dropdown-toggle">
{{menu_element.label}}
<b class="caret" ></b>
</a>
<ul class="dropdown-menu">
<li ng-repeat="sub_element in $parent.menu_element.dropdown">
<a ng-href="{{sub_element.href}}">{{sub_element.label}}</a>
</li>
</ul>
</li>
<li ng-if="menu_element.dropdown === undefined">
<a ng-href="{{menu_element.href}}">
{{menu_element.label}}
</a>
</li>
<span ng-repeat-end></span>
</ul>
Working example on Plnkr. Something happened with the css on Plunker, yesterday it was working... but still it works.
Nice, this helped me along the way. I've a slight variation on your theme.
<ul class="nav navbar-nav">
<li ng-repeat='link in menu track by $index' ng-class='[{dropdown:link.sub}]'>
/* normal menu */
<a ng-if='!link.sub' ng-bind='link.id' ng-click='jump(link.to)'></a>
/* dropdown menu */
<a ng-if='link.sub' class="dropdown-toggle" data-toggle="dropdown">
<span ng-bind='link.id'></span>
<ul class="dropdown-menu inverse-dropdown">
/* and repeat for the submenu */
<li ng-repeat='slink in link.menu track by $index'>
<a ng-bind='slink.id' ng-click='jump(slink.to)'></a>
</li>
</ul>
</a>
</li>
</ul>
My menu array is a list of
{id:'name', to:n}
where n points to an array listing some html I push into the page. When there is a sub menu the menu array element is
{id:'name', sub:true, menu:[{id:'name', to:n}, etc.]}
I tried ui-bootstrap but never got my head around it.
Related
I am trying to implement this theme for my website https://getstisla.com/demo/dashboard-ecommerce.html
I noticed that on the site, if you click a menu item, it sets a list item active on the menu.
However, I have tried to implement it and it but when I click on the menu item, nothing is set as active aside from the home item.
This is the menu
<div class="main-sidebar sidebar-style-2">
<aside id="sidebar-wrapper">
<div class="sidebar-brand">
#Html.ActionLink("App", "Index", "Home", new { area = "" }, new { #class = "" })
</div>
<div class="sidebar-brand sidebar-brand-sm">
#Html.ActionLink("A", "Index", "Home", new { area = "" }, new { #class = "" })
</div>
<ul class="sidebar-menu">
<li class="active"><a asp-controller="Home" asp-action="Index" class="nav-link"><i class="far fa-square"></i><span>Home Page</span></a></li>
<li class="menu-header">AM Mode</li>
<li class="nav-item dropdown">
<i class="fas fa-fire"></i><span>Configuration</span>
<ul class="dropdown-menu">
<li><a asp-area="Configuration" asp-controller="AC" asp-action="Index" class="nav-link">A C</a></li>
<li><a asp-area="Configuration" asp-controller="B" asp-action="Index" class="nav-link">B</a></li>
</ul>
</li>
</ul>
</aside>
</div>
I have tried searching through the files for the javascript that sets the menu item active but I haven't found it so far. I was hoping someone could take a look and see if I'm missing something.
The files can be downloaded from here https://cssauthor.com/bootstrap-templates/#Admin
This is more of a ASP.NET question IMO. Possible duplication of How to add “active” class to Html.ActionLink in ASP.NET MVC
EDIT:
The theme is hardcoding those class="active" in static *.html files, this theme is not a Single Page Application.
I have tried searching through the files for the javascript that sets the menu item active
You won't find it, JavaScript is not setting the active class.
I need to loop through the DOM with JQuery, and add a click handler to multiple parent elements that contain a child that will also be given a slideToggle(). I have the logic working fine when I add the click handlers manually, but now I need to be able to dynamically do this to multiple parent elements.
Here is my HTML:
<div class="map-poi-nav">
<ul class="map-poi-nav-dropdown">
//Parent #1
<li class="sub-menu-link" id="sub-menu-link-1">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Activities
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-1">
<li><a><span>•</span>Golden State Park</a></li>
<li><a><span>•</span>Sunrise Oaks City Park</a></li>
</ul>
</li>
</ul>
<ul class="map-poi-nav-dropdown">
//Parent #2
<li class="sub-menu-link" id="sub-menu-link-2">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Dining
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-2">
<li><a><span>•</span>The Loft Grill</a></li>
<li><a><span>•</span>Fish Grill & Bar</a></li>
</ul>
</li>
</ul>
</div>
Basically, you click on .sub-menu-link to slideToggle() .sub-menu-list.
Here is the JS that I have working so far. It targets the id's manually currently, which feels gross:
$('#sub-menu-link-1').click(function() {
$('#sub-menu-list-1').slideToggle(100);
$(this).toggleClass('active-menu-link');
});
$('#sub-menu-link-2').click(function() {
$('#sub-menu-list-2').slideToggle(100);
$(this).toggleClass('active-menu-link');
});
My apologies if this is something very apparent to do in JQuery. I am not at all familiar with it, and it just so happens to be a requirement of this project.
you could simply use below code.
select all list items with class name and add listener. click will be attached to all elements
$('.sub-menu-link').click(function() {
$(this).slideToggle(100);
$(this).toggleClass('active-menu-link');
});
You already have classes, so just use them instead of the ids: use this to refer to the clicked element, .next() to get the next sibling (the li.sub-menu), and .find('.sub-menu-list') to get to the ul you want to toggle:
$('.sub-menu-link').click(function() {
const $subMenuList = $(this).next().find('.sub-menu-list');
console.log($subMenuList.text().trim());
$subMenuList.slideToggle(100);
$(this).toggleClass('active-menu-link');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="map-poi-nav">
<ul class="map-poi-nav-dropdown">
//Parent #1
<li class="sub-menu-link" id="sub-menu-link-1">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Activities
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-1">
<li><a><span>•</span>Golden State Park</a></li>
<li><a><span>•</span>Sunrise Oaks City Park</a></li>
</ul>
</li>
</ul>
<ul class="map-poi-nav-dropdown">
//Parent #2
<li class="sub-menu-link" id="sub-menu-link-2">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Dining
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-2">
<li><a><span>•</span>The Loft Grill</a></li>
<li><a><span>•</span>Fish Grill & Bar</a></li>
</ul>
</li>
</ul>
</div>
You can use jQuery's .next() like so:
$(".sub-menu-link").click(function() {
$(this).next(".sub-menu-link").slideToggle(100);
$(this).toggleClass("active-menu-link");
})
Or you can chain them and use ES6 arrow syntax to make it more concise:
$(".sub-menu-link").click(() => $(this).toggleClass("active-menu-link").next(".sub-menu-link").slideToggle(100));
You should try this if your list and link ids have similiar pattern as in the code you have shown
$('#sub-menu-link').click(function() {
var id = $(this).attr("id").replace("sub-menu-link", "")
$('#sub-menu-list-'+ id).slideToggle(100);
$(this).toggleClass('active-menu-link');
});
I am creating a webpage using smart admin.I am getting left menu datas from an array.I need display menus and sub menus properly based on parent Id of each data using angular. But I don't know how to do it.Can anyone help me?please.
Script:
var app = angular.module('myApp', []);
app.controller('myController', ['$scope', '$http', function ($scope, $http) {
$scope.Menus = [];
$http.get('/list/GetSiteMenu').then(function (data) {
$scope.Menus = data.data.data.record;
}, function (error) {
alert('Error');
});
}]);
Html:
<nav ng-repeat="menuData in Menus">
<ul>
<li>
<ul>
<li><a></a></li>
</ul>
</li>
</ul>
</nav>
console.log($scope.Menus) will be in this format:
Need to iterate over menuData.menu_roles
<nav ng-repeat="menuData in Menus">
<ul>
<li>
<ul>
<li ng-repeat ="subMenu in menuData.menu_roles">
<a></a>
</li>
</ul>
</li>
</ul>
</nav>
You can use something like this according to your json
Use rootscope instead of scope to store Menus
<section class="sidebar">
<!-- sidebar menu: : style can be found in sidebar.less -->
<ul class="sidebar-menu">
<li class="{{menuItem.LiCssClass}}" ng-repeat="menuItem in $root.menuList" ng-class="{active:isActive('{{menuItem.NavigationURL}}')}">
<a ng-href="{{menuItem.NavigationURL}}" ng-click="sidebar()">
<i class="{{menuItem.ICssClass}}"></i>
<span class="{{menuItem.SpanCssClass}}"> {{menuItem.DisplayName}}</span>
<i class="{{menuItem.TreeViewIcon}}"></i>
</a>
<ul class="{{menuItem.UiCssClass}}">
<li id="{{subMenuItem.TagName}}" ng-repeat="subMenuItem in menuItem.SubMenu" ng-class="{active:isActive('{{subMenuItem.NavigationURL}}')}">
<a ng-href="{{subMenuItem.NavigationURL}}">
<i class="{{subMenuItem.ICssClass}}"></i><span>{{subMenuItem.DisplayName}}</span>
</a>
</li>
</ul>
</li>
</ul>
</section>
You can use ng-bootstrap-submenu
https://www.npmjs.com/package/ng-bootstrap-submenu
It's a module for add submenus items to parent menu items and it's easy to use
I have the following state using angular-ui-router module and I am currently at the url http://localhost:3000/#/bar/87023/ where 87023 is the value of a.
.state('foo', {
url: '/bar/:a/:b',
views: {
'': {
templateUrl: 'partials/zoo.tpl.html',
controller: 'XCtrl'
},
'purr#foo': {
templateUrl: 'partials/zing.html',
controller: 'YCtrl'
}
}
})
On the zing.html page I have 4 tabs as following:
<ul class="nav nav-tabs">
<li>
<a href="#tab_1_1" data-toggle="tab">
Zoo Details </a>
</li>
<li>
<a href="#tab_1_2" data-toggle="tab">
Pricing </a>
</li>
<li class="dropdown">
<a href="#tab_1_3" data-toggle="tab">
Reviews </a>
</li>
<li>
<a href="#tab_1_4" data-toggle="tab">
Something interesting </a>
</li>
</ul>
<div class="tab-content">
<div id="tab_1_1">
//tab_1_1 content
</div>
<div id="tab_1_2">
//tab_1_2 content
</div>
<div id="tab_1_3" >
//tab_1_3 content
</div>
<div id="tab_1_4" >
//tab_1_4 content
</div>
</div>
When I click on tab_1_1 or any of the tabs, I am taken to the http://localhost:3000/#/ page. Could somebody help me understand why am I having this issue and how to resolve this? I want to be on the same page (http://localhost:3000/#/bar/87023/) and be able to see the content of the tabs.
You are redirecting to index because href attribute changes the hash of browser, which is listened by angularJS's ngRoute.
Use data-target attribute instead of href
Here's a example on jsFiddle
Recently I am having a problem with my jquery code. I was trying to get the elements from the html using the jquery find method but its not working. I have tried changing the elements name but still i cant find where is my mistake.
Here is the following html code:
<div class="navbar-collapse collapse">
<nav>
<ul class="nav navbar-nav navbar-right">
<li class = "dropdown"><span>About Us</span><b class = "caret"></b>
<ul class = "dropdown-menu">
<li data-slide = '1'>Philosophy</li>
<li>Founding Members</li>
<li>Committee</li>
<li>Code of Ethics</li>
</ul>
</li>
<li data-slide='2'>Digital Ecosystem</li>
<li data-slide='3'>Fellow & Members</li>
<li data-slide='4'>SIGs</li>
<li data-slide='5'>Local Chapters</li>
<li data-slide="7">Events</li>
<li data-slide="8">Our Service</li>
<li>
<a href="#" onClick="window.open('logout.php','_self','width=400,height=200,toolbar=yes, location=yes,directories=yes,status=yes,menubar=yes,scrollbars=yes,copyhistory=yes, resizable=yes')">
<?php
if (isset($_SESSION['CurrentUser'])) {
echo "Log Out";
}
?>
</a>
</li>
<li>
<a href="#" onClick="window.open('login.php','_self','width=400,height=200,toolbar=yes, location=yes,directories=yes,status=yes,menubar=yes,scrollbars=yes,copyhistory=yes, resizable=yes')">
<?php
if (!isset($_SESSION['CurrentUser'])) {
echo "Login/Register";
}
?>
</a>
</li>
</ul>
</nav>
</div>
I have included my jquery code too :
var links = $('.nav, .navbar-nav, .navbar-right').find('li');
Actually what the code does is once it find the 'li' html elements it slides the page each time a 'li' element is being clicked. Now if I click on the 'li' elements my page doesnt scrolls to the selected page. it would be great if someone is there to solve my problem.
Try this (if you really want the "links" tags):
var links = $('.nav.navbar-nav.navbar-right').find('a');