72

I just started a new project with the new Twitter Bootstrap release : bootstrap 3. I can't make the Modal work in the remote mode. I just want that when I click on a link it shows the modal with the content of the remote url. It works but the modal layout is completely destroyed.

Here is a link to a jsfiddle : http://jsfiddle.net/NUCgp/5/

The code :

<a data-toggle="modal" href="http://fiddle.jshell.net/Sherbrow/bHmRB/0/show/" data-target="#myModal">Click me !</a> <!-- Modal --> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" 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">&times;</button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"><div class="te"></div></div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-primary">Save changes</button> </div> </div> <!-- /.modal-content --> </div> <!-- /.modal-dialog --> </div> <!-- /.modal --> 

Can anyone make this simple example work ?

9 Answers 9

112

Regarding the remote option for modals, from the docs:

If a remote URL is provided, content will be loaded via jQuery's load method and injected into the root of the modal element.

That means your remote file should provide the complete modal structure, not just what you want to display on the body.

Bootstrap 3.1 Update:

In v3.1 the above behavior was changed and now the remote content is loaded into .modal-content

See this Demo fiddle

Boostrap 3.3 Update:

This option is deprecated since v3.3.0 and has been removed in v4. We recommend instead using client-side templating or a data binding framework, or calling jQuery.load yourself.

Sign up to request clarification or add additional context in comments.

13 Comments

You don't need to put the contents of the modal on your original page, just the source itself. See here: jsfiddle.net/NUCgp/59
Why the heck do I have to replicate all the same html 10 times for 10 dialogs ONLY because they put the html loaded into the modal-content and not body? Are they stupid?!
How can we change the modal size depending on the remote content?
UPDATE: "This option is deprecated since v3.3.0 and will be removed in v4. We recommend instead using client-side templating or a data binding framework, or calling jQuery.load yourself."
I don't understand why it has been deprecated... This is extensively useful and despite depreciation, I feel like using it, improving it, making it work (and I actually do)! It would be great to have some deeper explanations on this, in order to decide whether making a plugin would be a good idea or not...
|
29

For Bootstrap 3

The workflow I had to deal with was loading content with a url context that could change. So by default setup your modal with javascript or the href for the default context you want to show :

$('#myModal').modal({ show: false, remote: 'some/context' }); 

Destroying the modal wouldn't work for me because I wasn't loading from the same remote, thus I had to :

$(".some-action-class").on('click', function () { $('#myModal').removeData('bs.modal'); $('#myModal').modal({remote: 'some/new/context?p=' + $(this).attr('buttonAttr') }); $('#myModal').modal('show'); }); 

This of course was easily refactored into a js library and gives you a lot of flexibility with loading modals

I hope this saves someone 15 minutes of tinkering.

2 Comments

Not 100% sure why - but I had to cleanup my DOM after the data cleanup. Added this line: $('#mymodal .modal-content').html("");
$('#myModal').on('hide.bs.modal', function () { $('#myModal').removeData('bs.modal'); $('#myModal .modal-content').html(''); }); Works for me.
18

If you don't want to send the full modal structure you can replicate the old behaviour doing something like this:

// this is just an example, remember to adapt the selectors to your code! $('.modal-link').click(function(e) { var modal = $('#modal'), modalBody = $('#modal .modal-body'); modal .on('show.bs.modal', function () { modalBody.load(e.currentTarget.href) }) .modal(); e.preventDefault(); }); 

1 Comment

why can't press 'escape' or click on the backdrop to close the dialog? keyboard option is set to true by default.
13

Here's my solution (leveraging a few above) that makes use of BS3's own structure to re-instate the old remote loading behaviour. It should be seamless.

I'm going to keep the code variable heavy and descriptive to keep things understandable. I'm also assuming the presence of JQuery. Javascript heavy lifter types will handily streamline the code.

For reference here's a link that invokes a BS3 modal:

<li><a data-toggle="modal" href="terms.html" data-target="#terms">Terms of Use</a></li> 

In youre Javascript you're going to need the following.

// Make sure the DOM elements are loaded and accounted for $(document).ready(function() { // Match to Bootstraps data-toggle for the modal // and attach an onclick event handler $('a[data-toggle="modal"]').on('click', function(e) { // From the clicked element, get the data-target arrtibute // which BS3 uses to determine the target modal var target_modal = $(e.currentTarget).data('target'); // also get the remote content's URL var remote_content = e.currentTarget.href; // Find the target modal in the DOM var modal = $(target_modal); // Find the modal's <div class="modal-body"> so we can populate it var modalBody = $(target_modal + ' .modal-body'); // Capture BS3's show.bs.modal which is fires // immediately when, you guessed it, the show instance method // for the modal is called modal.on('show.bs.modal', function () { // use your remote content URL to load the modal body modalBody.load(remote_content); }).modal(); // and show the modal // Now return a false (negating the link action) to prevent Bootstrap's JS 3.1.1 // from throwing a 'preventDefault' error due to us overriding the anchor usage. return false; }); }); 

We're just about there. One thing you may want to do is style the modal body with a max-height, so that long content will scroll.

In your CSS, you'll need the following:

.modal-body{ max-height: 300px; overflow-y: scroll; } 

Just for refference I'll include the modal's HTML, which is a knock-off of every Bootsrap Modal Example you've ever seen:

<div id="terms" class="modal fade"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button> <h3 id="termsLabel" class="modal-title">TERMS AND CONDITIONS</h3> </div> <div class="modal-body"> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal --> 

5 Comments

This can prevent non-remote modals from loading. I added this inside the click handler to fix it. var href = e.currentTarget.getAttribute('href'); if (!href || href.indexOf('#') === 0) { return; }
I noticed that the show.bs.modal events were stacking so I added modal.off('show.bs.modal'); before modal.on.
Do know how to target that <a> tag link with a a jQuery, so it would use the specified URL?
I have multiple urls in my page using one modal. Your code has solved one of my problems but when I click on the first link, any other link I open will take me to the first modal url i clicked. Can you help me sort this out?
I added ``` modal.off();``` after the declaration of the var modal because with lots of modals, it was loading all the previous data
9

I did this:

$('#myModal').on 'shown.bs.modal', (e) -> $(e.target).find('.modal-body').load('http://yourserver.com/content') 

2 Comments

i think this is the best solution among all here.
Depends. If the usage is heavy in your application, this will make you write more and more JS. But for few scenarios, this is perfect
8

As much as I dislike modifying Bootstrap code (makes upgrading more difficult), you can simply add ".find('.modal-body') to the load statement in modal.js as follows:

// original code // if (this.options.remote) this.$element.load(this.options.remote) // modified code if (this.options.remote) this.$element.find('.modal-body').load(this.options.remote) 

Comments

6

another great and easy way is to have a blind modal in your layout and call it if neccessary.

JS

 var remote_modal = function(url) { // reset modal body with a spinner or empty content spinner = "<div class='text-center'><i class='fa fa-spinner fa-spin fa-5x fa-fw'></i></div>" $("#remote-modal .modal-body").html(spinner) $("#remote-modal .modal-body").load(url); $("#remote-modal").modal("show"); } 

and your HTML

 <div class='modal fade' id='remote-modal'> <div class='modal-dialog modal-lg'> <div class='modal-content'> <div class='modal-body'></div> <div class='modal-footer'> <button class='btn btn-default'>Close</button> </div> </div> </div> </div> </body> 

now you can simply call remote_modal('/my/url.html') and the content gets displayed inside of the modal

Comments

5

Here is the method I use. It does not require any hidden DOM elements on the page, and only requires an anchor tag with the href of the modal partial, and a class of 'modalTrigger'. When the modal is closed (hidden) it is removed from the DOM.

 (function(){ // Create jQuery body object var $body = $('body'), // Use a tags with 'class="modalTrigger"' as the triggers $modalTriggers = $('a.modalTrigger'), // Trigger event handler openModal = function(evt) { var $trigger = $(this), // Trigger jQuery object modalPath = $trigger.attr('href'), // Modal path is href of trigger $newModal, // Declare modal variable removeModal = function(evt) { // Remove modal handler $newModal.off('hidden.bs.modal'); // Turn off 'hide' event $newModal.remove(); // Remove modal from DOM }, showModal = function(data) { // Ajax complete event handler $body.append(data); // Add to DOM $newModal = $('.modal').last(); // Modal jQuery object $newModal.modal('show'); // Showtime! $newModal.on('hidden.bs.modal',removeModal); // Remove modal from DOM on hide }; $.get(modalPath,showModal); // Ajax request evt.preventDefault(); // Prevent default a tag behavior }; $modalTriggers.on('click',openModal); // Add event handlers }()); 

To use, just create an a tag with the href of the modal partial:

<a href="path/to/modal-partial.html" class="modalTrigger">Open Modal</a> 

2 Comments

This is Excellent Brandon Fitzpatrick. I am calling ASP.Net MVC partial view, it is getting loaded and able to show that popup. I have an issue, my jquery code is not binding to my button, textbox. Can you please tell me how to assign button click event to the button, I have done like below in my partialview.cshtml <script> $(document).ready(function () { alert('doc ready'); $('#btnSaveComment').click(function () { alert('something');}); )}; </script>
It's hard to say without seeing more code, but here are some suggestions. I'm assuming both your button and script tag is inside the modal content. 1. Make sure that the #btnSaveComment element been rendered before the click event is registered. If $('#btnSaveComment').length===0, the element has not been added to the DOM. 2. If the mime type of the requested document isn't text/html, jquery will not evaluate the loaded scripts. If that's the case, specify that it's html using the lower-level $.ajax() function instead of $.get(). (stackoverflow.com/a/2203816/856389).
0

I do it this way:

<!-- global template loaded in all pages // --> <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="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> 

Here is my a href:

<a href="#NewsModal" onclick="remote=\'modal_newsfeed.php?USER='.trim($USER).'&FUNCTION='.trim(urlencode($FUNCTIONCODE)).'&PATH_INSTANCE='.$PATH_INSTANCE.'&ALL=ALL\' remote_target=\'#NewsModal .modal-body\'" role="button" data-toggle="modal">See All Notifications <i class="m-icon-swapright m-icon-dark"></i></a> 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.