Setup

Form Setup

Canvas ships an AJAX contact form that submits without a page reload, validates fields client-side, and posts to a PHP processor (include/form.php). This guide covers the wrapper, the form element, and the required hidden fields. Markup is taken from contact.html and block-contact-1.html.

Structure

Wrap the form in .form-widget. Inside, add an empty .form-result (where the alert message renders) and the <form> itself pointing at include/form.php.

<div class="form-widget">

    <div class="form-result"></div>

    <form class="mb-0" id="template-contactform" name="template-contactform" action="include/form.php" method="post">

        <div class="form-process">
            <div class="css3-spinner">
                <div class="css3-spinner-scaler"></div>
            </div>
        </div>

        <div class="row">

            <div class="col-md-4 form-group">
                <label for="template-contactform-name">Name <small>*</small></label>
                <input type="text" id="template-contactform-name" name="template-contactform-name" value="" class="form-control required">
            </div>

            <div class="col-md-4 form-group">
                <label for="template-contactform-email">Email <small>*</small></label>
                <input type="email" id="template-contactform-email" name="template-contactform-email" value="" class="required email form-control">
            </div>

            <div class="col-md-4 form-group">
                <label for="template-contactform-phone">Phone</label>
                <input type="text" id="template-contactform-phone" name="template-contactform-phone" value="" class="form-control">
            </div>

            <div class="w-100"></div>

            <div class="col-md-8 form-group">
                <label for="template-contactform-subject">Subject <small>*</small></label>
                <input type="text" id="template-contactform-subject" name="subject" value="" class="required form-control">
            </div>

            <div class="col-12 form-group">
                <label for="template-contactform-message">Message <small>*</small></label>
                <textarea class="required form-control" id="template-contactform-message" name="template-contactform-message" rows="6" cols="30"></textarea>
            </div>

            <div class="col-12 form-group d-none">
                <input type="text" id="template-contactform-botcheck" name="template-contactform-botcheck" value="" class="form-control">
            </div>

            <div class="col-12 form-group">
                <button class="button button-3d m-0" type="submit" id="template-contactform-submit" name="template-contactform-submit" value="submit">Send Message</button>
            </div>

        </div>

        <input type="hidden" name="prefix" value="template-contactform-">

    </form>
</div>

Setup

Three things make the AJAX form work:

  1. The .form-widget wrapper. Canvas binds its AJAX handler to this element. Without it, the form posts normally (full page reload).
  2. The .form-result div. Left empty; the success or error alert renders here.
  3. The prefix hidden field. include/form.php strips this prefix from field names when building the email. Every field name that should appear in the email starts with the prefix (for example template-contactform-name), while shared control fields such as subject do not.

The .form-process block holds the CSS spinner shown while the request is in flight.

The Bot Check (Honeypot)

Every Canvas form includes a hidden honeypot field. It is a real input hidden with d-none. Bots fill every field, so if botcheck is non-empty the PHP processor rejects the submission as a bot.

<div class="col-12 form-group d-none">
    <input type="text" id="template-contactform-botcheck" name="template-contactform-botcheck" value="" class="form-control">
</div>

The field name must be <prefix>botcheck (here template-contactform-botcheck). Leave the value empty; do not remove it.

Wrapper Options

The .form-widget accepts data-* attributes that change submit behaviour:

<!-- Show the alert inline instead of a floating notification -->
<div class="form-widget" data-alert-type="inline">

<!-- Replace the spinner with an in-button loading spinner -->
<div class="form-widget" data-loader="button">
  • data-alert-type = notify (default, floating toast) or inline (renders the alert in .form-result).
  • data-loader = button to swap the submit button label for a spinner during submit (used by subscribe widgets like .subscribe-widget).
  • data-redirect = a URL to send the user to on success.
  • data-timeout = request timeout in milliseconds (default 30000).

See the Settings doc for the full list of data-* options.

Tips

  • Keep action="include/form.php" unless you rename the processor; the JS reads the form's action for the AJAX target.
  • Field names with the form prefix appear in the email; unprefixed reserved names (subject, prefix, replyto, autoresponder) are treated as configuration, not content.
  • Use class="required" (plus email for email fields) so the validator enforces them before submit.
  • The submit button uses the Canvas .button shortcode (button button-3d), not the Bootstrap .btn.

Usage

Using PHP in Canvas

Canvas ships as static HTML, but several dynamic features run on small PHP includes found in the include/ folder (contact form processing, the newsletter subscribe endpoint, and the Twitter feed loader). To use them, serve the pages through PHP.

Contact form (points the form at the bundled handler):

<form class="mb-0" id="template-contactform"
      action="include/form.php" method="post">
    <input type="text" class="form-control" name="template-contactform-name" required>
    <input type="email" class="form-control" name="template-contactform-email" required>
    <textarea class="form-control" name="template-contactform-message" required></textarea>
    <button class="button button-3d m-0" type="submit">Send Message</button>
</form>

Notes:

  • To render .html files as PHP, either rename them to .php, or add a handler rule in your server config so .html is parsed by PHP.
  • The Twitter widget loads tweets from a PHP endpoint (default include/twitter/tweets.php); it must return JSON. See the Twitter OAuth setup snippet for the credentials it needs.
  • Set your destination email and any API keys inside the relevant files in include/ before going live.
  • Static hosting without PHP will still show every page; only the form/subscribe/twitter back ends need a PHP runtime.
Was this page helpful?