scope.$on $mdMenuOpen is not working - angularjs

I'm trying to listen for the $mdMenuOpen event in my directive.
.directive('mdPreventFocus', function () {
return {
restrict: 'A',
link: function (scope, element, attrs, $mdOpenMenu) {
element.on('click', function () {
console.log(scope);
scope.$on('$mdMenuOpen', function(ev, element) {
console.log('open');
});
})
}
}
})
<md-menu md-position-mode="target-right target" md-offset="0 42">
<md-button class="md-icon-button rounded dtp-btn-ok" ng-click="$mdMenu.open($event);" md-prevent-focus>
<i class="material-icons">more_horiz</i>
</md-button>
<md-menu-content class="person-popup contact-popup">
<md-card md-theme-watch>
<md-card-title>
<md-card-title-text>
<span class="md-headline">Headline</span>
<span class="md-subhead">Subhead informatie</span>
</md-card-title-text>
</md-card-title>
<md-card-actions layout="row" layout-align="end center">
<md-button title="Title informatie" class="md-icon-button icon-margin">
<i class="material-icons">phone</i>
</md-button>
<md-button title="Title informatie" class="md-icon-button icon-margin">
<i class="material-icons">email</i>
</md-button>
<md-button title="Title informatie" class="md-icon-button icon-margin">
<i class="material-icons" >forward</i>
</md-button>
</md-card-actions>
</md-card>
</md-menu-content>
</md-menu>
When I click the md-button I do see the console.log(scope) output but the scope.$on doesn't do anything.
If I check the scope in the console I do see $mdOpenMenu: ƒ
Also I can log the scope.$id which returns a value, but if I log scope.$mdMenuIsOpen I get a undefined. Which means the mdMenu is not open, otherwise it would be true. But in my UI the menu is open.
Any ideas why my scope.$on isn't working?
// EDIT //
It seems that only the first time I open the menu the scope.on('$mdMenuOpen') doesn't work. If I open the menu again I do see the console.log message.
// EDIT 2 //
I replicated my Code on a Codepen https://codepen.io/anon/pen/LmQNzv and there it does seem to work as intended. So I'm going see what the problem in my code is.

Related

mdDialog won't show templateUrl

Our team is using mdDialog to pull up a modal that allows a user to edit answers to a questionnaire.
$scope.editQuestionFnct = function(val){
$scope.editWidget = {};
//alert(val);
spUtil.get("gateway_questionnaire_widget", {//call new instance of this widget
//sys_id: $scope.params.refID,
task_id: $scope.data.task_id,
quest_id: val,
request: 'edit',
taskTable: $scope.data.task_table,
questionnaire_table: $scope.params.questionnaireTable,
serviceID: $scope.params.serviceID,
refID: $scope.params.refID,
taskCompleted: false,
editRequest: true
}).then(function(response) {
$scope.editWidget = response;//var to hold widget response to display in modal
$scope.showPrerenderedDialog('#editQuestion');
});
}
$scope.showPrerenderedDialog = function(name) {
$mdDialog.show({
templateUrl: name,
parent: angular.element(document.body),
clickOutsideToClose:true
});
};
$scope.closeDialog = function($scope){ //closes angular dialog window
$mdDialog.hide($scope);
}
$scope.closeSummDialog = function($scope){ //closes angular dialog window
$mdDialog.hide($scope);
}
<script type="text/ng-template" id="editQuestion">
<div class="md-dialog-container" >
<md-dialog style="background-color: #ffffff;" aria-label="edit dialog">
<md-toolbar style="background-color: #022C68; width: 100%;">
<h1 class="md-toolbar-tools" style="color: #ffffff;">Edit Response</h1>
</md-toolbar>
<md-dialog-content style="background-color: #ffffff;">
<div id="editQuestDiv" style="min-width: 700px;">
<sp-widget widget="editWidget"></sp-widget>
</div>
</md-dialog-content>
<md-dialog-actions layout="row">
<span flex></span>
<md-button ng-click="closeDialog()" style="background-color: #022C68; color: #ffffff;">
Close
</md-button>
</md-dialog-actions>
</md-dialog>
</div>
</script>
We are experiencing two problems with the above code:
First, instead of using templateUrl, we were using contentElement, which worked. Using contentElement pulled up a modal with the question that required editing. However, when a user clicks out of that first click, and clicks on another question, the same question that appeared in the first click shows up. Every click afterwards will only pull up the question from the first click.
After doing some reading, we decided to try and use templateUrl instead, but using that above opens up a modal with nothing in it:
Can someone explain what we're doing wrong? Are we doing something wrong with contentElement where only the question from the first click persists? If we were to use templateUrl, why isn't our modal showing up?
Thanks!

Using mdDialog with ng-repeat keeps displaying the same information from first click

Our team is building an app in ServiceNow and using AngularJS Material. We built a questionnaire that allows users to make edits to answers at the end. For the questions that can be edited, we're trying to use mdDialog that brings up a modal window where a user can edit their answers. The issue we're running into is that when a user clicks to edit an answer, then closes that modal to open up another answer to edit, the modal opens the first answer every time. We can't seem to close that scope to open another one.
In our HTML, we have a pencil glyphicon that has an ng-click for a function editQuestionFnct:
<td rowspan="2" style="color: #979797; padding-right: 15px; cursor: pointer;" ng-click="editQuestionFnct(item.quest_id)"><span class="glyphicon glyphicon-pencil" title="Edit Answer" style="padding-right: 5px;"></span></td>
That editQuestionFnct passes in several items into the showPrerenderedDialog function that generates the modal:
$scope.editQuestionFnct = function(val){
$scope.editWidget = {};
spUtil.get("gateway_questionnaire_widget", {//call new instance of this widget
task_id: $scope.data.task_id,
quest_id: val,
request: 'edit',
taskTable: $scope.data.task_table,
questionnaire_table: $scope.params.questionnaireTable,
serviceID: $scope.params.serviceID,
refID: $scope.params.refID,
taskCompleted: false,
editRequest: true
}).then(function(response) {
$scope.editWidget = response;//var to hold widget response to display in modal
$scope.showPrerenderedDialog('#editQuestion');
});
}
The showPrerenderedDialog function renders the modal:
$scope.showPrerenderedDialog = function(name) {
$mdDialog.show({
contentElement: name,
parent: angular.element(document.body),
clickOutsideToClose:true
});
};
Here is the md-dialog template:
<div style="visibility: hidden">
<div class="md-dialog-container" id="editQuestion">
<md-dialog style="background-color: #ffffff;" aria-label="edit dialog">
<md-toolbar style="background-color: #022C68; width: 100%;">
<h1 class="md-toolbar-tools" style="color: #ffffff;">Edit Response</h1>
</md-toolbar>
<md-dialog-content style="background-color: #ffffff;">
<!--<div id="editQuestDiv" style="min-width: 700px;">-->
<sp-widget widget="editWidget"></sp-widget>
<!--</div>-->
</md-dialog-content>
<md-dialog-actions layout="row">
<span flex></span>
<md-button ng-click="closeDialog()" class="md-primary md-raised">
Close
</md-button>
</md-dialog-actions>
</md-dialog>
</div>
What am i missing from the above code so that I can open one modal for a specific question and then open up another modal with another question? Thanks.

ng-click not responding when HTML added by JavaScript

ng-click is not working as it should. I tried looking at documentation and tutorials but couldn't find the reason.
I have a JavaScript variable storing html template. which by using
document.getElementById('someId').innerHTML = emptypage;
where emptypage is a JavaScript variable, is implemented inside a div with id=someId.
My Code:
var emptypage=` <md-toolbar `+ this.createID() +` class="md-accent
soopsObject" ng-app="vdApp">
<span class="example-spacer ng-controller="vdNav">
<md-sidenav class="md-sidenav-left" md-component-id="left" md-
disable-backdrop md-whiteframe="4">
<md-content layout-margin>
<p>
About
</p>
<p>
Contact
</p>
<md-button ng-click="toggleLeft()" class="md-accent">
Close
</md-button>
</md-content>
</md-sidenav>
<div>
<md-button ng-click="toggleLeft()">
<md-icon>menu</md-icon> Menu
</md-button>
</div>
</span>
</md-toolbar>`;
My Controller:
var nav=angular.module("vdApp", []);
nav.controller("vdNav", function($scope, $mdSidenav) {
alert("inside leftToggle");
$scope.toggleLeft = buildToggler('left');
function buildToggler(componentId){
return function(){
$mdSidenav(componentId).toggle();
};
}
});
Even alert isn't working.
What am I doing wrong? Any help or suggestion is appreciated.

how to create a collapsable/expandable open-locked sidenav with angular material

I want to have a sidenav with angular material which has 2 states: collapsed (only icons of the items are shown) and expanded (labes + icons shown). The example behaviour is shown at the RDash Dashboard, which is unfortunetally done with bootstrap.
Since the default sidenav of angular material does not provide that feature, I wanted to do it myself.
I have 2 ideas on how to do it:
1) using 2 different side-navs: one for collapsed, one for expanded. Then switching open-locked between them or just hiding/showing always one at a time.
2) using only 1 sidenav. somehow programmatically change the width, and the items of the sidenav and keeping it open-locked.
My favourite approach would be 2, but I want to know if there are any better ways to achieve that kind of sidenav with angular material?
I think approach 2 is the best - CodePen
Markup
<div ng-controller="AppCtrl" layout="column" style="height:500px;" ng-cloak="" class="sidenavdemoBasicUsage" ng-app="MyApp">
<section layout="row" flex="">
<md-sidenav class="md-sidenav-left" md-component-id="left" md-whiteframe="4" id="leftSideNav">
<md-toolbar class="md-theme-indigo" layout="row">
<h1 class="md-toolbar-tools">Sidenav Left</h1>
<span flex></span>
<md-button ng-click="toggleExpand()">{{toggleExpandButtonLabel}}</md-button>
</md-toolbar>
<md-content layout-padding="">
<md-button ng-click="close()" class="md-primary">
Close Sidenav Left
</md-button>
</md-content>
</md-sidenav>
<md-content flex="" layout-padding="">
<div layout="column" layout-align="top center">
<div>
<md-button ng-click="toggleLeft()" class="md-primary">
Toggle left
</md-button>
</div>
</div>
</md-content>
</section>
</div>
JS
angular
.module('MyApp',['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('AppCtrl', function ($scope, $timeout, $mdSidenav, $log, $element) {
$scope.toggleLeft = buildToggler('left');
$scope.toggleExpandButtonLabel = "Expand";
var sideNav = angular.element($element[0].querySelector('#leftSideNav'));
$scope.toggleExpand = function () {
if ($scope.toggleExpandButtonLabel == "Expand") {
sideNav.css("width", "500px")
}
else {
sideNav.css("width", "320px")
}
$scope.toggleExpandButtonLabel = ($scope.toggleExpandButtonLabel == "Expand") ? "Collapse" : "Expand";
}
$scope.close = function () {
$mdSidenav('left').close();
$scope.toggleExpandButtonLabel = "Expand";
sideNav.css("width", "320px")
};
function buildToggler(navID) {
return function() {
$mdSidenav(navID)
.toggle()
.then(function () {
$log.debug("toggle " + navID + " is done");
});
}
}
});

Angular: close ng-sidenav after a click on a element

Using angular & material, I have a sidenav on the left used to provide user's function (login, signup...).
Working fine, but I want the bar to be closed automatically once the user clicks on a menu. Currently, the bar stays open.
The sidebar code:
<md-sidenav md-component-id="user_sidenav" class="md-sidenav-left" flex>
<md-menu-content flex>
<md-menu-item>
<md-button ui-sref="app.user-state()">
<span>
User
</span>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button ui-sref="vlg.user-other-state()">
<span>
Other
</span>
</md-button>
</md-menu-item>
...
Any idea?
What I have done is create a function in the controller for closing the sidenav and then on clicking of an element calling the function.
app.controller('AppController', ['$scope', '$mdSidenav',
function ($scope, $mdSidenav) {
$scope.close = function () {
$mdSidenav('left').close();
};
}]);
and then in html
<div ng-controller="AppController">
<!-- Add in code for sidenav-->
<md-button ng-href="#/path" ng-click="close()"></md-button>
</div>
You could also just add the below code to a function if your elements already have a ng-click attached.
.then(function () {
$mdSidenav('left').close();
});

Resources