HTMX & MODX a match made in heaven?
HTMX is one of my favourite AJAX libraries for HTML-over-the-wire, it’s ridiculously simple to install and even easier to use. You can check out the official HTMX docs if you want to learn more.
The first thing we need to do is add HTMX to our templates. If you’re anything like me you have already set up a chunk called scripts or footer that holds your script tags, if not you’ll have to add the script tag to every template you want to use HTMX on. To install HTMX add the following tag to your site:
Once installed you can quickly check it’s working by using the following code (Note: You’ll need to have PDO Tools extra installed to use the fast field tag.)
<input type="text" name="name" hx-get="[[~[[*id]]]]" hx-trigger="keyup changed delay:500ms" hx-target="#yourname" hx-select="#yourname" placeholder="Enter your name"> <div id=”yourname">[[#GET.name]]</div>
It's literally that simple to get up and running with HTMX on MODX. Now for something a little more involved. Typically we use AJAX for form submissions, providing instant validation feedback and a success message once the form has been submitted successfully. For this example, we'll use the Formit Extra to handle the validation and submission.
Setting up Formit
Make sure you have the Formit extra installed! Then add the following code to your page:
Note, in the example code below there are no hooks. In your form, you'll want to add hooks like email, ReCaptcha, spam etc. Since this is just a demo on HTMX I thought it best if the example form doesn't collect any of your data :D
[[!FormIt? &validate=`name:required, email:email:required, subject:required, text:required:stripTags` &successMessage=`<div class="alert alert-success">Thank you for getting in touch</div>` &validationErrorMessage=`<div class="alert alert-danger">Please fix the errors in your form before resubmitting</div>` ]] <form hx-post="[[~[[*id]]]]" hx-target="#exForm" hx-select="#exForm" id="exForm"> [[!+fi.validation_error_message]] [[!+fi.successMessage]] <div class="mb-3"> <label for="finame" class="form-label">Name</label> <input type="text" class="form-control [[!+fi.error.name:notempty=`is-invalid`]]" id="finame" placeholder="Full name" name="name" value="[[!+fi.name]]"> </div> <div class="mb-3"> <label for="fiemail" class="form-label">Email address</label> <input type="text" class="form-control [[!+fi.error.email:notempty=`is-invalid`]]" id="fiemail" placeholder="email@example.com" name="email" value="[[!+fi.email]]"> </div> <div class="mb-3"> <label for="fisubject" class="form-label">Subject</label> <input type="text" class="form-control [[!+fi.error.subject:notempty=`is-invalid`]]" id="fisubject" placeholder="Just want to say hi" name="email" value="[[!+fi.subject]]"> </div> <div class="mb-3"> <label for="fitext" class="form-label">Message</label> <textarea name="text" id="fitext" class="form-control [[!+fi.error.text:notempty=`is-invalid`]]">[[!+fi.message]]</textarea> </div> <button class="btn btn-primary">Submit form</button> </form>
If you check the network tab in Dev tools you'll see the AJAX request and response, the response contains the entire rendered HTML from the resource. Depending on your page load speeds and requirements this may not be the best approach since you're reloading the entire page. There are a number of different approaches to AJAX in MODX which I'll cover some other time, but another approach could be to set up a resource called AJAX that uses a blank template, the snippet you want to run i.e. the FormIt snippet and the HTML you want to return. That way, when you send a request to the resource you'll only get back what you want.