formbus

    0.5.2 • Public • Published

    FormBus

    FormBus is what you are looking for if you do server-side form validation, and you want a plug and play front-end solution to do the typical.

    You can use the built-in directives to show or toggle CSS class names when the fields validation failed, or when the submission was successful, or something went wrong.

    In the WordPress context, FormBus is suitable when you are using a forms plugin and:

    1. The generated HTML structure does not suit your needs, or you are using utility-first CSS frameworks like Tailwind CSS, and you wish to use those class names
    2. You are deep into the rabbit hole of front-end optimization, and you don't want any bloated libraries or dependencies that you are not using anywhere else, like jQuery
    3. You are using WordPress as a headless CMS, and you are using the REST API as a primary way to interact with it

    FormBus demo with Contact Form 7

    Check out the video demonstration


    Usage

    Installation

    The recommended way of installing FormBus is using npm:

    npm install formbus

    Submitting your form

    As long as your form element is set up correctly:

    1. action is pointing to the API endpoint
    2. method is set to to post
    3. input elements have the name attribute

    FormBus is able to construct the request and send it. It uses Fetch API, and the data is constructed using FormData.

    If you need to set additional configuration values, for example, headers, you can use the configuration object. It's explained later in the documentation.

    <form action="https://your-website.com/wp-json/contact-form-7/v1/contact-forms/<ID>/feedback"
          method="post"
          id="contact-form">
        <div class="form-group">
            <label for="name">Your Name</label>
            <input type="text" name="your-name" class="form-control" id="name">
        </div>
        <!-- Other input elements -->
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>

    In your JavaScript file, import the corresponding function for the service. The first argument should be a CSS selector matching the form element or a parent, wrapper element.

    The selector expects a single element; if multiple are matched, only the first one is used.

    import { contactForm7Bus } from 'formbus';
    
    const contactFormBus = contactForm7Bus('form#contact-form');

    Or you can pass a HTMLElement directly:

    const contactFormWrapper = document.querySelector('section#contact-form-section');
    const contactFormBus = contactForm7Bus(contactFormWrapper);

    You have to call the init method explicitly for the initialization:

    contactFormBus.init();

    Later on, you can call destroy if you want to remove the events attached to the form:

    contactFormBus.destroy();

    With multiple form elements

    If you want to target multiple elements on the page, first get the elements, and then loop over them:

    const forms = document.querySelectorAll('form');
    
    forms.forEach(form => {
        const cf7FormBus = contactForm7Bus(form);
    
        cf7FormBus.init();
    });

    Supported services

    Contact Form 7

    Just another contact form plugin for WordPress. Simple but flexible.

    import { contactForm7Bus } from 'formbus';

    The REST API endpoint, if not altered, should look like this:

    https://your-website.com/wp-json/contact-form-7/v1/contact-forms/<ID>/feedback
    
    Gravity Forms

    Gravity Forms is the Easiest, Most Trusted Tool to Create Advanced Forms for Your WordPress-Powered Website.

    import { gravityFormsBus } from 'formbus';

    The REST API endpoint, if not altered, should look like this:

    https://your-website.com/wp-json/gf/v2/forms/<ID>/submissions
    
    Your service

    FormBus is extensible; if your endpoint returns field validation errors, and you can infer the submission state, you should be able to use it with your service. More about this later.

    Directives

    Directives are useful when you want to have what is expected. Just add one of the attributes to an element, and FormBus will do the rest.

    <form action="https://your-website.com/wp-json/contact-form-7/v1/contact-forms/43/feedback"
          method="post"
          id="contact-form"
    +     form-state-class>
    
    +   <div form-state-message></div>
    
    +   <div class="form-group" field-validation-error-class="your-name">
            <label for="name">Your Name</label>
            <input type="text" name="your-name" class="form-control" id="name">
    +       <div field-validation-error-message="your-name"></div>
        </div>
        <!-- Other input elements -->
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>

    Depending on your case, you can use only one directive or all of them:

    • field-validation-error-class
    • field-validation-error-message
    • form-state-class
    • form-state-message

    For separate form states:

    • form-submission-error-class
    • form-submission-error-message
    • form-submission-success-class
    • form-submission-success-class
    • form-validation-error-class
    • form-validation-error-message

    Events

    With the helper functions, you get a lot of flexibility, but it's up to you to act on different states.

    Events are attached to the form element.

    afterFormBusResponse

    const contactForm = document.querySelector('#contact-form');
    const contactFormBus = contactForm7Bus(contactForm);
    
    contactFormBus.init();
    
    contactForm.addEventListener('afterFormBusResponse', ({ detail: response }) => {
        console.log(response);
    });

    This custom event is fired after the form submission when a response is returned.

    The event's detail contains the raw response object. The format and the returned data that depends on the service.

    Response helper functions

    Because the response differs from service to service, FormBus provides a set of helper functions that you can use instead of writing logic that is bound to a specific service.

    The following methods are accessible under the responseHelpers key:

    • getFieldValidationErrorMessage(responseData, fieldName)
    • getFormSubmissionErrorMessage(responseData)
    • getFormSubmissionSuccessMessage(responseData)
    • getFormValidationErrorMessage(responseData)
    • isFieldValidationError(responseData, fieldName)
    • isFormSubmissionError(responseData)
    • isFormSubmissionSuccess(responseData)
    • isFormValidationError(responseData)

    Here's an example where it replaces the form element with the success message:

    contactForm.addEventListener('afterFormBusResponse', ({ detail: response }) => {
        const helpers = contactFormBus.responseHelpers;
    
        if (!helpers.isFormSubmissionSuccess(response)) {
            alert('Something went wrong.');
            return;
        }
    
        const successMessage = helpers.getFormSubmissionSuccessMessage(response);
    
        contactFormBus.destroy();
        contactForm.innerHTML = `<p>${successMessage}</p>`;
    });

    beforeFormBusRequest

    contactForm.addEventListener('beforeFormBusRequest', ({ detail: formData }) => {
        console.log(formData);
    });

    The custom event's detail contains the FormData that is sent with the request.

    Configuration

    You can overwrite the default configuration by passing an object as the second argument.

    const yourConfig = {
        classNames: {
            fieldValidationError: '--is-error'
        }
    };
    const contactFormBus = contactForm7Bus('#contact-form', yourConfig);

    Configuration values are merged with the defaults. If you want to overwrite a few of them, you don't have to provide the entire configuration object.

    The default configuration:

    const defaultConfig = {
        directives: {
            fieldValidationErrorClassNames: 'field-validation-error-class',
            fieldValidationErrorMessage: 'field-validation-error-message',
            formStateClassNames: 'form-state-class',
            formStateMessage: 'form-state-message',
            formSubmissionErrorClassNames: 'form-submission-error-class',
            formSubmissionErrorMessage: 'form-submission-error-message',
            formSubmissionSuccessClassNames: 'form-submission-success-class',
            formSubmissionSuccessMessage: 'form-submission-success-message',
            formValidationErrorClassNames: 'form-validation-error-class',
            formValidationErrorMessage: 'form-validation-error-message'
        },
        classNames: {
            fieldValidationError: 'is-error is-field-validation-error',
            formSubmissionError: 'is-error is-form-submission-error',
            formSubmissionSuccess: 'is-success is-form-submission-success',
            formValidationError: 'is-error is-form-validation-error'
        },
        request: {}
    };

    Customizing the directive attributes

    const yourConfig = {
        directives: {
            fieldValidationErrorClassNames: 'data-field-error-class',
            fieldValidationErrorMessage: 'data-field-error-message'
        }
    };
    <form action="https://your-website.com/wp-json/contact-form-7/v1/contact-forms/43/feedback"
          method="post"
          id="contact-form"
          form-state-class>
    
        <div form-state-message></div>
    
    -   <div class="form-group" field-validation-error-class="your-name">
    +   <div class="form-group" data-field-error-class="your-name">
            <label for="name">Your Name</label>
            <input type="text" name="your-name" class="form-control" id="name">
    -       <div field-validation-error-message="your-name"></div>
    +       <div data-field-error-message="your-name"></div>
        </div>
        <!-- Other input elements -->
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>

    Use your service

    Instead of service functions, use the formBus that expects to receive response helpers' implementation as the second argument:

    import { formBus } from 'formbus';
    
    const contactFormBus = formBus('#contact-form', serviceResponseHelpers);
    
    contactFormBus.init();

    You are expected to return a string or a null for these functions:

    • getFieldValidationErrorMessage
    • getFormSubmissionErrorMessage
    • getFormSubmissionSuccessMessage
    • getFormValidationErrorMessage

    You are expected to return a boolean for the following:

    • isFieldValidationError
    • isFormSubmissionError
    • isFormSubmissionSuccess
    • isFormValidationError
    const getFieldValidationErrorMessage = (response, fieldName) => {
        return null;
    };
    
    const getFormSubmissionErrorMessage = (response) => {
        return null;
    };
    
    const getFormSubmissionSuccessMessage = (response) => {
        return null;
    };
    
    const getFormValidationErrorMessage = (response) => {
        return null;
    };
    
    const isFieldValidationError = (response, fieldName) => {
        return false;
    };
    
    const isFormSubmissionError = (response) => {
        return false;
    };
    
    const isFormSubmissionSuccess = (response) => {
        return false;
    };
    
    const isFormValidationError = (response) => {
        return false;
    };
    
    const serviceResponseHelpers = {
        getFieldValidationErrorMessage,
        getFormSubmissionErrorMessage,
        getFormSubmissionSuccessMessage,
        getFormValidationErrorMessage,
        isFieldValidationError,
        isFormSubmissionError,
        isFormSubmissionSuccess,
        isFormValidationError
    };

    The configuration object can be passed as the third argument.

    const contactFormBus = formBus('#contact-form', serviceResponseHelpers, yourConfig);

    Changelog

    All notable changes to FormBus are documented in CHANGELOG.md.

    Contributing

    If you are using FormBus and found a bug, then you are likely the most capable of fixing it. You can contribute back the fix by submitting a pull request together with the steps to reproduce it.

    Another way to help is by improving the readme.

    Keywords

    none

    Install

    npm i formbus

    DownloadsWeekly Downloads

    0

    Version

    0.5.2

    License

    MIT

    Unpacked Size

    64.8 kB

    Total Files

    40

    Last publish

    Collaborators

    • meszarosrob