Detect $mdDialog close while pressing ESC - angularjs

I have a $mdDialog with input fields. Before closing $mdDialog, the content of the input fields is saved. So, when a user press 'close' button, a function is called to perform some operation on data and save them. However, I could not detect closing of $mdDialog on ESC. Is it possible to detect the closing event with ESC in the $mdDialog controller ?
Here is the sample code.
Codepen link
angular.module('MyApp', ['ngMaterial'])
.controller('AppCtrl', function($scope, $mdDialog, $rootScope) {
//$rootScope is used only of this demo
$rootScope.draft = ' ';
$scope.showDialog = function(ev) {
var msgDialog = $mdDialog.show({
controller: 'DemoDialogCtrl',
template: "<md-input-container><label>Text</label><input type='text' ng-model='myText' placeholder='Write text here.'></md-input-container><md-button ng-click='close()'>Close</md-button>",
})
};
});
(function() {
angular
.module('MyApp')
.controller('DemoDialogCtrl', DemoDialogCtrl);
DemoDialogCtrl.$inject = ['$scope', '$rootScope', '$mdDialog'];
function DemoDialogCtrl($scope, $rootScope, $mdDialog) {
$scope.close = function() {
//$rootScope is used only of this demo
// In real code, there are some other operations
$rootScope.draft = $scope.myText;
$mdDialog.hide();
}
}
})();
<div ng-controller="AppCtrl" class="md-padding dialogdemoBasicUsage" id="popupContainer" ng-cloak="" ng-app="MyApp">
<div class="dialog-demo-content" layout="row" layout-wrap="" layout-margin="" layout-align="center">
<md-button class="md-primary md-raised" ng-click="showDialog($event)">
Open Dialog
</md-button>
<div id="status">
<p>(Text written in $mdDialog text field must appear here when user closes the $mddialog. User can press close button or press ESC button.
</p>
<b layout="row" layout-align="center center" class="md-padding">
Draft: {{draft}}
</b>
</div>
</div>
</div>

You should use promise api.
$mdDialog.show().finally(
function onModalClose(){
}
);
But sink with external code should be used with other mechanism, for example by providing scope.
var modalScope = $rootScope.$new(true);
$mdDialog.show({scope: modalScope}).finally(function(){
$rootScope.draft = modalScope.myText;
});

Related

Method binding is not working in Angular

I am trying to attached a controller scope method in a directive but when i click in directive button that linked method is not called. Please review code. There is side-nav directive in which i have attached method with select parameter. but when button is clicked method is not called.
index.html
<div class="container" layout="row" flex ng-controller="userController as vm" ng-init="vm.loadUsers()">
<md-sidenav md-is-locked-open="true" class="md-whiteframe-1dp">
<side-nav users="vm.users" select="vm.selectUser(user)"></side-nav>
</md-sidenav>
<md-content id="content" flex>
<user-detail selected="vm.selected" share="vm.share()"></user-detail>
</md-content>
</div>
userController.js
app.controller("userController", ['$scope', 'userService', '$mdBottomSheet', function ($scope, userService, $mdBottomSheet) {
var self=this;
self.users = [];
this.name = "manish";
self.loadUsers = function () {
userService
.loadAllUsers()
.then(function (users) {
self.users = users;
self.selected = users[0];
userService.selectedUser = self.selected;
});
}
self.selectUser = function (user) {
self.selected = user;
userService.selectedUser = self.selected;
}
}]);
directives.js
app.directive("sideNav", function () {
return {
restrict :'AE',
templateUrl: './views/sidenav.html',
scope : {
select : '&',
users : '='
}
}
});
./views/sidenav.html
<md-list>
<md-list-item ng-repeat="user in users">
<md-button ng-click="select({user:user)">
<md-icon md-svg-icon="{{user.avatar}}" class="avatar"></md-icon>
{{user.name}}
</md-button>
</md-list-item>
</md-list>
Try doing it like this:
index.html
<side-nav users="vm.users" select="vm.selectUser"></side-nav>
./views/sidenav.html
<md-button ng-click="select()(user)">

Unable come out of the search on pressing ESC key

The Angular-Material based input/text field intend not to come out of the search on pressing ESC button; Is there any tweak for this?
Expected view on pressing Escape button
Current Elements panel
Here's an example of removing focus from an input with the escape key (I think that's what you are trying to achieve) - CodePen
Markup
<div ng-controller="DemoCtrl" ng-app="MyApp" ng-cloak>
<md-input-container md-theme="docs-dark" flex="">
<label>Name</label>
<input id="myInput" type="text" ng-keydown="inputKeydown($event)">
</md-input-container>
</div>
JS
(function () {
'use strict';
angular
.module('MyApp',['ngMaterial', 'ngMessages'])
.controller('DemoCtrl', DemoCtrl);
function DemoCtrl ($scope, $element) {
var myInput = angular.element($element[0].querySelector('#myInput'));
$scope.inputKeydown = function (event) {
if (event.key === "Escape") {
myInput.blur();
}
}
}
})();

bootstrap datetimepicker not working within modal

I am using bootstrap datetimepicker. Normally it is working. But in the modal pop up, it is not working. What could be the problem.
JS:
(function() {
'use strict';
angular
.module('app.inspection')
.controller('mainCtrl', mainCtrl)
.controller('scheduleModalCtrl', scheduleModalCtrl);
mainCtrl.$inject = ['$scope', '$state', '$modal'];
function mainCtrl($scope, $state, $modal) {
$scope.schedule_modal = function() {
var modalView = $modal.open({
templateUrl:'schedule_modal.html',
backdrop: 'static',
controller: 'scheduleModalCtrl',
windowClass: 'modal-dialog-schedule'
});
}
scheduleModalCtrl.$inject = ['$scope', '$modalInstance'];
function scheduleModalCtrl($scope, $modalInstance) {
$('#date').datetimepicker({
format: 'DD/MM/YYYY'
});
}
})();
schedule_modal.html
<div class="col-xs-12 col-sm-12 col-md-12">
<label for="insp-date" class="label-style">Date</label>
<div class='input-group date' id='date'>
<input type='text' class="input-style" placeholder="dd/mm/yyyy"/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
route.config.js :
.state('app.main', {
url: '/manageinspection',
title: 'Manage Inspection Page',
controller: 'mainCtrl',
templateUrl: helper.basepath('pages/main/main.html'),
resolve: helper.resolveFor('bootstrap','moment','bootstrapDateTimePicker')
})
I have include moment.js and bootstrapDateTimePicker constants in lazyload and in the route.config resolve. The datetimepicker is opening in mainCtrl(main page). It is not working in modal pop up, that is in scheduleModalCtrl.
I found several solutions, but they are all for ui-bootstarp datepicker but not for datetimepicker
Are you talking about angular-bootstrap-datetimepicker?
If you are, I had the same problem. The datepicker (using dropdown) never works fine on modal (at least bootstrap's modal).
My palliative solution, to maintain the consistency is "disable" the dropdown event on click in the input field. To execute the dropdown event, I'm using a 'input-group-addon' in this way:
<iframe width="100%" height="300" src="//jsfiddle.net/NandoMB/tLpbzkfj/27/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>

Angular JS simple button ng-click doesn't work

I have the following HTML
<html ng-app="processBeautifierApp">
...
<body ng-controller="PBCtrl" style="padding: 20px;">
<div id="header">
<div style="padding: 7px; float: right;">
<select ng-model="selectedProcess" ng-options="prozess as prozess for prozess in prozessListe"></select><br/>
<button type="button" ng-click="forceRefresh()">Force DCTM Refresh</button>
</div>
</div>
...
</body>
The corresponding javascript
var processBeautifierApp = angular.module('processBeautifierApp', []);
processBeautifierApp.controller('PBCtrl', function ($scope, $http, $interval, $window){
...
$scope.forceRefresh = function() {
...
}
});
The select element and the button are showing correctly. The options have been populated from the mode, $scope.selectedProcess changes when the user selects a different option.
But: The ng-click of the button doesn't react. $scope.forceRefresh() will never be called. There is no error on the console ... it just doesn't react at all. Can you see why?
Check the working example of your code plnkr.co
var processBeautifierApp = angular.module('processBeautifierApp', []);
processBeautifierApp.controller('PBCtrl', function ($scope, $http, $interval, $window){
$scope.forceRefresh = function() {
alert("asd");
}
});
Ok the solution was as simple as possible ... I am really ashamed
I used $scope.forceRefresh as the name of the function, but I also used $scope.forceRefresh somewhere else in the code as a boolean flag to enable/disable force refresh. Renaming the function did the trick

AngularJS: "TypeError: Cannot call method '$broadcast' of null"

I'm new to AngularJS and am working on my first mobile application starting with the Ionic Framework. I have a section where I have the user click on a "write review" button. This in turn opens an Ionic modal that has a form attached to it. When the user fills in the form and hits post I will be doing something with that data then the function it calls destroys the modal window. The error gets thrown after the form is submitted and I have the data everytime I open the write review button.
Code that opens the modal:
<a ng-controller="openReviewCtrl" ng-click="openModal()" class="item item-icon-left">
<i class="icon ion-compose"></i>
Write a Review (10 POINTS)
</a>
Review form Template:
<div class="modal" >
<header class="bar bar-header bar-positive">
<h1 class="title">Write Review</h1>
<button class="button button-clear button-positive" ng-click="closeModal()">Cancel</button>
</header>
<ion-content has-header="true" padding="true">
<form class="list">
<label class="item item-input">
<input type="text" placeholder="Full Name" ng-model="review.author" name="fullName">
</label>
<label class="item item-input">
<textarea placeholder="Review" cols="50" ng-model="review.text" name="review"></textarea>
</label>
<button class="button button-full button-positive" ng-click="writeReview(review)" />Post</button>
</form>
</ion-content>
</div>
And finally my Controller code (currently just logs data):
.controller('openReviewCtrl', function($scope, $ionicModal) {
$scope.master = {};
$ionicModal.fromTemplateUrl('templates/review.html', function(modal) {
$scope.modal = modal;
}, {
scope: $scope,
animation: 'slide-in-up'
});
$scope.openModal = function() {
$scope.modal.show();
};
$scope.closeModal = function() {
$scope.modal.hide();
};
//Be sure to cleanup the modal
$scope.$on('$destroy', function() {
$scope.modal.remove();
});
$scope.writeReview = function(review) {
console.log(review);
$scope.modal.remove();
};
})
Upon click of "Write Review" modal opens.
Data gets written in and submitted.
Logs what was written fine and closes Modal.
Upon clicking "Write Review" again throws error
Post button resets page and cancel does not work
TypeError: Cannot call method '$broadcast' of null
at ionic.views.Modal.inherit.show (http://angular.dev:8888/www/lib/js/ionic.bundle.js:31554:26)
at Scope.$scope.openModal (http://angular.dev:8888/www/js/controllers.js:49:18)
at http://angular.dev:8888/www/lib/js/ionic.bundle.js:17182:21
at http://angular.dev:8888/www/lib/js/ionic.bundle.js:33774:11
at Scope.$eval (http://angular.dev:8888/www/lib/js/ionic.bundle.js:18939:28)
at Scope.$apply (http://angular.dev:8888/www/lib/js/ionic.bundle.js:19039:23)
at HTMLAnchorElement.<anonymous> (http://angular.dev:8888/www/lib/js/ionic.bundle.js:33773:15)
at http://angular.dev:8888/www/lib/js/ionic.bundle.js:9578:10
at forEach (http://angular.dev:8888/www/lib/js/ionic.bundle.js:7272:20)
at HTMLAnchorElement.eventHandler (http://angular.dev:8888/www/lib/js/ionic.bundle.js:9577:5)
What is causing this?
I believe you need to create a new modal object using the $ionicModal.fromTemplateUrl method, instead of reusing the old modal object. Once the modal object is removed the angular bindings and $scope are destroyed and not available when you reopen it. The error comes from the modal trying to call broadcast on a $scope object that has been set to null.
I suspect your code should look something like this (I'm not sure when you have to call "modal.show()" so that might have to be moved):
.controller('openReviewCtrl', function($scope, $ionicModal) {
$scope.master = {};
function closeModal() {
if ($scope.modal) {
$scope.modal.remove();
delete $scope.modal;
}
}
$scope.openModal = function() {
$ionicModal.fromTemplateUrl('templates/review.html', function(modal) {
$scope.modal = modal;
modal.show();
}, {
scope: $scope,
animation: 'slide-in-up'
});
};
$scope.closeModal = function() {
closeModal();
};
//Be sure to cleanup the modal
$scope.$on('$destroy', function() {
closeModal();
});
$scope.writeReview = function(review) {
console.log(review);
closeModal();
};
})
Presumably it might also be possible to fix the ionic modal code to be reusable, but I've not looked at this.

Resources