Bootstrap modal on form submit not displaying at correct point

Viewed 520

Requirement

I want to display a fixed message to the user whilst a file is being uploaded and attached to an email to discourage clicking back or refreshing the page or repeatedly clicking the submit button.

Background

I'm using bootstrap v3.3.7 and JQuery v3.3.1.

I thought a good way to tackle this requirement was to make use of the Bootstrap Modal plugin, especially when I realised you could fix the modal on screen using:

$("#modal-foo").modal({backdrop: 'static',keyboard: false});

I have the following modal:

@model Web.ViewModels.Site.Foo.FooViewModel
<div class="modal fade" id="modal-foo" tabindex="-1" role="dialog" aria-labelledby="modal" aria-hidden="true" style="display: none;">
    <div class="modal-dialog">
        <div class="modal-content">
            <!-- Modal Header -->
            <div class="modal-header">
                <h4 class="modal-title" id="modal-label">
                    <i class="fa fa-spin fa-spinner"></i> Uploading your file and submitting it for review
                </h4>
            </div>

            <!-- Modal Body -->
            <div class="modal-body">
                <p>We're currently uploading and submitting your file for review.</p>
                <p>This may take a few moments. Please do not hit the back button or try to refresh this page whilst this is happening.</p>
            </div>
        </div>
    </div>
</div>

I have the following form:

<form id="fooform" asp-action="fooaction" asp-controller="foocontroller" asp-route-fooid="@Model.FooId" method="post" enctype="multipart/form-data" class="form-horizontal">

I have the following button:

<input type="submit" value="Submit" class="btn btn-primary" />

And the following jquery:

//when dom loaded hooks
$.when($.ready).then(function () {
  $('#fooform').on('submit', function () {
     if ($(this).valid()) {
        //we've passed the unobtrusive validation so now present the message to the user
        $("#modal-foo").modal({
          backdrop: 'static',
          keyboard: false
        });
     }
   });
})

Issue

What I was hoping would happen is that the modal would appear once the unobtrusive validation has passed, and is displayed until the user is redirected to a thank you page.

What I'm finding happen is that the modal isn't appearing until later in the process.

For example, if I put some alerts in to see what's happening, using the code below, the modal doesn't appear until after 'here3'. It's as though the .modal is firing an instruction to browser to display the modal but it doesn't action it immediately.

//when dom loaded hooks
$.when($.ready).then(function () {
  $('#fooform').on('submit', function () {
     alert('here1');
     if ($(this).valid()) {
        //we've passed the unobtrusive validation so now present the message to the user
        alert('here2');
        $("#modal-foo").modal({
          backdrop: 'static',
          keyboard: false
        });
        alert('here3');
     }
   });
})

Alternative attempt to achieve requirement

I've tried using an anchor instead of a submit button but again, the modal doesn't appear until after 'here3':

<a class="btn btn-primary" onclick="showModal();">Submit</a>

Javascript function:

function showModal() {
  if ($('#fooform').valid()) {
    //we've passed the unobtrusive validation so now present the message to the user
    alert('here1');
    $("#modal-foo").modal({
      backdrop: 'static',
      keyboard: false
    });
    alert('here2');
    //can I somehow wrap the submit in a promise or delegate so that after the modal appears it does the submit?
    $('#fooform').submit();
    alert('here3');
  }
}

Question

How can I achieve my requirement? As per my comment in the Javascript function above, can I wrap the form submit in a promise or delegate or can I set something on the DOM to fire after the modal has displayed or is there an alternative to the Modal that I should look at?

2 Answers

The problem is while you click the submit button your page reloading that's why you cannot see your modal

$.when($.ready).then(function () {

  $('#fooform').on('submit', function (e) {
       e.preventDefault();//added here
  //   if ($(this).valid()) {
        //we've passed the unobtrusive validation so now present the message to the user
        $("#modal-foo").modal({
          backdrop: 'static',
          keyboard: false
        });
   //  }
   });
})

see your above code i used 'e.preventDefault()' to block your submission on click Now you can see your model But your 'valid()' command will not work here, because form is prevented from submitting, that's why i commented out that....

So change your code according to this.....

One method is using AJAX you can send data without page reload... otherwise give a button to open model and put submit button on the model...

There is one more chance that model will not work...

while inserting scripts it must be in order that jquery must insert before other plugins, insert,

<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>

above code first, then try,

i am including the working full code below

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Bootstrap Example</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.validation/1.16.0/jquery.validate.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.validation/1.16.0/additional-methods.min.js"></script>


</head>

<body>
@model Web.ViewModels.Site.Foo.FooViewModel
<div class="modal fade" id="modal-foo" tabindex="-1" role="dialog" aria-labelledby="modal" aria-hidden="true" style="display: none;">
    <div class="modal-dialog">
        <div class="modal-content">
            <!-- Modal Header -->
            <div class="modal-header">
                <h4 class="modal-title" id="modal-label">
                    <i class="fa fa-spin fa-spinner"></i> Uploading your file and submitting it for review
                </h4>
            </div>

            <!-- Modal Body -->
            <div class="modal-body">
                <p>We're currently uploading and submitting your file for review.</p>
                <p>This may take a few moments. Please do not hit the back button or try to refresh this page whilst this is happening.</p>
            </div>
        </div>
    </div>
</div>

<form id="fooform" asp-action="fooaction" asp-controller="foocontroller" asp-route-fooid="@Model.FooId" method="post" enctype="multipart/form-data" class="form-horizontal">

</form>
<a class="btn btn-primary" onclick="showModal();">Submit</a>


</body>
<script>
function showModal() {
  if ($('#fooform').valid()) {
    //we've passed the unobtrusive validation so now present the message to the user
    alert('here1');
    $("#modal-foo").modal({
      backdrop: 'static',
      keyboard: false
    });
    alert('here2');
    //can I somehow wrap the submit in a promise or delegate so that after the modal appears it does the submit?
  //  $('#fooform').submit();
    alert('here3');
  }
}
</script>
</html>

In the end I got this working by using the following. Hopefully, someone else may find this useful:

Same button and form

<input type="submit" value="Submit" class="btn btn-primary" />

<form id="fooform" asp-action="fooaction" asp-controller="foocontroller" asp-route-fooid="@Model.FooId" method="post" enctype="multipart/form-data" class="form-horizontal">

Modal

Note the additional data-backdrop and data-keyboard attributes on the 1st div

@model Web.ViewModels.Site.Foo.FooViewModel
<div data-backdrop="static" data-keyboard="false" class="modal fade" id="modal-foo" tabindex="-1" role="dialog" aria-labelledby="modal" aria-hidden="true" style="display: none;">
    <div class="modal-dialog">
        <div class="modal-content">
            <!-- Modal Header -->
            <div class="modal-header">
                <h4 class="modal-title" id="modal-label">
                    <i class="fa fa-spin fa-spinner"></i> Uploading your file and submitting it for review
                </h4>
            </div>

            <!-- Modal Body -->
            <div class="modal-body">
                <p>We're currently uploading and submitting your file for review.</p>
                <p>This may take a few moments. Please do not hit the back button or try to refresh this page whilst this is happening.</p>
            </div>
        </div>
    </div>
</div>

jQuery

I ended up taking the key elements from the modal plugin in the Bootstrap js file and the modal appeared at the point I expected it to whilst still giving me the modal display effects that I was looking for.

function showModal() {
    var $body = $("body");
    $body.addClass("modal-open");
    $(document.createElement('div'))
        .addClass('modal-backdrop fade in')
        .appendTo($body)
    var $modal = $("#modal-foo");
    $modal.show();
    $modal.scrollTop(0);
    $modal[0].offsetWidth;
    $modal.addClass('in');
}

//when dom loaded hooks
$.when($.ready).then(function () {
    $('#fooform').on('submit', function () {
        if ($(this).valid()) {
            showModal();
        }
    });
})

Related