Developer forum

Forum » Swift » Swift 2 - Forms for editors - HTMX

Swift 2 - Forms for editors - HTMX

Aki Ruuskanen
Aki Ruuskanen
Reply

Hi,

Is it possible to implement a form for Forms For Editors with htmx? I'm trying to create a form that displays a Bootstrap Modal after submission.

I think Nicolai showed something like that i Göteborg couple of weeks ago but I don't remeber if it was for "Forms For Editors".

Regards / Aki  


Replies

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply
This post has been marked as an answer

Hi Aki

Of course you can. If you can do it in HTML you can do it in htmx. More or less.

You don’t need to rewrite the whole form – you mainly need to:

  1. Wrap the form in an element with and id (e.g. <div id="myCustomForm">)

  2. Let htmx handle the POST instead of the browser.

  3. Tell htmx to grab only #myCustomForm from the response.

  4. Inject that HTML into a Bootstrap modal body and show the modal.

1. Include htmx

First, make sure you load htmx somewhere on the page:

<script src="https://unpkg.com/htmx.org@2.0.3"></script>

(Any recent version is fine.)

2. Add a modal that will show the form result

Somewhere on the page (typically near the bottom), add a standard Bootstrap 5 modal.
Notice the id="myCustomFormModalBody" – that’s where we’ll inject the returned #myCustomForm HTML.

 
<div class="modal fade" id="myCustomFormModal" tabindex="-1" aria-hidden="true"> <div class="modal-dialog modal-lg"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Form result</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body" id="myCustomFormModalBody"> <!-- htmx will swap the returned #myCustomForm into here --> </div> </div> </div> </div>

3. Convert the form to use htmx

You already have:


 
 
<div class="p-4 p-md-5 w-100" id="myCustomForm"> <form method="post" action="/Admin/Public/404.aspx" enctype="multipart/form-data" class="" id="dw-form-1" onsubmit="s=function(e){...};return s(this);"> ... </form> </div>

We’ll change the form tag to use hx-post etc., and drop the old onsubmit logic (because htmx will handle the request). The hidden fields can stay – they’ll be posted as usual.

Here’s a cleaned-up version of the opening tags:


 
 
<div class="p-4 p-md-5 w-100" id="myCustomForm"> <form id="dw-form-1" class="" method="post" enctype="multipart/form-data" hx-post="/Default.aspx?ID=106&PID=2761" hx-target="#myCustomFormModalBody" hx-select="#myCustomForm" hx-swap="innerHTML" > <!-- your hidden fields + inputs stay as-is -->

What those htmx attributes do:

  • hx-post="/Default.aspx?ID=106&PID=2761"
    Tells htmx to send a POST to that URL when the form is submitted (instead of the browser doing a full page POST).

  • hx-target="#myCustomFormModalBody"
    Says: “When the response comes back, inject the selected HTML into this element.”

  • hx-select="#myCustomForm"
    Says: “From the HTML in the response, only take the element with id myCustomForm.”

  • hx-swap="innerHTML"
    Replace the inside of #myCustomFormModalBody with that selected HTML.

Result: your server still returns the full page like before, but htmx pulls out only the #myCustomForm div from it and stuffs it into the modal body.

You can keep the rest of the form body exactly as-is (all the hidden fields, inputs, button, etc.) – no need to change those.

If you don’t care about the Buttons.LockButton(event) click handler, you can also remove this:


 
 
<button class="btn btn-primary" type="submit" onclick="Buttons.LockButton(event)" id="Send">Send</button>

or just leave it; it won’t break htmx.

4. Show the modal after htmx swaps the content

Last step is to show the Bootstrap modal once htmx has injected the response content.
We hook into the htmx:afterSwap event and look for swaps that hit our modal body.


 
 
<script> document.body.addEventListener('htmx:afterSwap', function (evt) { // Only react when our modal body was the target if (evt.target.id === 'myCustomFormModalBody') { const modalEl = document.getElementById('myCustomFormModal'); const modal = new bootstrap.Modal(modalEl); modal.show(); } }); </script>

Now the flow looks like this:

  1. User fills out the form and hits Send.

  2. htmx sends a POST to /Default.aspx?ID=106&PID=2761 (with all the same fields).

  3. Server returns HTML (a full page or partial – doesn’t matter).

  4. htmx:

    • grabs #myCustomForm from the response (hx-select)

    • injects it into #myCustomFormModalBody (hx-target, hx-swap)

  5. htmx:afterSwap fires, we detect the target, and show the Bootstrap modal.

You’ve now turned a “boring full-page POST” into a “htmx-driven inline POST that shows the result inside a modal” without really touching the server side.

 

Votes for this answer: 1
 
Aki Ruuskanen
Aki Ruuskanen
Reply

Excellent, thanks for the pointers. 

/Aki 

 
Aki Ruuskanen
Aki Ruuskanen
Reply

Hi,

To get it to work you need to keep the "onsumbmit" otherwise DW will treat it as spam. I also dropped the "hx-select". The confimration page is a regular page with a clean pagetemplate and a paragrapgtemplate that renders the model and is then swapped to the "subscriptionConfirmationModalBody".  So i did it like this:

<form id="@GetString("Form.HtmlId")" class="" method="post" enctype="multipart/form-data" onsubmit="@GetString("Form.OnSubmit")" hx-encoding="multipart/form-data" hx-post="/Default.aspx?ID=8621&PID=23093" hx-target="#subscriptionConfirmationModalBody" hx-swap="innerHTML">
            @GetString("Form.SystemFields")

</form>

<div id="subscriptionConfirmationModalBody"></div>

Regards / Aki 

 
Aki Ruuskanen
Aki Ruuskanen
Reply

And a regex to get the hx-post for a general form template.

    var onSubmit = GetString("Form.OnSubmit");

    var match = Regex.Match(
        onSubmit,
        @"setAttribute\('action',\s*'([^']+)'",
        RegexOptions.IgnoreCase
    );

    postUrl = match.Groups[1].Value;

    <form id="@GetString("Form.HtmlId")" class="" method="post" enctype="multipart/form-data" onsubmit="@onSubmit" hx-encoding="multipart/form-data" hx-post="@postUrl" hx-target="#subscriptionConfirmationModalBody" hx-swap="innerHTML">

 

You must be logged in to post in the forum