Lazy loaded Bootstrap modals

Lazy loading Bootstrap modal windows.

Bootstrap modals are components containing HTML that is made visible in a modal like dialog when the user takes appropriate action.

Sircl offers different ways and different options to lazy load content for Bootstrap modals, thereby reducing the load and duration of the initial page request.

Using onshowmodal-load

The first way is the use of the onshowmodal-load attribute placed on the .modal element or any subelement of it, which will execute the URL and replace the content of the element holding the onshowmodal-load attribute with the returned content:

<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modal1">
  Modal 1
</button>

<div class="modal fade" id="modal1" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Modal 1</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body" onshowmodal-load="/Samples/LoremIpsum">
        Loading...
      </div>
    </div>
  </div>
</div>

The modal opens as soon as the button is clicked as this is done by Bootstrap. This gives the best reactivity: the user sees immediate reaction on his click action as the modal opens immediately. Then, when the URL request returned, the content of the modal is updated.

To make this more visible in the demo below, an artificial delay of 1 second was added to each content call, and the content contain a timestamp.

The URL is reexecuted each time the modal is opened. So when the modal is opened a second time, the user first sees the previous content, which is then updated when the URL request is done.

In some cases this may appear confusing or annoying. But there are 2 ways to solve this. The first is to add the onclose-restore class on the .modal element. This will cause the content of the modal to be reinitialized to its initial state when closed. As a result, when reopening the modal, the user will first see the initial "Loading..." message, before the content is updated:

<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modal2">
  Modal 2
</button>

<div class="modal fade onclose-restore" id="modal2" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Modal 2</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body" onshowmodal-load="/Samples/LoremIpsum">
        Loading...
      </div>
    </div>
  </div>
</div>

A different way to solve the issue of content to be updated is to simply not update the content after it has been loaded a first time. This can be instructed by adding the noreload class on the element holding the onshowmodal-load attribute. The first time the modal is opened, content is loaded. But when the modal is opend a second time, no update of the content is performed anymore:

<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modal3">
  Modal 3
</button>

<div class="modal fade" id="modal3" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Modal 3</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body noreload" onshowmodal-load="/Samples/LoremIpsum">
        Loading...
      </div>
    </div>
  </div>
</div>

Using a hyperlink with target

A whole different approach to open a Bootstrap modal with lazy loaded content is to create a regular hyperlink linking to the content of the modal and give it a target attribute with a (relative) CSS selector pointing anywhere inside a .modal element.

In the next code sample we created two hyperlinks, to different content, to be loaded inside the .modal-body element of the same modal:

<a href="/Samples/LoremIpsum" target="#modal4 .modal-body"><i class="spinner"></i> Modal 4a</a>
<a href="/Samples/BrownFox" target="#modal4 .modal-body"><i class="spinner"></i> Modal 4b</a>

<div class="modal fade" id="modal4" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Modal 4</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        Loading...
      </div>
    </div>
  </div>
</div>

When clicking on the "Modal 4" links in the demo below, you will notice that the modal is less reactive: the modal dialog only opens once the content is loaded and the spinner is finished spinning. The reason for this is that the server could still override the target by setting an X-Sircl-Target response header, and so it is only certain the modal is the target once the content is loaded.

You can however force the modal to open right away by adding the beforeload-showmodal class on the .modal element as done in the 5th sample:

<a href="/Samples/LoremIpsum" target="#modal5 .modal-body"><i class="spinner"></i> Modal 5a</a>
<a href="/Samples/BrownFox" target="#modal5 .modal-body"><i class="spinner"></i> Modal 5b</a>

<div class="modal fade beforeload-showmodal" id="modal5" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Modal 5</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        Loading...
      </div>
    </div>
  </div>
</div>
</p>

This introduces however again the issue that the content of the modal is updated when the modal is already open, which, when the modal is opened for a second time, first exposes the previously loaded content.

The solution is to combine the beforeload-showmodal with the onclose-restore class as done in this last sample:

<a href="/Samples/LoremIpsum" target="#modal6 .modal-body"><i class="spinner"></i> Modal 6a</a>
<a href="/Samples/BrownFox" target="#modal6 .modal-body"><i class="spinner"></i> Modal 6b</a>

<div class="modal fade beforeload-showmodal onclose-restore" id="modal6" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Modal 6</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        Loading...
      </div>
    </div>
  </div>
</div>

 

Working demo
Loading demo...

 

Requirements

This example requires following Sircl library files to be loaded:

or:

Or their non-minified counterparts.

See the Get Started section about how to set up your project to use the Sircl library.