How to Add HTMX, ASP.NET Core, and Bootstrap Modals - Windows ASP.NET Core Hosting 2024 | Review and ComparisonWindows ASP.NET Core Hosting 2024 | Review and Comparison

You’ve probably worked with Bootstrap, a toolkit designed to give developers access to CSS layout components and rules, if you’ve done any front-end development in the last ten years. Furthermore, no frontend toolkit is complete without the JavaScript that goes along with it to enable interactive elements. Nevertheless, you can use the toolkit’s “Bring Your Own JavaScript” approach to incorporate Bootstrap visual elements into any frontend library of your choice. The JavaScript components are completely optional.

This article will demonstrate how to use HTMX with Bootstrap modals. For those who do not know, HTMX is a hypermedia-focused library that allows you to incorporate server-rendered responses and interactivity into your client applications.

Please take note that I’m using the ASP.NET Core tag helpers and the HTMX.NET library.

Bootstrap Modals

The building blocks of a bootstrap modal are HTML, CSS, and Javascript. To achieve the desired behavior that the Bootstrap team intended, you usually have all three working together. The JavaScript library that comes with the library contains these interactive parts of bootstrap modals, but there’s a catch.

Modals must be added programmatically through JavaScript calls or must already be present on the page as HTML. Although static modals are fantastic, most people probably don’t want them. The majority of developers prefer situational or dynamic modals that are driven by user interaction. So, how can we obtain the dynamic modals that our server generates? Okay, let’s just say that HTMX is spoiled!

HTMX and All That Jazz

Let’s take a look at the aspects of the process that need to be taken into account before we examine the code.

  1. The button that a user clicks to send a request to the server is the interactive element.
  2. The location where the modal is received and rendered.
  3. The point of contact that receives data and provides a response tailored to the user.

If you’re a backend developer, following these simple steps will enable you to achieve the desired behavior. Let’s practice putting each into practice.

The Modal Trigger

Modals require a target and a trigger. We want to ask the server to create and return our modal HTML when our user hits the trigger.

First, let’s talk about our button and the necessary HTMX properties. I use Razor Pages for ASP.NET Core, which is compatible with all backend technologies. Additionally, keep in mind that the HTMX.NET library and the tag helpers it offers contain some of these attributes.

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <button hx-get hx-page="Index" 
            hx-page-handler="Modal"
            hx-target="#modal-container">
        Show Modal
    </button>
</div>

<div id="modal-container"></div>

The handler for Razor Pages is a basic endpoint that yields an IActionResult.

public IActionResult OnGetModal()
{
    return Partial("Modal");
}

Now that we have that section, let’s examine the actual modal HTML.

The Server-rendered Modal

The modal is essentially a standard Bootstrap modal with some extra JavaScript. This is the secret. Any <script> elements will be executed instantly by HTMX, freeing you up to complete the HTML setup. You will be able to use JavaScript and HTMX as intended by the Bootstrap development team thanks to this behavior.

@model IndexModel

<div id="my-modal" class="modal fade" tabindex="-1">
    <div class="modal-dialog modal-dialog-centered">
        <div id="modal-body" class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">From The Server</h5>
                <button type="button"
                        class="btn-close"
                        data-bs-dismiss="modal"
                        aria-label="Close">
                </button>
            </div>
            <div class="modal-body">
                <form id="myForm" hx-post
                      hx-page="index"
                      hx-page-handler="Modal"
                      hx-target="closest .modal-body">
                    <div class="mb-3">
                        <label asp-for="Message" class="form-label"></label>
                        <input asp-for="Message" class="form-control" placeholder="Your message...">
                    </div>
                    @Html.AntiForgeryToken()
                </form>
            </div>
            <div class="modal-footer">
                <button form="myForm"
                        type="submit"
                        class="btn btn-primary">
                    Save changes
                </button>
            </div>
        </div>
    </div>
</div>
<script>
    function showModal() {
        const modal = new bootstrap.Modal('#my-modal');
        modal.show();
    }
    // scopes the modal so we can keep creating them
    showModal();
</script>

You can see sprinklings of HTMX attributes if you look through the HTML. These attributes will be processed by HTMX when the HTML clientside DOM is added. I’m instructing HTMX where to send the subsequent response by using its hx-target. To learn how to use hx attributes for your solutions, please read the HTMX documentation.

You can end the process here if your modal is message-only; otherwise, the following section will walk you through handling the use case where modals are required for additional interactions.

Alright, one more thing: an interactive modal powered by HTMX will be present.

The Form Submission

The input elements from the HTML form must be received by our Razor Pages handler. That is a single Message text box in the sample above. We have a string property and an endpoint in our Razor Page implementation.

[BindProperty]
public string? Message { get; set; }

public IActionResult OnPostModal()
{
    return Partial("Success", this);
}

We have a corresponding view of Success along with the C# code.

@model IndexModel

<strong>You Said: "@Model.Message"</strong>

Wow, that’s it.

Conclusion

A well-known frontend library called Bootstrap was created to let you include any client-side libraries in the mix. Personally, I like to use HTMX to add some spice to otherwise boring experiences. It only takes a few simple problem-solving techniques to combine the two, as the sample illustrates.

Thank you for reading, and I hope this blog post was helpful.