Problem with Side Menu, toggling, $ionicSideMenuDelegate

I’m trying to get what I thought was very basic functionality to work, but am unable, so am reaching out for help. I’ve checked the examples, and other issues on the forum, but haven’t had any luck.

My app uses the Side Menus - a Left and a Right menu. The Left menu has items for all the app’s main functions. The Right menu is a list of the app’s “friends” (app users who have signed up). One item in the Left menu is “Invite Friends”, which is supposed to toggle open the Right menu, to show a list of people that the user can select to invite to join the app.

So, the flow is supposed to be: User clicks the “Invite Friends” menu item in the Left menu. (This item does have “menu-close” as an attribute.) This action is supposed to toggle open the Right menu. But that’s not happening.

Here’s my Controller:

app.controller('MenuController', ['$scope', '$ionicSideMenuDelegate', function($scope, $ionicSideMenuDelegate)
{
	$scope.toggleFriendsList = function()
	{
		$ionicSideMenuDelegate.toggleRight();
	}
}]);

And here’s the HTML (remaining menu items omitted for brevity):

<div ng-controller="MenuController">
	<ion-side-menus>
	    <ion-side-menu-content>
	        <ion-header-bar class="bar-royal" animation="nav-title-slide-ios7">
	            <div class="buttons left-buttons">
	                <button id="menu-left" menu-toggle="left" class="button button-icon icon ion-navicon"></button>
	            </div>
	            <div class="buttons right-buttons">
	                <button id="menu-right" menu-toggle="right" class="button button-icon icon ion-navicon"></button>
	            </div>
	        </ion-header-bar>
	        <ion-nav-view animation="slide-left-right">
	        </ion-nav-view> 							
	    </ion-side-menu-content>

<!-- Left Menu (actual application menu) -->

	    <ion-side-menu side="left" >
	        <ion-header-bar  class="bar-royal">
	            <h1 class="title">Menu</h1>
	        </ion-header-bar >

	        <ion-content class="has-header">
	            <ion-list>
		            <ion-item menu-close class="item item-icon-left" ng-if="isAuthenticated()" ng-click="toggleFriendsList()">
		                <i class="icon ion-person-add"></i>Invite Friends<i class="icon item-icon-right ion-chevron-right menu-padding-special"></i>
		            </ion-item>
	            </ion-list>
	        </ion-content>
	    </ion-side-menu>

<!-- Right Menu (Friends list) -->

	    <ion-side-menu side="right" width="350">
	        <ion-header-bar class="bar-royal">
	            <h1 class="title">My Friends</h1>
	        </ion-header-bar>
			<ion-content has-header="true" ng-controller="FriendsController">
				<ion-list>
					<ion-item ng-click="doFriend(item)" class="rs-item item-icon-right" ng-repeat="item in list" style="padding:0px">
						....
					</ion-item>
				</ion-list>
			</ion-content>
	    </ion-side-menu>

	</ion-side-menus>
</div> 

The toggleFriendsList() function is definitely being called - it’s just the $ionicSideMenuDelegate.toggleRight() isn’t doing anything.

Can anyone see what the problem is? I’ve tried using delegate-handle, but got an error saying it couldn’t find an element with the handle name. I tried using $rootScope.$broadcast(event), sending an event to the FriendsController, thinking that having nested Controllers was the problem; no joy either. I even resorted to document.getElementById('menu-right').click(), and even that didn’t work. I give up. Help!

Thank you!

I found the problem - finally.

It appears that calling two $ionicSideMenuDelegate.toggleX() functions in a row is the problem. By sheer accident, I enclosed one of them in a setTimeout, with a 10ms delay. And then it worked! No idea why, but maybe it’s similar in nature to Node.js, where there are situations in which you have to place a call with a process.nextTick(), defering the execution of a callback until the next cycle in the event loop.

Angular doesn’t have event loops, of course. But, there are many situations in JavaScript on the client where calling two rendering-related functions breaks. And the solution is to “pause” the JavaScript execution to let the rendering threads catch up. And this is the effect that setTimeout() with a small timeout does. It is like a thread/process yield in C. It actually gives the browser a chance to finish doing some non-JavaScript things that have been waiting to finish before attending to this new piece of JavaScript. In actuality, setTimeout() re-queues the new JavaScript at the end of the execution queue.

So, that’s probably the right answer - and the solution to this issue - in case anyone else runs into this.

2 Likes

You have just saved me hours, thank you so much for posting the solution

I had a slightly different issue, where calling toggleLeft would start to open the left menu but then immediately close it. I believe it’s because a click anywhere in the content area is calling toggleLeft(false) under the covers to close the menu if it’s open, and there are therefore essentially 2 “simultaneous” clicks occurring. Adding a 100ms delay resolved the issue for now.

I have exactly the same issue I think where recently for some reason the left menu s dismissed immediately after it has been displayed. I was going to start a separate thread on this but if you have any additional information on why it is occuring and how you fixed it it would be much appreciated.