Don't destroy an Angular Bootstrap modal on close - javascript

I am using Angular Bootstrap to display a Modal (the one presented here), which works perfectly. However, default behavior of this Angular extension is that the modal is reconstructed (and a new instance of its controller will be creatred) whenever it is closed and then opened again.
Since I have some pretty advanced stuff going on inside the Modal, I would like the modal to just be hidden when it is closed, so that its state remains. I have searched around a bit, but unfortunately could not find a simple and effective answer.
Just hiding it would be an option, but this then has to happen whenever the modal is closed, so also when it closes because the backdrop is clicked. And I want the same animation as when the modal is opened in the normal way.

Why don't you abstract the modal state into its own service? That way, whenever the modal controller is created, it uses the service to setup the view state on initialisation.
Eg. create a service
.factory('ModalStateService', function(){
var state = {
someValue: 'something'
};
return {
getState: function() { return state; }
};
});
Then in your controller:
.controller('ModalCtrl', function($scope, ModalStateService){
$scope.viewState = ModalStateService.getState();
});
Then in your modal content view for example:
<span>{{viewState.someValue}}</span>
If you were then to set someValue inside your modal, say through an input, the service state would be updated. Then when you create and destroy your modal, the state will persist.

As you might already know Angular initializes a controller when the associated view is added to the DOM. So the plugin author might have decided to add and remove the view element so that he does not have to worry about clearing the 'scope'each time user opens and closes the modal.
For example, we have a login box in the modal and if the scope is not cleared, it will keep the filled in details even the next time we show it.
An easy hack to solve your problem will be to wrap the originl modal in a custom directive, reneder it. And just change the display property of your custom modal to show and hide the modal ;)

Related

How to re-open Bootstrap modal accidentally closed

I have a few different modals on a page, and it all works as it should, but if a user makes some input on form fields in a modal and then accidentally clicks outside of the modal (which closes it), they loose their changes, since if the user clicks the same button they pressed to open the modal, the data they entered will be overwritten with data pulled from the database.
So I'd like to have a function for "reopen last closed modal" that simply shows the modal again in it's last used state - with whatever data was in it.
Essentially like a Ctrl-Z for accidentally closing a modal.
It's really simple if you know the ID of the modal. Such as:
$('#myModal1').modal('show'); });
But because I have several different modals available on a page, and I don't want to have a bunch of "restore" buttons, I need to be able to detect the ID of the last closed modal.
If there's not a simpler way, I could capture the ID each time a modal is closed, and then use that ID if the modal needs to be reopened without changing its data. Something like this:
$('#myModal1').on('hidden.bs.modal', function (e) {
var LastModal = '#myModal1';
})
$('#myModal2').on('hidden.bs.modal', function (e) {
var LastModal = '#myModal2';
})
function reOpen() {
$(LastModal).modal('show');
}
But I'm guessing there's a way that's simpler and doesn't require me to state all my modals ID's in JS/jQuery. Any ideas?
I've made a few tweaks, and this is working well for me now, with essentially no other hassle than a few short lines of code in my script file.
var LastModal;
$('.modal').on('hidden.bs.modal', (e) => {LastModal = $(e.target).attr('id'); })
function reOpen() { $('#'+LastModal).modal('show');}
Just use the style class "modal" for your modals, and to call the "reOpen", just have something like:
<span onclick='reOpen();'>Reopen</span>
Thanks #marekful for your suggestion!
Also, if you want to access this (or any other function) by pressing Ctrl+Z, you can add this:
// press Ctrl+Z to restore modal
$(document).keydown(function(evt){
if (evt.keyCode==90 && (evt.ctrlKey)){
evt.preventDefault();
reOpen();
}
});

AngularJS - When opening controller in new browser window, clicks on the child window randomly triggers events on the parent window

I have a requirement that I am trying to implement as follows -
I have an audit log page which has a button to display the logs on a new browser window, while continuing to do other stuff on the application open in the main window.
We use ui-router and angularjs (1.6). Below is my code -
Route to the controller -
.state('auditlog', {
url: '/auditlog',
templateUrl: 'app/system/audit/audit-log.html',
controller: 'AuditLogController',
controllerAs: 'al'
})
On the click event of a button in a different controller, I have the following code -
unDockEventsPanel(event) {
let location = this.$state.href('auditlog');
this.$window.open(location, '', 'scrollbars=no,fullscreen=yes,toolbar=no');
}
and the HTML -
<i class="Icon-MoveOut Icon-Large icon-btn" ng-click="eventsPanelVM.unDockEventsPanel($event)">
Now, when I click on the "MoveOut" button the unDockEventsPanel() method gets called and a new window is opened with the contents of the controller/template in the route definition "auditlog".
The problem I'm facing however is, any operation I perform on the child window is randomly triggering something else on the parent window and vice versa. For eg. When I click on a select button in the child window, the select opens up on the child, but also, on the parent the a text box comes into focus like it would if I had clicked it. Likewise, when I click a select on the parent, a different control on the child gets highlighted.
I can see that a new instance of the application/controller is not created on the child and hence there is an overlap of the controls and events between the two. But I'm not able to figure out how to isolate the two.
Any help is greatly appreciated.
I believe the issue is related to the use of '$state'
let location = this.$state.href('auditlog');
this.$window.open(location, '', 'scrollbars=no,fullscreen=yes,toolbar=no');
from the angular-ui github wiki
When a state is activated, its templates are automatically inserted into the ui-view of its parent state's template.
I would suggest trying to avoid the use of $state by using plain old Javascript to do the new window navigation
window.open("{yourURL}/auditlog", 'scrollbars=no,fullscreen=yes,toolbar=no');

How to clear a featherlight modal

I am using feather-light modal in my page. on the modal one form is there with certain input fields. Once I fill in the fields and close the modal and when I open it again , it contains the previously filled data. I want to clear the data once it is closed. I am using angular js in my page.
Can anyone tell me how can I clear the feather-light modal using angular js?
Update-
In my code I have to open another modal after closing the first modal. And once second modal closes, if I am opening my first modal, its showing the previously filled data, I want to reset the modal data of first modal.
in my html I am using below code-
<button type="submit" ng-click="anotherModal(myForm)" ng-class="{ 'featherlight-close' : myForm.$valid}">Submit</button>
and in script I am using below code-
$scope.anotherModal= function (myForm) {
if ($scope.myForm.$valid) {
$scope.myForm.$submitted = true;
$.featherlight("#f12","open");
}
}
Can anyone tell me where should I add to reset the first modal?
Updated Plunker-
Please find my plunker here-
https://plnkr.co/edit/cDP1eqtUsKkeMaUiCIoM?p=preview
I am using persist ='shared' in my code because if I remove this then form validation won't work on first modal.
My issue is that when I open my second modal next time,it contains previously filled values and from there when I click on submit button my second modal doesn't show up.
Can anyone help me in solving my issue?
If you are using the persist option, then yeah, the form is persisted, so you'll have to clear it yourself.
If not, then you'll get a new copied form each time. In that case though, you'll have to be careful about how you bind it and avoid using any IDs, since those are supposed to be unique.
As far as I know featherlight is gallery plugin, used for displaying images in a lightbox. Considering this it is not meant to be used like that (even though you can, but it will not behave as you expect here out of the box), so that's why you'll have to cleanup behind you (or more specific your users), and on popup close action, clear all form fields. There are several ways to do that, eg. form reset button (input type="reset"), js callback on close popup or submit event (or in your case using angular js events), etc..
Since you didn't provide any code that's all I can tell you for now..
Also possible duplicate of Resetting form after submit in Angularjs
UPDATE
Not sure what exactly are you trying to achive here, but if you remove (or move inside showAnotherModal function) $.featherlight.defaults.persist=true; line, it works as you described, first popup is cleared when you open it for second time. Here is your snippet updated:
var app = angular.module('myApp', ['ngMessages']);
app.controller('myCtrl', function($scope) {
// $.featherlight.defaults.persist="shared";
$scope.showAnotherModal = function () {
$.featherlight.defaults.persist="shared";
if ($scope.myForm.$valid) {
$scope.myForm.$submitted = true;
$scope.myForm.dirty = false;
$scope.myForm.$setPristine();
$scope.myForm.$setUntouched();
$.featherlight("#fl3",'open');
}
}
});

Execute same function in all Controllers on the same event - AngularJS

I'm currently experiencing a problem with Bootstrap Modal, when changing views through the URL. ReloadOnSearch is disabled.
If I'm on a view such as:
blah.com/examples/1
and open up a Modal with a faded backdrop, then change the URL to change views such as:
blah.com/examples/2
the Modal window will close, but the faded backdrop will remain, and disable interaction to the web page.
I'm wondering if there is a way to define one function, which will programmatically remove the faded backdrop, which will execute on URL change, regardless of the controller in use.
Though the cause of the issue is due to AngularJS, the solution doesn't need to use AngularJS.
I had same issue, the solution is to remove that overlay class while your hashurl change
window.onhashchange = function() {
$(".lean-overlay").fadeOut(500); // whatever class name your overlay has
}
Use the event onhashchange to hide all modals on screen using the proper hide method:
window.onhashchange = function(event) {
$('.modal').modal('hide');
// You can even add some tests based on the new and old URL
console.log('new URL', event.newURL);
console.log('old URL', event.oldURL);
}

Hide Angular Bootstrap modal instead of close

I am using Angular Bootstrap Modal to open a bunch of modals including video player inside
http://angular-ui.github.io/bootstrap/#/modal
I want to be able to keep where the video is at even if the modal is closed. It's just so next time I open the same modal again, I can see where I left off in the video.
In order to do that, I need to do:
Create each modal a separate instance
Instead of close(), I need to hide() the modal instead. Therefore the DOMs are still in there and the video player don't get re-created
What's the elegant way to do this as the Bootstrap modal has no hide feature. Should I just use jQuery to show/hide the .modal-backdrop and .modal classes?
From Don't destroy an Angular Bootstrap modal on close:
Why don't you abstract the modal state into its own service? That way, whenever the modal controller is created, it uses the service to setup the view state on initialisation.
Eg. create a service
.factory('ModalStateService', function(){
var state = {
someValue: 'something'
};
return {
getState: function() { return state; }
};
});
Then in your controller:
.controller('ModalCtrl', function($scope, ModalStateService){
$scope.viewState = ModalStateService.getState();
});
Then in your modal content view for example:
<span>{{viewState.someValue}}</span>
If you were then to set someValue inside your modal, say through an input, the service state would be updated. Then when you create and destroy your modal, the state will persist.

Categories