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:
- The
.form-widgetwrapper. Canvas binds its AJAX handler to this element. Without it, the form posts normally (full page reload). - The
.form-resultdiv. Left empty; the success or error alert renders here. - The
prefixhidden field.include/form.phpstrips this prefix from field names when building the email. Every field name that should appear in the email starts with the prefix (for exampletemplate-contactform-name), while shared control fields such assubjectdo 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) orinline(renders the alert in.form-result).data-loader=buttonto 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 (default30000).
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"(plusemailfor email fields) so the validator enforces them before submit. - The submit button uses the Canvas
.buttonshortcode (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
.htmlfiles as PHP, either rename them to.php, or add a handler rule in your server config so.htmlis 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.
