2

So in the near future my shop is going to upgrade to Bootstrap 4 but we cannot do this until we solve the issue with using remote modals. Here is an example of how we load our modals. The reason we use remote modals is because the modal-body is dynamic and may use different file based on the url. I have heard that using jQuery("#newsModal").on("load",..) is an alternative but how could I do this? I found this but I am not sure how my anchor would look and how to build the url to load the remote data.

Global PHP include file:

   <div id="NewsModal" class="modal fade" tabindex="-1" role="dialog" data-
ajaxload="true" aria-labelledby="newsLabel" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
                    <h3 class="newsLabel"></h3>
                </div>
                <div class="noscroll-modal-body">
                        <div class="loading">
                            <span class="caption">Loading...</span>
                           <img src="/images/loading.gif" alt="loading">
                    </div>
                </div>
                <div class="modal-footer caption">
                    <button class="btn btn-right default modal-close" data-dismiss="modal">Close</button>
                </div>
            </div>
        </div>
    </div>

modal_news.php file:

     <form id="newsForm">
        <div id="hth_err_msg" class="alert alert-danger display-hide col-lg-12 col-md-12 col-sm-12 col-xs-12">
                You have some errors. Please check below.
        </div>
        <div id="hth_ok_msg" class="alert alert-success display-hide col-lg-12 col-md-12 col-sm-12 col-xs-12">
           &#10004;&nbsp;Ready 
        </div>                     
            <!-- details //-->
        </form>

Here is how we trigger the modals :

   <a href="#newsModal" id="modal_sbmt" data-toggle="modal" data-target="#newsModal" 
    onclick="remote='modal_news.php?USER=yardpenalty&PKEY=54&FUNCTION=*GENERAL'; remote_target='#NewsModal .noscroll-modal-body'">
    <span class="label label-icon label-info">
       <i class="fa fa-bullhorn"></i>
    </span>
    Promotional Ordering
   </a>

I think I need to do something like this when building anchor dynamically:

a) Replace paramters with data-attrs

b) Use the event invoker to get the data-attrs using event.target.id

Community
  • 1
  • 1
yardpenalty.com
  • 1,244
  • 2
  • 17
  • 32
  • Is there an overriding reason you use `onclick`, rather than capturing the click event? – Tieson T. Nov 13 '16 at 07:51
  • TBH this is how my boss started doing them because he implemented Metronic theme. I try not to use `onclick` but I am not sure how to load content remotely the proper way. – yardpenalty.com Nov 13 '16 at 07:54
  • @natel, In regards to `onclick` we are in an era were disabling javascript is becoming no longer an option. Our site requires javascript and we are not even attempting to provide an alternative. There is only so many hours in a week. In the future ALL sites/apps will require javascript to be enabled. IMHO – yardpenalty.com Nov 13 '16 at 08:06

2 Answers2

2

Thanks to Tieson T. and this post I was able to effectively pass parameters to the remote modal using this technique except if you have multiple modals

I have also included some helpful techniques inside this example as to how you may pass parameters to the remote modal.

bootstrap_modal4.php:

    <div class="portlet-body">
    <a href="#attendee" id="add-attendee" data-atnid="add" data-fscode="S" role="button" class="btn btn-success atn show-modal" data-toggle="modal" data-target="#attendee" data-remote="/modal_attendeesave.php?USERNAME=BRIAN">Add Attendee&nbsp;<i class="fa fa-plus"></i></a>   
   </div>

<!-- BEGIN Food Show Attendee Add/Edit/Delete Modal -->
<div  id="attendee" class="modal fade" tabindex="-1" role="dialog" data-ajaxload="true" aria-labelledby="atnLabel" aria-hidden="true">
    <form id="signupForm" method="post">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <label id="atnLabel" class="h3"></label><br>
                <label id="evtLabel" class="h6"></label>
            </div>
            <div class="modal-body">
            <div class="loading"><span class="caption">Loading...</span><img src="/images/loading.gif" alt="loading"></div>
             </div>
            <div class="modal-footer">
            <span class="caption">
                <button type="button" id="add_btn" class="btn btn-success add-attendee hidden">Add Attendee&nbsp;<i class="fa fa-plus"></i></button>
                <button type="button" id="edit_btn" class="btn btn-info edit-attendee hidden">Update Attendee&nbsp;<i class="fa fa-save"></i></button>
                <button type="button" id="del_btn" class="btn btn-danger edit-attendee hidden">Delete Attendee&nbsp;<i class="fa fa-minus"></i></button>
                <button class="btn default modal-close" data-dismiss="modal" aria-hidden="true">Cancel</button>
            </span>
            </div>
        </div>
        </div>
    </form>
 </div>

    <script>
    jQuery(document).ready(function() { 
        EventHandlers();
     });
       function EventHandlers(){
            $('#attendee').on('show.bs.modal', function (e) {
                e.stopImmediatePropagation();

                if($(this).attr('id') === "attendee"){

                // Determines modal's data display based on its data-attr
                var $invoker = $(e.relatedTarget);   
                 var fscode = $invoker.attr('data-fscode');
                 console.log(fscode);
                  // Add Attendee
                  if($invoker.attr('data-atnid') === "add"){ 
                       $("#atnLabel").text("Add New Attendee");
                       $(".add-attendee").removeClass("hidden"); 
                   }
                   else{ //edit/delete  attendee
                     $("#atnLabel").text("Attendee Maintenance");
                     $(".edit-attendee").removeClass("hidden"); 
                   }

                   //insert hidden inputs
                    //add input values for post
                     var hiddenInput = '<INPUT TYPE=HIDDEN NAME=FSCODE VALUE="' + fscode + '"/>';
                     $("#signupForm").append(hiddenInput);
                }
            });

               $('#attendee').on('hidden.bs.modal', function (e) {
                  $(".edit-attendee").addClass("hidden"); 
                  $(".add-attendee").addClass("hidden"); 
                  $("#signupForm input[type='hidden']").remove();
               });

                // BOOTSTRAP 4 REMOTE MODAL ALTERNATIVE FOR BOOTSTRAP 3v-
                $('#add-attendee').on('click', function(e){
                    $($(this).data("target")+' .modal-body').load($(this).data("remote"));
                    $("#attendee").modal('show');      
                });

       }

    </script>

bootstrap_remote_modal4.php:

<form id="signupForm">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
Hello World! 
</div>
</form> 
<script>
  $(document).ready(function(){
     console.log('<?php echo $_GET["USERNAME"]?>'); //passed through url
   });
</script>

NOTE: I am having problems with event propagation during the show.bs.modal event which I have a global show.bs.modal that is propagating up to this event handler due to multiple modals so if you have multiple modals make sure to handle them correctly.

Here is a screen shot of the results which clearly show propagation is taking place but the parameter passing techniques are working.

enter image description here

Community
  • 1
  • 1
yardpenalty.com
  • 1,244
  • 2
  • 17
  • 32
0

You might find it easier to use something like Bootbox.js, which can be used to dynamically create Bootstrap modals.

Given what you've shown, it would work something like:

<a href="/path/to/your/service" class="show-modal">trigger modal</a>

with

$(function(){

    $('.show-modal').on('click', function(e){

        e.preventDefault();

        var url = $(this).attr('href');

        $.get(url)
            .done(function(response, status, jqxhr) {

                bootbox.dialog({
                    title: 'Your Title Here',
                    message: response
                });
            });

    });

});

This assumes response is an HTML fragment.

Bootbox hasn't officially been confirmed to work with Bootstrap 4, but I haven't run into any problems with it yet (modals seem to be one of the few components that don't have updated markup in BS4).

Disclaimer: I am currently a contributor to Bootbox (mainly updating the documentation and triaging issues).

If you must use only the Bootstrap modal, you're actually after load(). You would probably do something like:

$(function(){

    $('.show-modal').on('click', function(e){

        e.preventDefault();

        var url = $(this).attr('href');
        var dialog = $('#NewsModal').clone();

        dialog.load(url, function(){
            dialog.modal('show');
        });

    });

});
Tieson T.
  • 20,774
  • 6
  • 77
  • 92
  • Thanks. I'll give it a try. Gives me a good reason to research the clone() method too. Never had to use it but have been curious as to how it would be beneficial. I'll check out bootbox.js as well. – yardpenalty.com Nov 13 '16 at 08:55
  • The href for the bootstrap modal is the id (not the remote url) so I would have to build the url some other way. I have to pass in parameters to the `onclick` event listener which in turn is passed as part of the url. I suppose I could create data-attributes and find the data-attributes via the invoker inside the event? – yardpenalty.com Nov 13 '16 at 09:12
  • If I understand correctly, yes. jQuery has a .data() function you can call on the selected element. – Tieson T. Nov 13 '16 at 10:15
  • Right. Use e.target.id to find the selector and from there access the data attributes. I will work out the solution when I get into the office tomorrow and post results. Thanks again. – yardpenalty.com Nov 13 '16 at 16:44