-
Notifications
You must be signed in to change notification settings - Fork 6.7k
$modal: Cannot disable backdrop/keyboard after modal has been instantiated #967
Comments
Also, the This has no effect:
|
@georgiosd blocking ability to close modal is an interesting use case. I don't think I've got a nice solution to this right now, probably something like AngularJS does with route evens (that you can cancel) would work. But yeh, it is en interesting use-case that we should support this way or another. As for the issue with default options - could you provide a plunker with a minimal reproduce scenario? We've got tests for this functionality so I would be very, very surprised if it is broken. |
Hm... What about allowing to pass a function to keyboard/backdrop properties? Re the options: I didn't explain myself fully. You use your own internal reference to the defaults which means that this will work:
but this won't:
|
Woops, actually 8e7fbf0 covers only part of the problem (default options), didn't mean to close. |
Another thought would be to allow binding the properties in the scope! Now that scope is supported :) |
@pkozlowski-opensource perhaps: var modal = $modal.open( ... );
modal.options( { ... } );
// or
modal.options( 'optionName', newValue); Might be a non-trivial thing to implement. |
Any news on this? |
You can do this since forever with the $modalStack: Inject it in the controller, then do something like |
I believe I've found quite elegant workaround for this issue. We could decorate app.config(function($provide) {
$provide.decorator('$modal', function($delegate) {
var open = $delegate.open;
// decorate newly created modalInstance with some custom methods
$delegate.open = function() {
var modalInstance = open.apply(this, arguments);
modalInstance.freeze = function(freeze) {
modalInstance._freezed = freeze;
};
// return true when the modal instance is freezed and
// dismiss reason is 'backdrop click' or 'escape key press'
modalInstance.freezed = function(reason) {
if (!modalInstance._freezed) { return false; }
return _.contains(['backdrop click', 'escape key press'], reason);
};
return modalInstance;
};
return $delegate;
});
$provide.decorator('$modalStack', function($delegate) {
var dismiss = $delegate.dismiss;
// do nothing when the modal is freezed
// otherwise fallback to the old behaviour
$delegate.dismiss = function(modalInstance, reason) {
if (modalInstance.freezed(reason)) { return; }
dismiss.apply(this, arguments);
};
return $delegate;
});
}); ...and in the modal's controller we could use var FormCtrl = function($scope, $modalInstance, list) {
this.$modalInstance = $modalInstance;
this.list = list;
};
angular.extend(FormCtrl.prototype, {
submit: function(list) {
// create/update new record
var promise = list.isPersisted() ? list.$update() : list.$create();
// freeze the modal keyboard/backdrop close until request is completed
this.$modalInstance.freeze(true);
promise.finally(angular.bind(this, function() {
this.$modalInstance.freeze(false);
}));
// close the modal and resolve it with updated/created record
promise.then(angular.bind(this, function(list) {
this.$modalInstance.close(list);
}));
return promise;
},
cancel: function() {
this.$modalInstance.dismiss();
}
}); BONUS. Also we could use this solution for creating a directive for freezing modals when the embedded form was changed. app.directive('glFreezeModal', function($parse) {
return {
restrict: 'A',
require: 'form',
link: function(scope, element, attrs, form) {
var modalInstance = $parse(attrs.glFreezeModal)(scope);
scope.$watch(function() { return form.$dirty; }, function(dirty) {
modalInstance.freeze(dirty);
});
}
}
}); This simple directive will prevent a user from accidentally lost his changes by pressing The complete code is here https://gist.github.com/lucassus/9e7bbb89a630f3390b2f |
Great solution @lucassus, works perfectly. |
I am closing this as I do not think this is an appropriate feature to move into this library. One can always work around this by having a modal controller with a close method that checks a condition before allowing the user to close the modal, which is the appropriate approach. |
@wesleycho Can we re-open this? As it stands, the 'backdrop' and 'keyboard' properties can only be specified when the modal is instantiated and @georgiosd use-case is reasonable and probably frequently utilized (disable escaping the modal via esc key or clicking outside the modal while data retrieval is in process). Hitting escape on your keyboard or clicking outside the modal do not invoke (at least natively) any controller function and instead make calls to $dismiss and $close in the modalStack object, so your solution to have a "controller with a close method that checks a condition before allowing the user to close the modal" doesn't seem applicable unless I am misunderstanding. As it stands the only solution that works is the decorator solution @lucassus provided, and I think its a reasonable request to be able to modify these properties within the modal itself, rather than only at insantiation time. |
|
In a common modal with a submit action, we need to be able to change whether the modal can be closed by clicking on the backdrop or by hitting ESC.
example case:
The text was updated successfully, but these errors were encountered: