Two mouseevents on the same button angular - angularjs

I am working on a project where there is required that the menu, which i have built by md-menu will do two functions on the same button.
Firstly it is that, once you click on the button, something happens, but also when you hover over it, it will open up the dropdown.
<md-menu-bar md-selected-nav-item="$ctrl.currentNavItem" md-no-ink-bar="$ctrl.landingPage" md-theme="reverse" aria-label="Main menu">
<md-menu ng-repeat="item in $ctrl.menuItems track by item.id">
<md-button ng-mouseover="$mdMenu.open()" ng-click="$ctrl.menuClick(item)">{{::item.name}}</md-button>
<md-menu-content ng-show="item.sub.length > 0">
<md-menu-item ng-repeat="subitem in item.sub">
<md-button ng-click="$ctrl.menuClick(subitem)">
{{::subitem.name}}
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
Is this even possible, or am I trying to solve something that's not even solvable?

Not sure if I've understood you correctly, but I think you can achieve it playing a litle bit with $timeout instead of opening the menu directly in ng-mouseover. It's just one choice.
Here you have a working example.
Code, just for reference. See the plunker for the complete details:
this.openMenu = function($mdMenu, ev) {
$timeout(function() {
if ($scope.openWhenHover) {
originatorEv = ev;
$mdMenu.open(ev);
}
}, 1000);
};
this.clickButton = function() {
$scope.clickedButton = true;
$scope.openWhenHover = false;
$timeout(function() {
$scope.clickedButton = false;
$scope.openWhenHover = true;
}, 1500);
};
Hope it helps

Related

md-tabs not showing scroll or pagination

I have recently upgraded my angularjs material version from 1.0.9 to 1.1.10. After the change my scroll bars have stopped showing up in the sides of my tab menu panels when there is an overflow. This used to work fine earlier.
Now I only see the following in the Devtools, for some reason the this flag is not becoming true for the pagination to work. Please let me know what could be the issue here.
<!-- ngIf: $mdTabsCtrl.shouldPaginate -->
This is the code that I have.
<div class="mainContentWrapper md-whiteframe-2dp" id="mainContentWrapper" style="overflow:auto;">
<div class="tab-panel">
<md-content class="md-padding">
<md-tabs md-selected="selectedIndex" md-border-bottom md-autoselect>
<md-tab>
<img class="dashboard" width="20" src="../../images/dashboard-icon1.png" />
<md-tooltip md-direction="right" ng-click="backToDashboard()">
Dashboard
</md-tooltip>
</md-tab>
<md-tab ng-repeat="tab in tabs"
ng-disabled="tab.disabled"
title="{{tab.desc}}" ng-if="$index>0">
{{tab.title}}
<md-tooltip>
{{tab.desc}}
</md-tooltip>
</md-tab>
</md-tabs>
</md-content>
</div>
There has been a change in implementation from 1.0.9 to 1.1.10. in the new version its using MutationObserver to detect any change to decide if it needs to show pagination.
var mutationCallback = function() {
ctrl.updatePagination();
ctrl.updateInkBarStyles();
};
if('MutationObserver' in $window) {
var config = {
childList: true,
subtree: true,
// Per https://bugzilla.mozilla.org/show_bug.cgi?id=1138368, browsers will not fire
// the childList mutation, once a <span> element's innerText changes.
// The characterData of the <span> element will change.
characterData: true
};
observer = new MutationObserver(mutationCallback);
observer.observe(element[0], config);
disconnect = observer.disconnect.bind(observer);
} else {
var debounced = $mdUtil.debounce(mutationCallback, 15, null, false);
element.on('DOMSubtreeModified', debounced);
disconnect = element.off.bind(element, 'DOMSubtreeModified', debounced);
}
Previously it was using only $mdUtil.debounce(mutationCallback, 100) which means it was updating the flags every 100ms. for some reason when I resize my window the mutation is not triggered. So I had to manually mutate the contents of the tab on resizing the tabs. I dont like this fix. Am I missing something?

Best way to implement a toggle button in AngularJS Material

I am looking for a simple solution to implement a toggle button with a custom selected / unselected icon in AngularJS Material.
The functionality should be identical to the md-checkbox (with ng-model for the selection state), but I want to have my own icon displayed for selected / unselected state. md-checkbox does not seem to support custom icons, and md-button lacks the ng-model.
Preferably I would like to avoid implementing a custom directive and only make this work through css. Is this possible with AngularJS Material?
You can define a toggle function to create toggle activity in your controller, like this:
$scope.toggle = function() {
$scope.variable = !$scope.variable
console.log($scope.variable);
}
Button on the html:
<md-button
ng-click="toggle()"
ng-class="{'active': variable, 'disable': !variable}">
After some digging the best solution currently seems to be using an md-button, which allows custom icons, and extending it with ng-click and ng-class like this:
<md-button ng-click="selected = !selected"
ng-class="{'selected-button' : selected}">
This takes care of the selection state. And in CSS I can then set the styles for the selected-button class
Even though the solution is rather simple, I think there should be an out-of-the-box support from Angular Material for a toggle button (or checkbox) with custom icons.
Properly using all classes of Angular Material v1.x
<md-button class="md-icon-button"
ng-click="filterToggle = !filterToggle"
ng-class="{'md-primary md-raised' : filterToggle}">
<md-tooltip md-direction="bottom">Filter</md-tooltip>
<md-icon ng-hide="filterToggle">filter_list</md-icon>
<md-icon ng-show="filterToggle">clear_all</md-icon>
</md-button>
in controller set
$scope.filterToggle = false;
var app = angular.module('app', []);
app.controller('CommentController', function($scope) {
$scope.filterToggle = true;
//start function.
$scope.StartFunc = function() {
$scope.filterToggle = false;
console.log('in pause function.');
};
$scope.CallFunc = function() {
$scope.filterToggle ? $scope.StartFunc() : $scope.PauseFunc();
}
// pause function.
$scope.PauseFunc = function() {
$scope.filterToggle = true;
console.log('in pause function.');
}
})
<link href="https://material.angularjs.org/1.1.2/angular-material.min.css" rel="stylesheet" />
<script src="https://material.angularjs.org/1.1.2/angular-material.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="CommentController">
<md-input-container>
<md-button class="md-icon-button md-primary md-raised" ng-click="CallFunc()">
<md-tooltip md-direction="bottom">Start/Pause Func</md-tooltip>
<md-icon ng-hide="filterToggle" style="background-color:grey;width:auto;">pause</md-icon>
<md-icon ng-show="filterToggle" style="background-color:grey;width:auto;">play_arrow</md-icon>
</md-button>
</md-input-container>
</div>
</div>

AngularJs - Opening a Bootstrap dropdown menu on page load by programmatically triggering the "click" event (NO jQuery)

May I ask if it's possible to trigger the click event of a dropdown menu programmatically on page load using AngularJS?
What I want to happen is that after loading the page, my navigation menu gets displayed automatically.
This is what I have so far:
<li class="menu-item" style="margin-top:15px">
<!-- Single button -->
<div class="btn-group open" uib-dropdown is-open="status.isopen">
<!-- Hamburger menu -->
<img ng-init="displayMainMenu()" id="nav-burger" uib-dropdown-toggle ng-disabled="disabled" ng-click="sMainMenu=true; isSubMenu=resetMenu(); getLinks(); bStopPropagation=true;" src="img/burger.png">
<!-- Main menu -->
<ul uib-dropdown-menu role="menu" aria-labelledby="single-button" ng-click="bStopPropagation && $event.stopPropagation()">
<!-- Main Menu -->
<li role="menuitem" class="main-menu-item" ng-repeat="link in links" ng-click="whatMenu(link.name); isSubMenu=false;" ng-show="isMainMenu">
<img id="{{link.icon}}">{{link.name}}<img class="navi-expand-icon">
</li>
<!-- End Main Menu -->
</ul>
</div>
</li>
And this is my Angular JS code:
$scope.displayMainMenu = function () {
var domElement = document.getElementById('nav-burger');
alert('before timeout'); // <-- This gets triggered
$timeout(function () {
angular.element(domElement).triggerHandler('click');
}, 0);
alert('after timeout'); // <-- This doesn't get triggered...
}
I have a feeling that I'm really close, however I couldn't figure out why it's not working.
Thank you in advance for your replies.
The ng-click on your image triggers this: ng-click="sMainMenu=true;"
However, to show your list items you have used isMainMenu ng-show="isMainMenu"
So I guess you made a typo.
Thank you for the clue Matheno! I did some more research about $timeout and finally got it to work by declaring $timeout in the controller:
app.controller('ctrlDropdown', function ($scope, $timeout) {
$scope.isMainMenu = true;
$scope.isSubMenu = false;
$scope.links = "";
$scope.subLinks = "";
$scope.selectedLink = "";
$scope.bStopPropagation = true;
...
}

AngularJs dropdown menu-content covering menu button

My dropdown menu content is covering up my dropdown button, any idea how to fix it? I want it to appear directly underneath my dropdown button. I have tried creating a class and style it in CSS as "position: absolute;" but it doesn't work.
Here is my code in angular:
<div ng-controller="Ctrll" ng-app="Fruit">
<div>
<md-menu>
<md-button ng-click="$mdOpenMenu()">Fruits
</md-button>
<md-menu-content class="dropdown" >
<md-menu-item >
<md-button ng-click="apple()">Apple</md-button>
</md-menu-item>
<md-menu-item>
<md-button ng-click="blueberry()">Blueberry </md-button>
</md-menu-item>
</md-menu>
</md-menu-content>
</div>
</div>
here is my Angular app
angular
.module('Fruit',['ngMaterial'])
.controller('Ctrll', function () {
var originatorEv;
this.openMenu = function($mdOpenMenu, ev) {
originatorEv = ev;
$mdOpenMenu(ev);
};
});
I have added it to codepen. Here is how my code looks like in action. http://codepen.io/zcook/pen/YqramL
Also, does anyone know how to change the color of the background of the dropdown menu content?
why can't you change the CSS property of class .md-open-menu-container.md-active?
.md-open-menu-container.md-active{
top: 45px !important;
}
Check this updated codepen

Angular material menu opening on mouse hover

I'm using Angular Material menubar to show a menu and the sub menu under each menu item. I've added ng-click event to open the submenu. But the menu is still opening on mouse hover on the parent menu item. Not only this, as I have two sub menus, for the first submenu item, the submenu is opening on mouse hover but the second submenu is not opening on mouse hover. How i can stop this menu opening on mouse over. I tried to stop event propagation on mouseenter on the parent menu item. But then at the time of opening second submenu the first submenu is not being hidden. Please help me how to fix it.
<div ng-controller="DemoBasicCtrl as ctrl" ng-cloak="" class="menuBardemoBasicUsage" ng-app="MyApp">
<md-menu-bar>
<md-menu>
<button ng-click="$mdOpenMenu()">
File
</button>
<md-menu-content>
<md-menu-item>
<md-menu>
<md-button ng-click="$mdOpenMenu()">New</md-button>
<md-menu-content>
<md-menu-item><md-button ng-click="ctrl.sampleAction('New Document', $event)">Document</md-button></md-menu-item>
</md-menu-content>
</md-menu>
</md-menu-item>
<md-menu-item>
<md-menu>
<md-button ng-click="$mdOpenMenu()">New</md-button>
<md-menu-content>
<md-menu-item><md-button ng-click="ctrl.sampleAction('New Document', $event)">Document</md-button></md-menu-item>
</md-menu-content>
</md-menu>
</md-menu-item>
</md-menu-content>
</md-menu>
</md-menu-bar>
My existing demo code is at demo.
Unfortunately Google is not fixing many of the Angular Material 1 issues, in favor of version 2.
I think this could be a way to encourage people to switch to Angular v2...
Anyway - I have solved the hover issue by stopping the event propagation on the menu item. Then adding a "mouse leave" event handler to the submenu container, that closes the current menu.
Controller -
$scope.noop = function(event){
event.stopImmediatePropagation();
};
$scope.closeSubMenu = function(event){
mdMenu.hide();
}
View -
<md-menu-item ng-repeat="item in menu.items" >
<md-menu-item>
<md-menu>
<md-button ng-click="$mdOpenMenu($event)" ng-mouseenter="noop($event)">{{item.title}}</md-button>
<md-menu-content ng-mouseleave="closeSubMenu($event)" >
<md-menu-item ng-repeat="subitem in item.items">
<md-button ng-click="$location.url(subitem.location)">{{subitem.title}}</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
</md-menu-item>
</md-menu-item>
it is very simple here is an answer, if you use bower to install angular-material, you need to:
go to /bower-components/angular-material/modules/js folder
open menu.js in any test editor such as visual code, sublime or atom
go to find this line this.handleMenuItemHover =
function(event) {
then use my fix:
this.handleMenuItemHover = function(event) {
if (self.isAlreadyOpening) return;
var nestedMenu = (
event.target.querySelector('md-menu')
|| $mdUtil.getClosest(event.target, 'MD-MENU')
);
openMenuTimeout = $timeout(function() {
if (nestedMenu) {
nestedMenu = angular.element(nestedMenu).controller('mdMenu');
}
if (self.currentlyOpenMenu && self.currentlyOpenMenu != nestedMenu)
{
var closeTo = self.nestLevel + 1;
self.currentlyOpenMenu.close(true, { closeTo: closeTo });
/******* david zhao: fix codes ******/
if (!!nestedMenu) {
self.isAlreadyOpening = true;
nestedMenu.open();
}
} else if (nestedMenu && !nestedMenu.isOpen && nestedMenu.open) {
self.isAlreadyOpening = true;
nestedMenu.open();
}
}, nestedMenu ? 100 : 250);
var focusableTarget =
event.currentTarget.querySelector('.md-button:not([disabled])');
focusableTarget && focusableTarget.focus();
};

Resources