ngClick on mdDialog's action button not triggering controller function - angularjs

I am trying to undertsand angular dialogs. I have created a very simple code to display a custom alert dialog. I am trying to pass a string message to the dialog. Dialog has an OK button which shoudl close it.
The message data is being passed correctly. However for some reason, the OK button is not triggering the dialog controller's function.
Here is my code
Alert.html - Contains template for Alert dialog
<md-dialog>
<md-dialog-content>
{{message}}
</md-dialog-content>
<md-dialog-actions>
<md-button ng-click="alertFunc">
OK
</md-button>
</md-dialog-actions>
</md-dialog>
AlertCtrl.js - Contains Controller for Alert Dialog
app.controller('AlertCtrl', function ($scope, $mdDialog, message) {
$scope.message = message
$scope.alertFunc = function () {
console.log("Closing Alert Dialog")
$mdDialog.hide()
}
})
DialogService.js - Contains API to launch alert dialog
app.service('DialogService', function($mdDialog) {
// Launch Alert Dialog
this.alert = function (message) {
// Show Dialog
$mdDialog.show({ templateUrl: 'Alert.html',
controller: 'AlertCtrl',
clickOutsideToClose: true,
locals: { message: message }
})
}
})
The log inside alertFunc never shows up.
I also tried putting controllerAs : 'ctrl' inside the $mdDialog.show. Then I changed the alertFunc declaration to this.alertFunc = function... and changed ng-click='ctrl.alertFunc'. However this did not work as well.
Can someone help me figure out the problem.
Thank You

It should be ng-click="alertFunc()" instead of ng-click="alertFunc". 2 hours of effort and a stupid parenthesis.
Amazing how ignorant a programmer can get.

Related

Angular JS material dialog with multiple options to save

I'm trying to have a dialog with multiple options to save and another option to save and close as well as cancel option, where the (save and close) button will save the data and close the dialog, while the (save) button will save the data in modal then open an empty instance of the modal, the problem is when adding two options with save I see only buttons for save and cancel, here is the angular Material Snippet example I'm modifying:
$scope.showConfirm = function(ev) {
// Appending dialog to document.body to cover sidenav in docs app
var confirm = $mdDialog.confirm()
.title('Would you like to delete your debt?')
.textContent('All of the banks have agreed to forgive you your debts.')
.ariaLabel('Lucky day')
.targetEvent(ev)
.ok('Save and Close')
.ok('Save')
.cancel('Cancel');
When clicking on Confirm Dialog button I would like to see three buttons, below is the modified code:
https://codepen.io/anon/pen/dgWzjw
You can't achieve the dialog presentation you've described using $mdDialog.confirm().
This method provides a preconfigured dialog that can only ever have two action buttons. You can build the dialog you want by providing more configuration parameters to $mdDialog.show().
Here's an example.
You'll need to provide the HTML for your custom dialog:
<script type="text/ng-template" id="custom-confirm.html">
<md-dialog>
<md-dialog-content>
<md-content layout-padding>
<div>...</div>
</md-content>
</md-dialog-content>
<md-dialog-actions>
<md-button ng-click="cancel()">Cancel</md-button>
<md-button ng-click="save()">Save</md-button>
<md-button ng-click="saveAndClose()">Save and Close</md-button>
</md-dialog-actions>
</md-dialog>
</script>
Then provide a custom dialog configuration to $mdDialog.show():
$scope.showCustomConfirm = function () {
$mdDialog.show({
controller: function ($scope, $mdDialog) {
$scope.cancel = function () {
$mdDialog.cancel();
};
$scope.save = function () {
/* ... */
};
$scope.saveAndClose = function () {
/* ... */
};
},
templateUrl: 'custom-confirm.html',
});
};
I've forked your CodePen to include the example described above.
Edit
To have the save button reopen the same dialog, simply chain the the call to open the dialog onto a call to first hide it. You can do this because the return value of $mdDialog.hide() is a promise that resolves once the dialog has hidden itself.
To follow on from the above example, you'll need to do some some slight refactoring to make sure you're not shadowing $scope:
$scope.showCustomConfirm = showCustomConfirm;
function showCustomConfirm() {
$mdDialog.show({
controller: function ($scope, $mdDialog) {
$scope.save = function () {
// Save data...
$mdDialog.hide().then(showCustomConfirm);
};
// Everything else as before...
},
});
}
And here's an updated CodePen fork.

Trying to fire a function inside an angular controller after bootstrap modal is dismissed

I'm basically trying to figure out how to do a certain event listener within an angular controller. More specifically, when a bootstrap modal is dismissed I would like to fire a function within the angular controller. In jquery you can normally do something like:
$(.some-class).on('click', function() {
// do something
});
What i have is a side navigation with images as buttons. I have gray buttons for when they're inactive and red buttons when they're active. Each button launches a bootstrap modal.
I'm using:
<a type="button" data-toggle="modal" data-target="#overview" ng-click="launchOverview()">
<img ng-src="{{ sideNavActive.overviewSrc }}" /><br />
</a>
and I have an object in my controller:
$scope.sideNavActive = {
"overviewSrc": "img/side-nav/tab-overview-off.png",
"detailsSrc": "img/side-nav/tab-details-off.png",
"contactSrc": "img/side-nav/tab-contact-off.png"
}
When the user clicks one of the side-nav buttons i have an ng-click function that changes the button to "img/...-on.png" so the button turns red (active). When the user clicks another side-nav button it turns that button red and the rest gray.
What I'm trying to do is when the user clicks in the faded area around the modal to dismiss it, i also want the buttons to all reset to gray. According to the bootstrap documentation I should be able to fire a function on the 'hidden.bs.modal' event but I can't get it to work in my angular controller. I have the following function where '#overview' is my id for my modal.
$('#overview').on('hidden.bs.modal', function() {
console.log('function fired!!!!!🔥');
$scope.sideNavActive = {
"overviewSrc": "img/side-nav/tab-overview-off.png",
"detailsSrc": "img/side-nav/tab-details-off.png",
"contactSrc": "img/side-nav/tab-contact-off.png"
}
})
However, this function doesn't fire when the modal is dismissed and I can't figure out why.
One thing I've done to see if the function is actually listening is changed it to:
$('body').on('click', function() {
// function code here
}
and it works. It fires whenever I click anywhere since it's listening on the 'body' element. So I know it's listening but for some reason the 'hidden.bs.modal' event isn't working.
I would use the angular-ui-bootstrap modal if you're not already: http://angular-ui.github.io/bootstrap/#!#modal. There is a callback function on the modal instance that is executed when the modal is dismissed:
modalInstance.result.then(function (someObj) {
// success
}, function () {
// this code will be executed when the modal is dismissed
console.log('Modal dismissed at: ' + new Date());
});
Figured out how to fire a function in an angular controller when modal is dismissed.
angular.element(document).find('.modal').on('hidden.bs.modal', function(){
// do something
console.log('function fired');
});

Pass variable to UI-bootstrap modal without using $scope

Since I am a beginner using AngularJS the $scope approach to pass data between different controllers and (in my case) a modal drives me crazy. Due to that reason, I googled around the web and found an interesting blogpost about passing data to a UI-bootstrap modal without using $scope.
I had a deeper look at this blogpost and the delivered plunk which works pretty nice and started to adopt this to my own needs.
What I want to achieve is to open a modal delivering an text input in which the user is able to change the description of a given product. Since this would provide more than a minimal working example I just broke everything down to a relatively small code snippet available in this plunk.
Passing data from the main controller into the modal seems to work as the default product description is displayed in the modal text input as desired. However, passing the data back from the modal to the main controller displaying the data in index.html does not seem to work, since the old description is shown there after it was edited in the modal.
To summarize my two questions are:
What am I doing wrong in oder to achieve a 'two-way-binding' from the main controller into the modal's text input and the whole way back since the same approach works in the mentioned blogpost (well, as the approach shown in the blogpost works there must be something wrong with my code, but I cannot find the mistakes)
How can I implement a proper Accept button in order to accept the changed description only if this button is clicked and discard any changes in any other case (clicking on Cancel button or closing the modal by clicking next to it)?
In your main controller, create two resolver functions: getDescription and setDescription.
In your modal controller, use them.
Your modal HTML
<div class="modal-header">
<h3 class="modal-title">Test Text Input in Modal</h3>
</div>
<div class="modal-body">
Product description:
<input type="text" ng-model="modal.description">
</div>
<div class="modal-footer">
<button ng-click="modal.acceptModal()">Accept</button>
<button ng-click="modal.$close()">Cancel</button>
</div>
Your main controller
function MainCtrl($modal) {
var self = this;
self.description = "Default product description";
self.DescriptionModal = function() {
$modal.open({
templateUrl: 'modal.html',
controller: ['$modalInstance',
'getDescription',
'setDescription',
ModalCtrl
],
controllerAs: 'modal',
resolve: {
getDescription: function() {
return function() { return self.description; };
},
setDescription: function() {
return function(value) { self.description = value; };
}
}
});
};
};
Your modal controller
function ModalCtrl($modalInstance, getDescription, setDescription) {
var self = this;
this.description = getDescription();
this.acceptModal = function() {
setDescription(self.description);
$modalInstance.close();
};
}

confirm modal using ngDialog

I am using ngDialog in my application and I would like to create a generic confirm modal , which I can use whenever I need , the confirm message is going to be different .
My questions :
1- Is creating a directive with the ngDialog functionality a good idea and what is its design ?
2- what is the difference between confirm() and openConfirm() in ngDialog code .
Thanks in advance
Well, to answer your questions,
1 - You can create a directive for it, having a scope, say type to which you pass the confirmation type ( i.e. submit for submit confirmations, delete for delete confirmations) and the directive should render the message based on the type you specified.
2 - openConfirm() is a type of ngDialog, which can only be closed by confirming the action (unlike ngDialog.open()), so you don't have the ability here to close the dialog when clicking anywhere in theDOM. confirm() is just a method you use to close the dialog, you use this method to close the dialog and resolve the promise that was returned when opening the modal, so it can go on <button ng-click="confirm()">Confirm</button> inside your dialog.
Hope this helped you
Update
openConfirm()
Opens a dialog that by default does not close when hitting escape or clicking outside the dialog window. The function returns a promise that is either resolved or rejected depending on the way the dialog was closed.
To resolve the promise, your dialog should be like this:
With ngDialog controller
ngDialog.openConfirm({
template: '<div></div>',
controller: ['$scope', function($scope) {
// Controller logic here
}]
}).then(function (success) {
// Success logic here
}, function (error) {
// Error logic here
});
With directive controller
ngDialog.openConfirm({
template: '<div></div>',
scope: $scope, // <- ability to use the scopes from directive controller
}).then(function (success) {
// Success logic here
}, function (error) {
// Error logic here
});
You can use your directive controller as long as you pass scope: $scope inside the dialog
Here is a demo showing you how you can use type
Try switching the type in index.html from confirm to remove and see the updated content and button text in the dialog

Click event gets executed even after window.confirm returns false in angular confirmation dialog

Based on the example given here I have written a directive to display a confirmation dialog in Angular when a button is clicked. The problem is even after the user clicks on the cancel button on the confirmation dialog, the ng-click action gets triggered.
This is the directive:
app.directive('ngConfirmClick',function(){
return {
link: function(scope, element, attr) {
var msg = attr.ngConfirmClick;
var clickAction = attr.ngClick;
attr.ngClick = "";
element.bind('click', function(event) {
if(window.confirm(msg)){
scope.$eval(clickAction);
}
});
}
}
});
This is the section of my index.html that has the ng-confirm-click directives:
<input class="delete" type="button" value="" ng-click="delete(item._id)"
ng-confirm-click="Are you sure you want to delete?">
I tried setting a priority of -1 for the ng-confirm-click directive and that did not help either.
When I was debugging the code on firebug, I found that window.confirm DOES return false when the user clicks on Cancel, so I am not sure why the ng-click (clickAction in the directive code above) is getting executed.
Is there a way to stop propagating the click action if window.confirm returns false?
Any help would be appreciated.

Resources