angularjs custom confirm box
Solution 1
I created a repo for this functionality. It wraps the ui-bootstrap modal to produce a confirmation box. It is customizable and easily integrated into any application.
Here is the link to the GitHub: https://github.com/Schlogen/angular-confirm
Example Usages:
As a directive:
<button type="button" ng-click="delete()" confirm-if="checked" confirm="Are you sure, {{name}}?">Delete</button>
As a service:
$confirm({text: 'Are you sure you want to delete?'})
.then(function() {
$scope.deletedConfirm = 'Deleted';
});
Solution 2
It seems to me that you're trying to do things the jQuery way from within the directive. However, what you want is as simple as pulling in the UI-Bootstrap directive for confirming actions. http://plnkr.co/edit/JhfAF1?p=preview
Solution 3
First simple service for modal windows:
app.service('ConfirmService', function($modal) {
var service = {};
service.open = function (text, onOk) {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalConfirmCtrl',
resolve: {
text: function () {
return text;
}
}
});
modalInstance.result.then(function (selectedItem) {
onOk();
}, function () {
});
};
return service;
})
app.controller('ModalConfirmCtrl', function ($scope, $modalInstance, text) {
$scope.text = text;
$scope.ok = function () {
$modalInstance.close(true);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
Then simple directive that uses it:
app.directive('confirm', function(ConfirmService) {
return {
restrict: 'A',
scope: {
eventHandler: '&ngClick'
},
link: function(scope, element, attrs){
element.unbind("click");
element.bind("click", function(e) {
ConfirmService.open(attrs.confirm, scope.eventHandler);
});
}
}
});
And here u go:
<button ng-click="test(12)" confirm='Are you sure?'>Button</button>
http://plnkr.co/edit/LOZOnsVyx3JU5XoKYn74?p=preview
Solution 4
Here is a nice directive for that.That is ngBootbox
. Check it out.
<button class="btn btn-lg btn-primary"
ng-bootbox-title="A cool title!"
ng-bootbox-custom-dialog="Some custom text"
ng-bootbox-buttons="customDialogButtons"
ng-bootbox-class-name="some-class">
Custom dialog
</button>
<script>
$scope.customDialogButtons = {
warning: {
label: "Warning!",
className: "btn-warning",
callback: function() { $scope.addAction('Warning', false); }
},
success: {
label: "Success!",
className: "btn-success",
callback: function() { $scope.addAction('Success!', true) }
},
danger: {
label: "Danger!",
className: "btn-danger",
callback: function() { $scope.addAction('Danger!', false) }
},
main: {
label: "Click ME!",
className: "btn-primary",
callback: function() { $scope.addAction('Main...!', true) }
}
};
</script>
Solution 5
To allow a button to be marked up like
<button type="button" ng-click="deleteItem(drink)" ng-confirm="Are you sure you want to delete '{{drink.name}}'">Delete</button>
You can write a directive that
- Intercepts the click event before
ngClick
's click handler can run - Opens a dialog (using
$modal
and not the removed$dialog
) - On
close
of the dialog (which is treated as a success) run the function specified by thengClick
attribute on the element.
Basing the code on the previous answer, you can do this as follows:
app.directive('ngConfirm', function($modal, $parse) {
return {
// So the link function is run before ngClick's, which has priority 0
priority: -1,
link: function(scope, element, attrs) {
element.on('click', function(e) {
// Don't run ngClick's handler
e.stopImmediatePropagation();
$modal.open({
templateUrl: 'ng-confirm-template',
controller: 'ngConfirmController',
resolve: {
message: function() {
return attrs.ngConfirm;
}
}
}).result.then(function() {
// Pass original click as '$event', just like ngClick
$parse(attrs.ngClick)(scope, {$event: e});
});
});
}
};
});
which needs a simple controller:
app.controller('ngConfirmController', function($scope, $modalInstance, message) {
$scope.message = message;
$scope.yes = function() {
$modalInstance.close();
};
$scope.no = function() {
$modalInstance.dismiss();
};
});
and template for the dialog:
<script type="text/ng-template" id="ng-confirm-template">
<div class="modal-body">
<p>{{message}}</p>
</div>
<div class="modal-footer">
<button class="btn btn-link pull-left" ng-click="no()">No</button>
<button class="btn btn-primary pull-right" ng-click="yes()">Yes</button>
</div>
</script>
You can see this running at http://plnkr.co/edit/Gm9lFsGb099w6kCMQoVY?p=preview
Edit: changed plunker link to example without scrollbar appearing/disappearing on display of the dialog
Comments
-
James Kleeh almost 2 years
So I'm trying to implement a custom confirm box using Angular. Ideally, I would simply like to add an attribute to enable the functionality. Example:
<button type="button" ng-click="delete(foo)">Delete</button> -> <button type="button" ng-click="delete(foo)" ng-confirm="Are you sure you want to delete this foo?">Delete</button>
(foo is inside an ng-repeat... foo in fooList..)
So all of the problems I am having revolve around tying the click event that would normally happen to a different button. I have a seperate directive "confirmBox" that will create my modal (not using bootstrap) and handle all of the showing/hiding/etc.
What I am currently using requires me to alter my ng-click functionality, which I really want to get away from:
Current Implementation:
<button ... ng-click="confirm('Are you sure you want to delete this foo?, 'delete', foo)">Delete</button> var confirmModule = angular.module('confirm', []); confirmModule.run(function($rootScope) { $rootScope.confirm = function(text, func, obj) { $rootScope.$broadcast('confirm', func, obj, text); }; }); confirmModule.directive('confirmBox', function($parse) { return { restrict: 'A', template: myModalTemplate, link: function(scope, element, attrs){ element.hide(); var noBtn = element.find("[name='no']"); noBtn.bind("click", function() { element.hide(); }); scope.$on("confirm", function(event, func, obj, text) { var yesBtn = element.find("[name='yes']"); element.show(); yesBtn.unbind("click").bind("click", function() { scope[func](obj); }); }); } } });
Anyone have any ideas? I started by adding the directive for the button and then unbinding the click event so
ng-click
doesn't fire. Then I am left with the string'delete(foo)'
from theng-click
attribute that I can execute with$parse(attrs.ngClick)(scope)
, but I don't know how to tie that to the separate directives button click.Edit: Here is a fiddle with my current attempt at implementation. The problem is the variable being passed in to the function is always undefined.
Edit2: Updated implementation, however I don't particularly like how it links the two directives together by targetting the other directives elements.
-
James Kleeh about 11 yearsThe problem with this is that it requires you to put this dialog code in each function you want it to show. It really has nothing to do with the business logic of the application so imo, it shouldn't be there.
-
ScottGuymer about 10 yearsIt seems that angular UI has been refactored and the $dialog service has been removed and you can use messagebox functionality as indicated in the plunker anymore. stackoverflow.com/questions/19468127/…
-
James Kleeh about 10 yearsI could refactor it to use the $modal service in my confirm directive. I still don't want to use $modal in my controller - its view logic so doesn't belong there.
-
James Kleeh over 9 yearsThis implementation has the same idea as mine, however I can see some issues with it - see my answer.
-
Michal Charemza over 9 years@JamesKleeh What are the issues?
-
Demodave over 9 yearsThis one is pretty close but sort of jumps because it alters the scroll instead of doing an overlay.
-
Demodave over 9 yearsThis one looks cleaner than mine. Does this one still need the && confirm test within ng-click? Or is it binded somehow?
-
MartianMartian almost 8 yearsis there a way to use ONLY the UI-BS part of the code and not having to load the rest?
-
MartianMartian almost 8 yearsis there a way to not use the ui-bootstrap?