Bootstrap 4 Modal as Confirm Revisited - javascript

I wanted to make a "flexible" confirm dialog with Bootstrap 4 as I do not want to hardcode each confirm modal / action on its own.
So, with a standard Modal like
<div class="modal fade" tabindex="-1" role="dialog" id="msgModal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="msgModalTitle">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" id="msgModalBody">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Doch nicht</button>
<button type="button" class="btn btn-primary" id="btnModelConfirmMessage">OK</button>
</div>
</div>
</div>
</div>
and the respective js-magic :D
function showConfirm(htmlInput,headerTxt, fun){
$('#msgModalTitle').text(headerTxt);
$('#msgModalBody').html(htmlInput);
$('#msgModal').modal('show');
$('#btnModelConfirmMessage').click(function () {
fun();
$('#msgModal').modal('hide');
});
}
I thougth, that by sending the "action" part as function which will exceute as soon the "OK" button #btnModelConfirmMessage is clicked.
Works like a charm, BUT it has a major bug.
It seems that the event-handler stays on the modal, i.e. if I show and just hide the modal the OK button will fire the function twice.
Among others I found this post
Bootstrap modal firing up incrementing times
where it suggest to move the click() event outside. I am sure this would work on that specific task, however I would lose the function.
So how can I unbind the handler using the hide.bs.modal event?

After reading the jquery-doc the answer is fairly easy:
Change:
$('#btnModelConfirmMessage').on('click',function () {
fun();
$('#msgModal').modal('hide');
});
Then add a new call on the hide.bs.modal event
$('#msgModal').on('hide.bs.modal',function () {
$('#btnModelConfirmMessage').off();
});
This removes the previously added handler, so we do not stack-up the events.
Hope someone will find this usefull :))
Cheers,
Daniel

Related

Bootstrap modal not becoming active element on toggle, background scrolling but modal not scrolling

I have a web page that makes use of a number of different modals to display information to the user.
These modals are triggered by certain buttons, which usually call $("#id").modal("toggle") to toggle the modal's visibility on. In one particular scenario, I have one modal which displays a second modal through the use of the above stated function. It also hides itself through the use of the same function, so I have an onClick function that does the following.
$("#EditTask").modal("hide");
$("#AddressProspect").modal("show");
The issue is that when the AddressProspect modal is displayed, it seems as though it is not being changed to the active element. The background goes dark, and the modal is displayed correctly. However when I attempt to scroll, the background elements scroll instead, as if the modal hasn't actually been displayed.
I have attempted a number of different approaches. I have used .modal("show") and .modal("hide") to display the modals I need. I have also trieddata-dismiss="modal" within the button of the modal that needs to be hidden. These have all produced the exact same result.
Interestingly, if I go to my console and execute the following commands
$("body").css("overflow-y", "hidden");
$("#AddressProspect").css("overflow-y", "scroll");
The background becomes unscrollable, and the AddressProspect modal becomes scrollable, just as I would expect.
I have around 10 modals being used within my page, and none of them have this problem apart from the one in question. I have posted the code to the two modals mentioned in this post below, with their bodies removed for clarity.
<div class="modal fade bd-example-modal-lg" id="EditTask" tabindex="-1" role="dialog" data-keyboard="false" data-backdrop="static" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel"><span class="Title">Title</span></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
-snip-
</div>
<div class="modal-footer">
<div style="width: 100%">
<button type="button" class="btn btn-warning action-skip-instruction" style="float: left;" data-dismiss="modal">Skip Instruction</button>
</div>
<button type="button" class="btn btn-secondary action-close-edit-modal">Close</button>
<button type="button" id="edit-task-button-defer" class="btn btn-warning edit-task-action" style="display: none;">Defer</button>
<button type="button" id="edit-task-button-action" class="btn btn-success edit-task-action" data-dismiss="modal">Complete</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="AddressProspect" tabindex="-1" role="dialog" data-keyboard="false" data-backdrop="static" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" style="max-width: 600px;" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">New Security Address Prospect</h5>
</div>
<div class="modal-body">
-snip-
</div>
<div class="modal-footer">
<div style="width: 100%">
<button type="button" class="btn btn-warning prospect-button-clear" style="float: left;">Clear</button>
</div>
<button type="button" style="float: left;" class="btn btn-danger prospect-button-close" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-success prospect-button-update">Update</button>
</div>
</div>
</div>
</div>
After a decent amount of time having issues with this problem I have managed to figure out why it is happening and how to fix it.
There are two places I looked for information on this topic:
This Github issue on the Bootstrap repo
The Bootstrap documentation on modal methods
From reading the Github issue we can see that one user notes that the calls to .modal("hide") and .modal("show") are asynchronous, therefore using them in quick succession is invalid. Instead we must wait for the show/hide to complete by listening for the shown or hidden events.
To do this we can use the following function:
$('#myModal').on('hidden.bs.modal', function (e) {
// do something...
})
By checking for the hidden.bs.modal class to be placed into the modal's classlist we can verify when the hide animation has completely finished. At this point we can then call the show method of the next modal to be displayed, ensuring that all of the background events handled by Bootstrap have finished executing, and ensuring that behaviour is expected.
My previous code goes from being:
$("#EditTask").modal("hide");
$("#AddressProspect").modal("show");
to:
$("#EditTask").modal('toggle');
$("#EditTask").on("hidden.bs.modal", function() {
$("#AddressProspect").modal('toggle');
});
As soon as I tried the new code, the weird issues with scrolling disappeared.

open alert window once modal submit button clicked

<div class="modal" id="myInquiry" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button class="close" data-dismiss="modal">×</button>
<h4 id="myModalLabel">Thank you for your feedback:</h4>
</div>
<div class="modal-body">
<label for="inquiry">Feedback:</label>
<textarea class="form-control" rows="5" id="inquiry"></textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary" data-dismiss="modal" id="send">Send</button>
</div>
</div>
</div>
</div>
This is the code I have for my modal footer. I am wanting to click the send button and close the modal. Once it has been closed I want to have an alert window or modal pop up and thank the user for giving their feedback. I am new to web development and am getting stuck on this issue after numerous attempts (after finding different solutions on other questions) but nothing is working.
The modal's div id is 'myInquiry' if that helps.
Thank you!
You need to add an action to your modal Close button, worst way would be like:
<button type="button" class="btn btn-default" data-dismiss="modal" onclick="alert('thank you');">Close</button>
you can add the ID to the button and then use jQuery to handle the action, and show something better than this.
You can add jQuery code like this.
$('button#send').click(function() {
alert('Alert Content');
}
Then you can see the alert "Alert Content" when you click the Send Submit button.
Bootstrap modal has a hide.bs.modal event, you can listen to that event and then, when the modal is closed (hidden from user) you can show the thank modal. Here is an example on jsfiddle. Cheers, sigfried.
Maybe you can try adding an
onclick="window.alert('<Your text here>')"
attribute to the button.

How to properly trigger default action on a bootstrap dialog?

Most of the answers on SO are either about how to activate a modal dialog box or how the dismissal works.
However what I find lacking is how to trigger an action that the default button signifies.
For example,
the default action of this dialog is 'Save'.
Here is the html markup
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">Dialog</h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" id="btn-save" class="btn btn-primary btn-save">Save</button>
</div>
</div>
</div>
</div>
If I call $('#myModal).modal('show'), the dialog box will appear.
If I click on the cross on upper right corner or the 'Close' button, the dialog box will be dismissed as expected.
However, when I press 'Save', nothing happens.
I used a round-about way to implement it:
It is written in coffeescript.
$('#myModal).on('click', _.bind(#_handleSave, #))
$('#myModal).modal('show')
Then inside _handleSave,
_handleSaveProfile: (data) ->
return unless data.target.id is 'btn-save'
# Do saving
# ...
I don't think it is the right way because it intercepts every click event.
What is the proper to implement this function?
bind the click event to the button instead of the modal :
$('#myModal').modal('show')
$('#btn-save').on('click', _.bind(#_handleSave, #))

Understanding how data-dismiss attribute works in Bootstrap

I'm new to Bootstrap and i'm facing problem with this example:
<!-- Trigger the modal with a button -->
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal">Open Modal</button>
<!-- Modal -->
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<p>Some text in the modal.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
As per my understanding data-dismiss="modal" attribute should close the modal if you click on it, but i don't understand how it works behind the scene. I checked the official documentation at: http://getbootstrap.com/javascript/#modals-examples but there's no explaination.
The hiding functionality is implemented in the modal.js in this way.
this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
Basically it's just finding the elements that have the attribute of data-dismiss and the value of modal. Upon click it will hide these elements.
replace data-dismiss="modal" by: onclick="$('#modal_id').modal('hide');"
You should have something like this:
<button type="button" class="close" onclick="$('#modal_id').modal('hide');" aria-label="Close">
onclick="$('#modal_id').modal('hide');" will close only the particular modal in which it is placed.
please note if it is this answer is useful.
If u use multiple modals on one page open at the same time on top of each other dismissing the topmost with data-dismiss="modal" will hide all active modals.
exactly in bootstrap.js find the element with attribute data-dismiss="modal" and trigger this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) behind. i.e. it hides the element but in more complex way.
It is roughly equivalent to onclick="$(this).closest('.modal').modal('hide')", i.e. it is searching the DOM upward for .modal (means, the definition of dialog itself) and hides it. The dialog's DOM is not removed.
I triggered the data dismiss with JQuery like so
$('.close').click();
This triggered like if user would of clicked the close button on modal, making data-dismiss hit. You might run in to some issues if there is layers of modals at one, hence will close all.
reference to where I found my solution here

Meteor's Iron Router doesn't close modal dialog

I'm using Meteor and Iron Router, and I have a modal dialog that won't hide the backdrop when it gets dismissed. To be more accurate, I want that after clicking the dismiss button, the iron router will redirect to another page. The redirection code does work, but the backdrop stays visible. If I remove the routing line - the modal is dismissed and so does the backdrop.
Here is the modal's markup:
<div class="modal fade" id="confirm-modal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title" id="modal-title">Are you sure?</h4>
</div>
<div class="modal-body">
This cannot be undone.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal" id="confirm-yes-button">Yes</button>
<button type="button" class="btn btn-default" data-dismiss="modal">No</button>
</div>
</div>
</div>
</div>
Here is the button that toggles the modal dialog:
<button type="button" id="delete-recipe-btn" data-target="#confirm-modal" data-toggle="modal" class="btn btn-primary btn-danger pull-right">Delete</button>
Here is the click event on the 'yes' button of the confirm modal dialog:
'click #confirm-yes-button': function() {
Recipes.remove(this._id);
$('#confirm-modal').modal('hide');
Router.go('/');
}
Why would the routing leave the backdrop visible?
There are multiple solutions to this, depending on exactly how you desire the behavior. If you want the modal to hide first, then change the page, you can use a callback on the modal's behavior.
'click #confirm-yes-button': function() {
Recipes.remove(this._id);
$('#confirm-modal')
.on('hidden.bs.modal', function() {
Router.go('/');
})
.modal('hide');
}
As to your question of why the backdrop is visible - its complicated. The backdrop is only hidden once the "hide" animation completes, and changing the page interrupts/stops this behavior.
One of the solution would be to use jQuery methods to remove backdrop
once the user has been redirected.
Accounts.onLogin(function(){
Router.go('/');
$('.modal-backdrop').remove();
});
However to use this method you need have access to Accounts.login method which can be acquired by adding
gwendall:auth-client-callbacks
package to your meteor project

Categories

Resources