I am building a collapsable dropdown vertical menu and I've got most of all the functionalities working except one that is eluding me. And that is, rotating the icon so that it shows up when it's open and pointing down when it's closed.
I have a CodePen that you can use. I've updated the code below to show the changes that are now closest to the solution.
Here is my HTML
<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="{'fa fa-chevron-down rotate180': open1, 'fa fa-chevron-down': !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="{'fa fa-chevron-down rotate180': open2, 'fa fa-chevron-down': !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>
And here is what's inside my controller. The toggle function is workout and I figured, it would probably be a good idea to attach the icon rotation to this function so that they work together. But I am having a hard time figuring it out. The closest I got to it was with this function below. But it changes all the icons in the same click
$scope.open1 = false; //initial value
$scope.open2 = false; //initial value
$scope.toggle = function(itemPos) {
if ($scope.menuIsOpen === itemPos) {
$scope.menuIsOpen = 0;
}
else {
$scope.menuIsOpen = itemPos;
}
}
Either an AngularJS or JavaScript solution will be fine. I'll prefer AngularJS. No Bootstrap suggestions please. This is an Angular Material application. It doesn't use Bootstrap. Thanks again!
I am building a collapsable dropdown vertical menu and I've got most of all the functionalities working except one that is eluding me. And that is, rotating the icon so that it shows up when it's open and pointing down when it's closed.
I have a CodePen that you can use. I've updated the code below to show the changes that are now closest to the solution.
Here is my HTML
<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="{'fa fa-chevron-down rotate180': open1, 'fa fa-chevron-down': !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="{'fa fa-chevron-down rotate180': open2, 'fa fa-chevron-down': !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>
And here is what's inside my controller. The toggle function is workout and I figured, it would probably be a good idea to attach the icon rotation to this function so that they work together. But I am having a hard time figuring it out. The closest I got to it was with this function below. But it changes all the icons in the same click
$scope.open1 = false; //initial value
$scope.open2 = false; //initial value
$scope.toggle = function(itemPos) {
if ($scope.menuIsOpen === itemPos) {
$scope.menuIsOpen = 0;
}
else {
$scope.menuIsOpen = itemPos;
}
}
Either an AngularJS or JavaScript solution will be fine. I'll prefer AngularJS. No Bootstrap suggestions please. This is an Angular Material application. It doesn't use Bootstrap. Thanks again!
Share Improve this question edited Jan 26, 2017 at 15:58 Heretic Monkey 12.1k7 gold badges61 silver badges131 bronze badges asked Jan 26, 2017 at 14:44 LOTUSMSLOTUSMS 10.3k18 gold badges78 silver badges153 bronze badges 10- Is it adding the class or giving any console error?? – Shubhranshu Commented Jan 26, 2017 at 14:51
- no errors. I technically didn't violate any Javascript or Angular rule, it's just not built logically – LOTUSMS Commented Jan 26, 2017 at 14:52
- I think it's not finding the element.. So why don't you try to get it directly from the menu-item class . and try finding in its children.. Instead of using closest and find... – Shubhranshu Commented Jan 26, 2017 at 14:58
- I think I tried that and I could be wrong, but the actual condition is in the md-menu-item ng-if="....". The menu-item div has the click listener to fire the function but not the condition. If you check my codepen, it has angular code instead javascript but it is doing all of the icons instead of the one that is being clicked on. I think this could work if I could get help with isolating the event. – LOTUSMS Commented Jan 26, 2017 at 15:02
-
The problem is you have 2 menu items to handle, but you just have one mon
class
andmenuIsOpen
properties. Ideally each menu object should have these properties and your code will work fine. I've logged in via mobile and did some quick tweak in your code and is working fine. – Developer Commented Jan 26, 2017 at 15:19
2 Answers
Reset to default 4In case you need to animate the opening and closure of the menu icon you could also apply 2 different CSS classes with different CSS transform properties.
And use ng-class accordingly using 2 expressions:
HTML
ng-class="{'fa fa-chevron-down rotate180': open1, 'fa fa-chevron-down rotate-back': !open1}"
CSS CLASSES
.rotate180 {
display: inline-block;
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
-webkit-transition: all linear 200ms;
transition: all linear 200ms;
}
.rotate-back {
display: inline-block;
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
-webkit-transition: all linear 200ms;
transition: all linear 200ms;
}
CODEPEN
http://codepen.io/alexincarnati/pen/zNEPoW
Add a $scope variable named opened and set it 0.
Toggle its value in your ng-click based on which menu is clicked like this ... opened=1;
And use it with your ng-class:
<i ng-class="{'fa fa-chevron-up': opened===1, 'fa fa-chevron-down': opened!==1}"></i>
You'd do this for each menu using a different number to identify it, 1,2,3...