Jump to content

FormBuilderHtmx - A zero configuration Pro FormBuilder companion module to enable AJAX form submissions


Recommended Posts

Hey all!

This is a module to enhance forms built using the Pro FormBuilder module that converts the submission/response loop to AJAX via HTMX.

Some noteworthy features:

  • Zero configuration, install and render AJAX powered FormBuilder forms immediately
  • Unintrusive, can be used alongside FormBuilder's native rendering methods and does not modify core module behavior
  • Perfect for forms embedded in popups and modals, does not use iframes
  • Does not conflict with styling and other JavaScript already in-place, only handles the form submission/response loop
  • Automatically disables the `Submit` button on submission to prevent duplicate requests
  • Provides the ability to add a custom 'spinner' shown when a form is being processed
  • Uses HTMX, a stable, powerful, and tiny (11kb gzipped) library

Note- this module is BYOH (Bring Your Own HTMX) as the library is not provided with FormBuilderHtmx. Read the HTMX documentation for more information and installation instructions. It's a pretty nifty library with a lot of great features that you may want to use on other parts of your site or app.

You may also have to disable CSRF protection for a form rendered using this module.

Usage is cake.

<!--
  Replace the native $forms->render() method with $htmxForms->render()
-->
<?= $htmxForms->render('your_form_name') ?>

Presto.

You can optionally include a 'spinner' or activity animation that will be showed to the user while your form request is in flight. Highly recommended.

<style>
  /*
    Include this in your CSS stylesheets, note the 'activity-indicator` class name on the 'spinner'
    element below. That class name is your choice, however `.htmx-request` must be unchanged. Also include any
    CSS your 'spinner' may need
  */

  .activity-indicator {
    display: none;
  }

  .htmx-request .activity-indicator {
    display: inline;
  }

  .htmx-request.activity-indicator {
    display: inline;
  }
</style>

<!--
  Optional second argument matches that of the $forms->render() method for pre-populated values
  Optional third argument is a CSS selector matching your 'spinner' element
-->
<?= $htmxForms->render('your_form_name', [], '#indicator-for-the-form') ?>

<!-- The 'spinner' element -->
<div id="indicator-for-the-form" class="activity-indicator">
  <span class="spinner"></span>
</div>

Presto (again)

This is an alpha release as I wrote it while working on a current project, that is to say the testing has worked for the forms I have in place. Please test and check that everything works with your FormBuilder forms. Pull requests on Github are welcome. When there has been more testing and usage I'll add it to the modules directory if it proves useful.

Download from the FormBuilderHtmx Github repository .

Cheers!

  • Like 18
  • Thanks 1
Link to comment
Share on other sites

  • FireWire changed the title to FormBuilderHtmx - A zero configuration Pro FormBuilder companion module to enable AJAX form submissions

I was just playing around with your module and wanted to export my playground profile so I can use it in another PW instance and then this happened:

Spoiler

Dangit… Fatal Error: Uncaught TypeError: FormBuilderHtmx::renderAjaxResponseMarkup(): Argument #2 ($submitKey) must be of type string, null given, called in site/modules/FormBuilderHtmx/FormBuilderHtmx.module.php on line 68 and defined in site/modules/FormBuilderHtmx/FormBuilderHtmx.module.php:117

#0 site/modules/FormBuilderHtmx/FormBuilderHtmx.module.php(68): FormBuilderHtmx->renderAjaxResponseMarkup('InputfieldForm2', NULL, '<!DOCTYPE html>...')
#1 wire/core/WireHooks.php (1085): FormBuilderHtmx->{closure}(Object(HookEvent))
#2 wire/core/Wire.php (484): WireHooks->runHooks(Object(Page), 'render', Array)
#3 wire/modules/Process/ProcessPageView.module (184): Wire->__call('render', Array)
#4 wire/modules/Process/ProcessPageView.module (114): ProcessPageView->renderPage(Object(Page), Object(PagesRequest))
#5 wire/core/Wire.php (416): ProcessPageView->___execute(true)
#6 wire/core/WireHooks.php (968): Wire->_callMethod('___execute', Array)
#7 wire/core/Wire.php (484): WireHooks->runHooks(Object(ProcessPageView), 'execute', Array)
#8 index.php (55): Wire->__call('execute', Array)
#9 {main}
thrown (line 117 of site/modules/FormBuilderHtmx/FormBuilderHtmx.module.php)

This error message was shown because: you are logged in as a Superuser. Error has been logged.

Tried to export everything with ProcessExportProfile in it's latest version on ProcessWire 3.0.238.

  • Thanks 1
Link to comment
Share on other sites

On 5/2/2024 at 10:50 PM, FireWire said:

Note- this module is BYOH (Bring Your Own HTMX) as the library is not provided with FormBuilderHtmx

You could do a check for existance of window.htmx and then conditionally include it from CDN.

Sth along these lines

if (typeof window.htmx === 'undefined') {
    var script = document.createElement('script');
    script.src = "https://unpkg.com/htmx.org@latest";
    script.integrity = "sha384-ujb1lZYygJmzgSwoxRggbCHcjc0rB2XoQrxeTUQyRjrOnlCoYta87iKBWq3EsdM2"; // Not sure if this works reliably with @latest
    script.crossOrigin = "anonymous";
    document.head.appendChild(script);
    script.onload = function() {
        console.log("htmx loaded successfully!");
    };
    script.onerror = function() {
        console.error("Failed to load htmx!");
    };
} else {
    console.log("htmx is already loaded.");
}

 

Link to comment
Share on other sites

7 hours ago, gebeer said:
Not sure if this works reliably with @latest

Yeah, the subresource key is a hash of the file contents so that will break at some point on @latest. Alternatively, I don't want to introduce external resource versioning since it would mean the module has to be updated to keep up with HTMX.

Biggest deal for me is that, as an online privacy advocate, I can't recommend something that I wouldn't use myself.

7 hours ago, gebeer said:

htmx is awesome and absolutely the right tool for such things.

Agreed! Great way to add SPA features without fundamentally changing ProcessWire rendering. I'd argue that it's the way that interactive UI should be built to begin with.

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...