open one dropdown at a time while using ngHide/ngShow angular directives - angularjs

I have a simple dropdown menu that I want to tweak a little. I need help with animating the dropdown so it's scaling down when it opens. But that is not my biggest concern. What I really need help with is opening only one dropdown at a time. So if I open one and another one had already been previously opened, it should close.
I'm using Angular-Material, so I am looking for an Angular Controller or directive solution please, one that uses ngHide/ngShow directives perhaps? Not sure about that part.
This is my HTML
<md-list ng-click="menuIsOpen = !menuIsOpen" layout="row" layout-padding="" class="layout-row" layout-align="start center" flex>
<span class="title flex" flex=""> Menu Item</span>
<i class="fa fa-chevron-down"></i>
</md-list>
<div class="sub-menu">
<ul ng-init="menuIsOpen= false" ng-show="menuIsOpen">
<md-menu-item ng-repeat="item in data">
<md-button>
<div layout="row" flex="">
<a ui-sref="{{item.link}}">
<p flex=""><i class="fa fa-{{item.icon}}"></i> {{item.title}}</p>
</a>
</div>
</md-button>
</md-menu-item>
</ul>
</div>
<md-list ng-click="menu2IsOpen = !menu2IsOpen" layout="row" layout-padding="" class="layout-row" layout-align="start center" flex>
<span class="title flex" flex=""> Menu Item 2</span>
<i class="fa fa-chevron-down"></i>
</md-list>
<div class="sub-menu">
<ul ng-init="menu2IsOpen= false" ng-show="menu2IsOpen">
<md-menu-item ng-repeat="item in data">
<md-button>
<div layout="row" flex="">
<a ui-sref="{{item.link}}">
<p flex=""><i class="fa fa-{{item.icon}}"></i> {{item.title}}</p>
</a>
</div>
</md-button>
</md-menu-item>
</ul>
</div>
I have a CODEPEN you can checkout. Thanks a lot!

In ng-click, set variable menuIsOpen to ng-click="menuIsOpen = 1" and as ng-show="menuIsOpen === 1 " Do the same thing with other menus.
Example
var app = angular.module("app", []);
app.controller("ctrl", function($scope) {
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<button ng-click="menuIsOpen = 1">About Page</button>
<button ng-click="menuIsOpen = 2">Help page</button>
<button ng-click="menuIsOpen = 3">Info Page</button>
<button ng-click="menuIsOpen = 4">Refrence page</button>
<div class="form-group" ng-show="menuIsOpen===1">
<p>About page</p>
</div>
<div class="form-group" ng-show="menuIsOpen===2">
<p>Help page</p>
</div>
<div class="form-group" ng-show="menuIsOpen===3">
<p>Info</p>
</div>
<div class="form-group" ng-show="menuIsOpen===4">
<p>Refrence</p>
</div>
</div>
<div ng-controller="ListBottomSheetCtrl" class="md-padding bottomSheetdemoBasicUsage" ng-cloak="" ng-app="MyApp">
<div class="cnt">
<md-list ng-click="menuIsOpen = 1" layout="row" layout-padding="" class="layout-row" layout-align="start center" flex>
<span class="title flex" flex=""> Menu Item</span>
<i class="fa fa-chevron-down"></i>
</md-list>
<div class="sub-menu">
<ul ng-init="menuIsOpen= false" ng-show="menuIsOpen === 1 ">
<md-menu-item ng-repeat="item in data">
<md-button>
<div layout="row" flex="">
<a ui-sref="{{item.link}}">
<p flex=""><i class="fa fa-{{item.icon}}"></i> {{item.title}}</p>
</a>
</div>
</md-button>
</md-menu-item>
</ul>
</div>
<md-list ng-click="menuIsOpen = 2" layout="row" layout-padding="" class="layout-row" layout-align="start center" flex>
<span class="title flex" flex=""> Menu Item 2</span>
<i class="fa fa-chevron-down"></i>
</md-list>
<div class="sub-menu">
<ul ng-init="menu2IsOpen= false" ng-show="menuIsOpen === 2 ">
<md-menu-item ng-repeat="item in data">
<md-button>
<div layout="row" flex="">
<a ui-sref="{{item.link}}">
<p flex=""><i class="fa fa-{{item.icon}}"></i> {{item.title}}</p>
</a>
</div>
</md-button>
</md-menu-item>
</ul>
</div>
</div>
</div>

I solved try following:
<div ng-controller="ListBottomSheetCtrl" class="md-padding bottomSheetdemoBasicUsage" ng-cloak="" ng-app="MyApp">
<div class="cnt" ng-init="menuIsOpen= false; menu2IsOpen= false">
<md-list ng-click="menuIsOpen = !menuIsOpen; menu2IsOpen = false" layout="row" layout-padding="" class="layout-row" layout-align="start center" flex>
<span class="title flex" flex=""> Menu Item</span>
<i class="fa fa-chevron-down"></i>
</md-list>
<div class="sub-menu">
<ul ng-show="menuIsOpen">
<md-menu-item ng-repeat="item in data">
<md-button>
<div layout="row" flex="">
<a ui-sref="{{item.link}}">
<p flex=""><i class="fa fa-{{item.icon}}"></i> {{item.title}}</p>
</a>
</div>
</md-button>
</md-menu-item>
</ul>
</div>
<md-list ng-click="menu2IsOpen = !menu2IsOpen; menuIsOpen = false" layout="row" layout-padding="" class="layout-row" layout-align="start center" flex>
<span class="title flex" flex=""> Menu Item 2</span>
<i class="fa fa-chevron-down"></i>
</md-list>
<div class="sub-menu">
<ul ng-show="menu2IsOpen">
<md-menu-item ng-repeat="item in data">
<md-button>
<div layout="row" flex="">
<a ui-sref="{{item.link}}">
<p flex=""><i class="fa fa-{{item.icon}}"></i> {{item.title}}</p>
</a>
</div>
</md-button>
</md-menu-item>
</ul>
</div>
</div>
Here is CODEPEN

Related

How to apply ng-repeat on carousel with multiple items using angular js?

<div class="carousel slide" id="myCarousel">
<div class="carousel-inner">
<div class="item active">
<div class="row">
<div class="col-md-3 home__li-align" ng-
repeat="electronic in allItem.slice(0,4) | filter :enter code here 'electronics'">
<a ui-sref="" ng-click="`enter code here`view(mobile)">
<img ng-src="../asset/img/{{electronic.image[0]}}" alt="Not Found" style="height: 200px;width:50%;" />
<div class="home__label-align">{{electronic.product_name}}</div>
<div class="home__label-align"> ₹: {{electronic.cost}}</div>
</a>
</div>
</div>
</div>
<div class="item">
<div class="row">
<div class="col-md-3 home__li-align" ng-repeat="electronic in allItem.slice(4,8) | filter : 'electronics'">
<a ui-sref="" ng-click="view(mobile)">
<img ng-src="../asset/img/{{electronic.image[0]}}" alt="Not Found" style="height: 200px;width:50%;" />
<div class="home__label-align">{{electronic.product_name}}</div>
<div class="home__label-align"> ₹: {{electronic.cost}}</div>
</a>
</div>
</div>
</div>
</div>
<a class="left carousel-control" href="#myCarousel" data-slide="prev" style="margin-bottom: 70px; margin-left: -70px; color: black;"><i class="glyphicon glyphicon-chevron-left" ></i></a>
<a class="right carousel-control" href="#myCarousel" data-slide="next" style="margin-bottom: 70px; margin-right: -70px; color: black;"><i class="glyphicon glyphicon-chevron-right"></i></a>
</div>
Only item active class is working and i want 4 div in one slide of carousel then on clicking carousel control. It should bring next carousel having 4 div.So any Solution of that?
I can understand your problem and i created solution fiddle please follow below link.
<script>
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
myApp.controller("MyCtrl",MyCtrl);
function MyCtrl($scope) {
$scope.list = [];
for(var i = 0; i< 16;i++){
$scope.list.push(i);
}
}
</script>
<div ng-app="myApp" ng-controller="MyCtrl">
<div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
<!-- Indicators -->
<ol class="carousel-indicators">
<li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
<li data-target="#carousel-example-generic" data-slide-to="1"></li>
<li data-target="#carousel-example-generic" data-slide-to="2"></li>
</ol>
<!-- Wrapper for slides -->
<div class="carousel-inner" role="listbox">
<div class="item active">
<div class="row">
<div class="col-sm-3" style="height:100px; background:red; color:green; font-size:18px;" ng-repeat="l in list.slice(0,4)">
Hello {{l}}
</div>
</div>
</div>
<div class="item">
<div class="row">
<div class="col-sm-3" style="height:100px; background:red; color:green; font-size:18px;" ng-repeat="l in list.slice(4,8)">
Hello {{l}}
</div>
</div>
</div>
<div class="item">
<img src="http://placehold.it/450x350" alt="Slide 3">
<div class="carousel-caption">
Caption Slide 3
</div>
</div>
</div>
<!-- Controls -->
<a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#carousel-example-generic" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
</div>
http://jsfiddle.net/r2wLz6xr/507/

How do I make the card title heights the same when content is different

I've run into this before and just forced it to work with a bunch of custom css but that seems sloppy. This seems completely backwards to how I would expect it to work. The content should flex to match the height, not the header. Any ideas on how to fix this besides custom css? Is there an "angular-material" way to fix it?
<div layout-gt-sm="row" flex="1">
<md-card ng-show="!trackingStored.loading" flex="20">
<md-card-title>
<md-card-title-text layout-align="center center">
<span class="md-headline"> General </span>
</md-card-title-text>
</md-card-title>
<md-divider style="width:100%;"></md-divider>
<md-card-content layout="column" layout-align="center center" flex = "1">
<dl>
<dt ng-show="trackingStored.VehicleStatus">Status</dt>
<dd ng-show="trackingStored.VehicleStatus">{{trackingStored.trackingInfo.VehicleStatus}}</dd>
<dt>Location</dt>
<dd>{{trackingStored.trackingInfo.ConfirmationNumber}}</dd>
<dt>Year</dt>
<dd>{{trackingStored.trackingInfo.VehicleYear}}</dd>
<dt>Make</dt>
<dd>{{trackingStored.trackingInfo.VehicleMake}}</dd>
<dt>Model</dt>
<dd>{{trackingStored.trackingInfo.VehicleModel}}</dd>
<dt>VIN</dt>
<dd>{{trackingStored.trackingInfo.VehicleVIN}}</dd>
<dt ng-show="trackingStored.trackingInfo.DropOffDate.HasValue">Dropped off</dt>
<dd ng-show="trackingStored.trackingInfo.DropOffDate.HasValue">{{trackingStored.trackingInfo.DropOffDate.Value}}</dd>
</dl>
</md-card-content>
</md-card>
<md-card ng-show="trackingStored.trackingInfo.RecentHistory != null && trackingStored.trackingInfo.RecentHistory.length > 0"
flex="80">
<md-card-title >
<md-card-title-text layout-align="center center">
<span class="md-headline"> Maintenance History </span>
</md-card-title-text>
</md-card-title>
<md-divider style="width:100%;"></md-divider>
<md-card-content>
<h4>(12 most recent entries)</h4>
<div layout-gt-xs="row" layout-wrap layout-align="space-between center">
<div ng-repeat="item in trackingStored.trackingInfo.RecentHistory track by $index" flex="50" flex-xs="100" style="width:100%;">
<md-card>
<md-card-title class="customCardHeader">
<md-card-title-text>
<span class="md-headline customCardHeaderText"> {{item.CompletedDate | date: trackingStored.dateFormat}} </span>
</md-card-title-text>
</md-card-title>
<md-divider> </md-divider>
<md-card-content>
<div>{{item.Comments}}</div>
</md-card-content>
</md-card>
</div>
</div>
</md-card-content>
</md-card>

Content inside md-card spilling over despite having layout-wrap in its parent tag

Part of my html file below:
<md-content class="md-padding" layout="row" layout-wrap>
<md-card flex="30" ng-repeat="classified in classifieds" class="classified">
<img src={{classified.image}} class="md-avatar"></img>
<md-card-content>
<div class="classified-info" ng-hide="showContact">
<h2 class="md-title">{{classified.title}}</h2>
<h3>{{classified.price | currency}}</h3>
<p>{{classified.description}}</p>
</div>
<div class="classfied-contact" ng-show="showContact">
<p><md-icon class="mdi mdi-account"></md-icon>{{classified.contact.name}}</p>
<p><md-icon class="mdi mdi-phone"></md-icon>{{classified.contact.phone}}</p>
<p><md-icon class="mdi mdi-account"></md-icon>{{classified.contact.email}}</p>
</div>
<div layout="row">
<md-button ng-hide="showContact" ng-click="showContact=true">Contact</md-button>
<md-button ng-show="showContact" ng-click="showContact=false">Details</md-button>
<md-button ng-hide="showAdmin" ng-click="showAdmin=true">Admin</md-button>
<md-button ng-show="showAdmin" ng-click="showAdmin=false">Close</md-button>
</div>
<div class="classified-admin" ng-if="showAdmin">
<h3>Admin</h3>
<div layout="row">
<md-button class="md-primary" ng-click="editClassifieds(classified)">Edit</md-button>
<md-button class="md-warn">Delete</md-button>
</div>
</div>
</md-card-content>
</md-card>
</md-content>
Despite having layout-wrap in my md-content tag, I have some content of the card spilling over when I click on an expanding button inside it(see below image):

preventing ng-click event with angular-material

I have a series of toggles inside a custom angular dropdown(s). The problem I am having is, the toggles do toggle, but they close the dropdown as well. How can I prevent this? The dropdowns should still close when double clicking the drawer, that is the expected behavior, but not when the toggle is clicked.
This is the HTML:
<div class="cnt" ng-repeat="item in data">
<div class="menu-item" ng-click="toggle(item.pos);">
<md-list layout="row" layout-padding="" class="layout-row" layout-align="start center" flex>
<span class="title flex" flex=""> {{item.name}}</span>
<i class="fa fa-chevron-down" ng-class="{'rotate180': item.pos==menuIsOpen, 'rotate-back': !menuIsOpen}"></i>
</md-list>
<div class="sub-menu" ng-animate="'animate'" >
<div ng-repeat='(k,v) in item track by $index'>
<div ng-if="isArray(v)">
<md-menu-item ng-if="menuIsOpen===item.pos" ng-repeat='v1 in v track by $index'>
<md-button>
<div layout="row" flex="">
<md-switch class="md-primary" name="special" ng-model="project.special" required>
<span class="">
<p flex="">{{v1.title}}</p>
</span>
</md-switch>
</div>
</md-button>
</md-menu-item>
</div>
</div>
</div>
</div>
</div>
and the controller has this in it for functionality purposes and data population from json :
$scope.toggle = function(itemPos) {
if ($scope.menuIsOpen === itemPos) {
$scope.menuIsOpen = 0;
}
else {
$scope.menuIsOpen = itemPos;
}
}
$scope.isArray = function(val) {
return Array.isArray(val);
}
spoiler alert:adding md-prevent-menu-close="true" to the md-button didn't help
Here is a CODEPEN to try things out
Thanks guys
You should move your ng-click="toggle(item.pos);" into the <md-list>
<div class="cnt" ng-repeat="item in data">
<div class="menu-item">
<md-list layout="row" layout-padding="" class="layout-row" layout-align="start center" flex ng-click="toggle(item.pos);">
<span class="title flex" flex=""> {{item.name}}</span>
<i class="fa fa-chevron-down" ng-class="{'rotate180': item.pos==menuIsOpen, 'rotate-back': !menuIsOpen}"></i>
</md-list>
<div class="sub-menu" ng-animate="'animate'" >
<div ng-repeat='(k,v) in item track by $index'>
<div ng-if="isArray(v)">
<md-menu-item ng-if="menuIsOpen===item.pos" ng-repeat='v1 in v track by $index'>
<md-button>
<div layout="row" flex="">
<md-switch class="md-primary" name="special" ng-model="project.special" required>
<span class="">
<p flex="">{{v1.title}}</p>
</span>
</md-switch>
</div>
</md-button>
</md-menu-item>
</div>
</div>
</div>
</div>
</div>

Minimalizing a menu with ng-repeat

I know the question title is a little vague but I don't know what else to call it. Basically, this is my problem:
I have an angular menu with submenus. I have each menu item separate and the submenu items being injected with ng-repeat. That is fine, but the problem is I would like to run the entire menu in one ng-repeat and have the json file hold, not only the submenu items, but the menu items as well. This is what I have:
<div class="cnt">
<div class="menu-item" ng-click="toggle(1); open1=!open1">
<md-list layout="row" layout-padding="" class="layout-row" layout-align="start center" flex>
<span class="title flex" flex=""> Menu Item</span>
<i class="fa fa-chevron-down" ng-class="{'rotate180': open1, 'rotate-back': !open1}"></i>
</md-list>
<div class="sub-menu" ng-animate="'animate'" >
<md-menu-item ng-if="menuIsOpen===1" ng-repeat="item in data" >
<md-button>
<div layout="row" flex="">
<a ui-sref="{{item.link}}">
<p flex=""><i class="fa fa-{{item.icon}}"></i> {{item.title}}</p>
</a>
</div>
</md-button>
</md-menu-item>
</div>
</div>
<div class="menu-item" ng-click="toggle(2); open2=!open2">
<md-list layout="row" layout-padding="" class="layout-row" layout-align="start center" flex>
<span class="title flex" flex=""> Menu Item 2</span>
<i class="fa fa-chevron-down" ng-class="{'rotate180': open2, 'rotate-back': !open2}"></i>
</md-list>
<div class="sub-menu" ng-animate="'animate'" >
<md-menu-item ng-if="menuIsOpen===2" ng-repeat="item in data2">
<md-button>
<div layout="row" flex="">
<a ui-sref="{{item.link}}">
<p flex=""><i class="fa fa-{{item.icon}}"></i> {{item.title}}</p>
</a>
</div>
</md-button>
</md-menu-item>
</div>
</div>
</div>
with a json file that looks like this:
$scope.data =
[{
title: 'Home',
icon: 'home',
link: '/page1/'
}, {
title: 'Email Us',
icon: 'envelope',
link: '/page2/'
}, {
title: 'Profile',
icon: 'user',
link: '/page3/'
}, {
title: 'Print',
icon: 'print',
link: '/page4/'
}];
$scope.data2 =
[{
title: 'Home 2',
icon: 'home',
link: '/page1/'
}, {
title: 'Email Us 2',
icon: 'envelope',
link: '/page2/'
}, {
title: 'Profile 2',
icon: 'user',
link: '/page3/'
}, {
title: 'Print 2',
icon: 'print',
link: '/page4/'
}];
As you can see, if I want 2 menu items, I have to build the code for 2 menu items, add the data to the json, and run the bindings. And if I want 3, then I have to do this 3 times. But what if I want 20? Ideally, I would like to have 1 single HTML structure that pulls the data from the json to create as many menu items with as many submenu items as it finds in the json. But I am having problems trying to achieve this:
This is what makes sense in my head:
<div class="cnt" ng-repeat="item in data">
<div class="menu-item" ng-click="toggle({{item.pos}}); open{{item.pos}}=!open{{item.pos}}">
<md-list layout="row" layout-padding="" class="layout-row" layout-align="start center" flex>
<span class="title flex" flex=""> {{item.name}}</span>
<i class="fa fa-chevron-down" ng-class="{'rotate180': open{{item.pos}}, 'rotate-back': !open{{item.pos}}}"></i>
</md-list>
<div class="sub-menu" ng-animate="'animate'" >
<md-menu-item ng-if="menuIsOpen==={{item.pos}}" >
<md-button>
<div layout="row" flex="">
<a ui-sref="{{item.item1[0].linkto}}">
<p flex=""><i class="fa fa-{{item.icon}}"></i> {{item.item1[0].title}}</p>
</a>
</div>
</md-button>
</md-menu-item>
</div>
</div>
</div>
I have a CODEPEN that you can see the working code in.
See this CODEPEN for the desired effect. This is how I have it working now and how it should work ultimately.
Thanks fellas!
This answer is not directly addressing the parsing issue, but a solution to what you are trying to achieve.
Instead of using open{{item.pos}} to identify the menu item, which is resulting in parsing error, use the the menuIsOpen,which holds the position of the toggled item. Based on the desired effect.. codepen sample
script additions
//Not needed
// $scope.open1 = false; //initial value
//$scope.open2 = false; //initial value
//$scope.open3 = false; //initial value
//$scope.open4 = false; //initial value
$scope.toggle = function(itemPos) {
if ($scope.menuIsOpen === itemPos) {
$scope.menuIsOpen = 0;
}
else {
$scope.menuIsOpen = itemPos;
}
}
html : just need toggle the item we pass the position property
<div class="cnt" ng-repeat="item in data">
<div class="menu-item" ng-click="toggle(item.pos);">
<md-list layout="row" layout-padding="" class="layout-row" layout-align="start center" flex>
<span class="title flex" flex=""> {{item.name}}</span>
<i class="fa fa-chevron-down" ng-class="{'rotate180': item.pos==menuIsOpen, 'rotate-back': !menuIsOpen}"></i>
</md-list>
<div class="sub-menu" ng-animate="'animate'" >
<md-menu-item ng-if="menuIsOpen===item.pos" >
<md-button>
<div layout="row" flex="">
<a ui-sref="{{item.item1[0].linkto}}">
<p flex=""><i class="fa fa-{{item.icon}}"></i> {{item.item1[0].title}} a</p>
</a>
</div>
</md-button>
</md-menu-item>
</div>
</div>
</div>
Let us know
Update : based on your comment, the current setup only deals with item at postion 0 (only 1 item). The JSON (if you do not have control) and you need the item1 item2 etc.. to be displayed you can extend the ng-repeat by going over the entire object and iterate ONLY the ARRAYS. This is not going for the optimal solution just a work around.. sort of..
If there is another array of links inside the array.. this solution will not work.
html
<div class="sub-menu" ng-animate="'animate'" >
<div ng-repeat='(k,v) in item track by $index'>
<div ng-if="isArray(v)">
<md-menu-item ng-if="menuIsOpen===item.pos" ng-repeat='v1 in v track by $index'>
<md-button>
<div layout="row" flex="">
<a ui-sref="{{v1.linkto}}">
<p flex=""><i class="fa fa-{{v1.icon}}"></i> {{v1.title}}</p>
</a>
</div>
</md-button>
</md-menu-item>
</div>
</div>
</div>
script
$scope.isArray = function(val) {
return Array.isArray(val);
}

Resources