Toggle menu with ng-repeat - angularjs

I have a sidebar with toggle menus of companies. I get the companies data from api and print it out. And each company has same two subtitle "documents" and "add new document".
I use ng-repeat for printing all the companies to sidebar. And i couldn't find any solution to toggle these menus.
Last thing i found is this:
<li data-ng-click="toggleMenu($event)" ng-repeat="company in companies" >
<a class="nav-submenu" data-toggle="nav-submenu" href="#">
<span class="sidebar-mini-hide">{{company.name}}</span>
</a>
<ul>
<li>
<a data-ui-sref="{{company.id}}" data-ui-sref-active="active">
<i class="fa fa-file-text-o"></i>Company's Documents
</a>
</li>
<li>
<a data-ui-sref="{{company.id}}" data-ui-sref-active="active">
<i class="fa fa-plus"></i>Add New Document
</a>
</li>
</ul>
</li>
Here is the Js Code:
$scope.toggleMenu = function($event){
$($event.currentTarget).toggleClass('open');
$($event.currentTarget).siblings().removeClass('open');
};
But this code causes menu to close whenever i click on the "add new document" or "documents" of any company.
Any help would be great for me !
Thanks,
Burak

As I wrote in the comment: You should avoid as much as possible uglifying your angular code with jQuery.
I suggested the following as an alternative:
<li ng-class="{open: company.isOpen}" ng-repeat="company in companies" >
<a ng-click="company.isOpen = !company.isOpen" class="nav-submenu" data-toggle="nav-submenu" href="#">
<span class="sidebar-mini-hide">{{company.name}}</span>
</a>
But as you correctly say, it won't close to menu if you're clicking on another company menu.
So here is a similar, but different approach:
<li ng-class="{open: currentOpen.companyId == company.id}" ng-repeat="company in companies" >
<a ng-click="currentOpen.companyId = currentOpen.companyId == company.id ? null : company.id" class="nav-submenu" data-toggle="nav-submenu" href="#">
<span class="sidebar-mini-hide">{{company.name}}</span>
</a>
This will store the company id when you click on it in an object: $scope.currentOpen.companyId, and will add the open class if it matched to the same company id inside the ngRepeat loop.
Working example: https://jsfiddle.net/jsv2q4bm/

Related

angularjs activate class on the menu in a sub page

I have a menu of nageção that works perfectly the class when clicking the option corespondente. Inside this page that opens when clicking on the menu there is a button that leads to another page, after clicking the menu loses the active class. How do I indicate that I'm still in that session.
First page working .. but clicking the button ..
the menu does not remain active
HTML
<li ng-class="{active: 'home.produtos'}">
<a href="">
<i class="fa fa-fa-briefcase"></i>
<span class="nav-label">Produtos</span>
<span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level collapse" ng-class="{in: $state.includes('home.produtos','home.etiquetas','home.etiquetasview')}">
<li>
<a ui-sref="home.produtos">Produto</a>
</li>
<li ui-sref-active-eq="active">
<a ui-sref="home.etiquetas">Etiqueta</a>
</li>
</ul>
</li>
Button in page
<a ui-sref-active-eq="active" ui-sref="home.etiquetasview({id:{{item.codigo}}})" class="btn btn-white btn-sm">
<i class="fa fa-eye"></i> View
</a>
<a ui-sref-active="active" ui-sref="home.etiquetasview({id:{{item.codigo}}})" class="btn btn-white btn-sm">
<i class="fa fa-eye"></i> View
</a>
May be this Can Help You Angular-ui-router: ui-sref-active and nested states

open dropdown with ng-class Angularjs and typescript

I need to open the dropdown when clicking on link with angularjs. my idea is to add the class open to the dropdown with ng-class directive but this is not working .
I have two dropdown menu, what i need is to open the second one when clicking on the link within the first one
<ul class="nav navbar-nav navbar-right " >
<li class="dropdown" ng-class="myDropdown ? : 'open'">
<a class="dropdown-toggle" data-toggle="dropdown" >Menu</a>
<ul class="dropdown-menu " role="menu" ng-if="!myDropdown">
<li>
Open second dropdown
</li>
</ul>
<ul class="dropdown-menu " role="menu" ng-if="myDropdown">
<li >
Go back
</li>
</ul>
</li>
</ul>
Typescript
toogleDropDown() {
this.scope.myDropdown = true;
}
This won't work since you toggleDropDown is a function and it does not return anything !undefined should be true I think so your line:
Go back
is same as writing:
Go back
overall there's no need for that function at all what you need is something like this:
<a href="" ng-click="myDropdown=!myDropdown">
<span ng-if="!myDropdown">Open second dropdown</span>
<span ng-if="myDropdown">Go back</span>
</a>
and remove that function from your controller there's no need for it.
also I believe you wanted to set up ng-class like this:
<li class="dropdown" ng-class="{'open': myDropdown}">
Here's fiddle: https://jsfiddle.net/pegla/nq11093m/1/

how to select a li which is nested within another ng-repeat in angular js

(please do not update the english grammer in this question/ I wont be able to approve it and this question wont get resolved.)
This is my UI
It contains various li elements whose values are populated using this angular html
<div class="row">
<li class="no-bullet-li li-12 monaco-font"> {{selectedChangeEligibilityPlan}}</li>
<ul class="ul-plan-1">
<li class="no-bullet-li" ng-repeat="plan in fewThings">
<div ng-class="{ 'selected-class-name': $index == selectedIndex }" ng-click="itemClicked($index)" class="li-alt monaco-font"> p2|{{plan.planName}} | {{plan.planId}}
<a class="iconing-sub" ng-click="addClick(item)" href=""><i class="glyphicon glyphicon-plus"></i></a>
<a ng-click="deleteClick(item)" ng-class="{ active : active.one }" href=""><i class="glyphicon glyphicon-remove iconing_1-sub"></i></a>
</div>
<ul class="ul-plan">
<li class="no-bullet-li li-8 monaco" ng-repeat="item in plan.planIds">
p1| {{ plan.planNames[$index]}} | {{item}}
<a <a ng-click="editClick(item)" href=""><i class="glyphicon glyphicon-pencil iconing"></i></a>
<a ng-click="deleteClick(item)" href=""><i class="glyphicon glyphicon-remove iconing_1"></i></a>
</li>
</ul>
</li>
</ul>
</div>
It uses the nested ng-repeat.
The whole UI is contained within a one controller ( no directives used)
the following code gets triggered when someone clicks the blue lis.
$scope.itemClicked = function ($index) {
console.log($index);
// console.log($(item).closest('li') );
$scope.selectedIndex = $index;
};
here's how to ui looks and its great.
problem arises when I try to do the same logic for the pink ones (nested ng-repeat li). It selects other pink lis in all the other stack too.
here's the screenshot.
second part of question:
I have I have the above UI plus I also have this second UI that is loaded along with this on the same page. It contains a bunch of horizontal rows.
Once the user click the blue pink colored lis it goes into the active state. Then the user can click the row which he likes. upon clicking it the plan name of currently selected li will get replaced.
Here is the html for it.
<div class="row">
<li class="no-bullet-li li-12 monaco-font"> {{selectedChangeEligibilityPlan}}</li>
<ul class="ul-plan-1">
<li class="no-bullet-li" ng-repeat="plan in fewThings">
<div class="li-alt monaco-font"> p2|{{plan.planName}} | {{plan.planId}}
<a class="iconing-sub" ng-click="addClick(item)" href=""><i class="glyphicon glyphicon-plus"></i></a>
<a ng-click="deleteClick(item)" ng-class="{ active : active.one }" href=""><i class="glyphicon glyphicon-remove iconing_1-sub"></i></a>
</div>
<ul class="ul-plan">
<li ng-class="{ 'selected-class-name': $index == selectedIndex }" ng-click="itemClicked($index)" class="no-bullet-li li-8 monaco" ng-repeat="item in plan.planIds">
p1| {{ plan.planNames[$index]}} | {{item}}
<a ng-click="editClick(item)" href=""><i class="glyphicon glyphicon-pencil iconing"></i></a>
<a ng-click="deleteClick(item)" href=""><i class="glyphicon glyphicon-remove iconing_1"></i></a>
</li>
</ul>
</li>
</ul>
</div>
The problem lies in the fact that you are trying to save the state of the data (which one is selected) inside your controller using $index. The $index property isn't unique among different ng-repeats, so when you set your $scope.selectedIndex to $index, each of your sub lists will see that their $index matches, and so will each trigger the ng-class and add the selected-class-name class.
What you could do instead is have each item in the data have a unique index and use that id to store which item is selected in $scope.selectedIndex.
<ul class="ul-plan">
<li ng-class="{ 'selected-class-name': item.id == selectedIndex }" ng-click="itemClicked(item.id)" class="no-bullet-li li-8 monaco" ng-repeat="item in plan.planIds">
p1| {{ plan.planNames[$index]}} | {{item}}
<a ng-click="editClick(item)" href=""><i class="glyphicon glyphicon-pencil iconing"></i></a>
<a ng-click="deleteClick(item)" href=""><i class="glyphicon glyphicon-remove iconing_1"></i></a>
</li>
</ul>
This line looks strange.
<a ng-click="select('one')" href="">
Did you really mean to pass a hardcoded 'one' to the function? Or was it supposed to be the index, like the deleteClick() call.

How to make dynamic dropdown menu?

<ul class="nav navbar-nav friend-label">
<li class="dropdown" ng-repeat="module in modules">
<a href="" class="dropdown-toggle" data-toggle="dropdown">
{{module.ModuleName}} <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li ng-repeat="subModule in module.SubModules">
<a href=""><b>{{subModule.SubModuleName}} </b>
</a>
</li>
</ul>
</li>
</ul>
By which, I'm getting following out put.
Question and problem is, when I do have submenu its fine if dropdown appears,
but when there is no submenu, dropdown should not come. still it shows dropdown small pointer arrow. and if you click it, it comes out with blank dropdown.
As shown in this fig, Contact Us menu doesn't have submenu. Still blank dropdown comes. I want to stop it using above code of HTML. Its a small problem. but I'm unable to fig it out.
Using ngRepeat you can dynamically populated menu from the model:
<span class="dropdown" dropdown on-toggle="toggled(open)">
<a href class="dropdown-toggle" dropdown-toggle>
Click me!
</a>
<ul class="dropdown-menu">
<li ng-repeat="choice in items">
<a ng-click="runFn(choice.fn)">{{choice.name}}</a>
</li>
</ul>
</span>
Look for fully worked example on Plunker
I am inferring that you are populating your dropdown items dynamically via ajax or server-side.
If that is true, then you could make use of small CSS/Javascript to hide empty menus. But, you have to take care of a few quirks.
First make sure that your markup looks like this:
<li class="dropdown">
Contact Us <span class="caret"></span>
<ul class="dropdown-menu" role="menu"></ul>
</li>
Important: Notice, that there is no white space between your ul.dropdown-menu start and end tags. This is because, the CSS :empty selector will fail if there is a white-space or line-break.
Now, if there are menu-items in your database you could populate those inside the ul.dropdown-menu as li. If there are no items, then it will left empty. At this point you will have a small dropdown which is empty and still a caret showing.
A little CSS can make the empty dropdown go away:
ul.dropdown-menu:empty {
display: none;
}
But, because CSS does not have reverse adjacent sibling combinator, we cannot target the caret. So, we have to resort to a little Javascript/jQuery:
$("ul.dropdown-menu:empty").prev("a").children("span.caret").first().hide();
You can choose to have both implemented only in jQuery if you wish to. This is just to give you an idea.
Put together your setup now looks and behaves something like this snippet below. Please view it in full-screen to prevent collapsing.
Snippet:
$("ul.dropdown-menu:empty").prev("a").children("span.caret").first().hide();
ul.dropdown-menu:empty {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<nav class="navbar navbar-default" role="navigation">
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li class="dropdown">
Dropdown <span class="caret"></span>
<ul class="dropdown-menu" role="menu">
<li>Action</li>
<li>Another action</li>
<li>Something else here</li>
</ul>
</li>
<li class="dropdown">
Contact Us <span class="caret"></span>
<ul class="dropdown-menu" role="menu"></ul>
</li>
</ul>
</nav>

angular binding span within custom dropdown

I have a custom dropdown like the one below which I use in a form to create roles. The purpose of the dropdown is to select a css-class to associate with a role. The name of the css-classes are role0, role1, role2.... role9
<ul class="dropdown-menu dropdown-select">
<li ng-repeat="i in [1,2,3,4,5,6,7,8,9,10]">
<a href="#"><input type="radio" ng-model="roleCss" value="role{{$index}}" name="d-s-r">
<span class="label role{{$index}}"> </span>
</a>
</li>
</ul>
how do I bind the value of roleCss, so it saves the correct value (eg. role1) ?
Thanks
Thomas
You pretty much have it correct. The only problem is that ng-repeat creates its own scope, so the roleCss you are saving into is in that scope, not your controllers scope. All you need to do is add $parent like this.
<ul class="dropdown-menu dropdown-select">
<li ng-repeat="i in [1,2,3,4,5,6,7,8,9,10]">
<a href="#"><input type="radio" ng-model="$parent.roleCss" value="role{{$index}}" name="d-s-r">
<span class="label role{{$index}}"> </span>
</a>
</li>
</ul>

Resources