Pipit: pipit_form_response()
The function returns a JSON response detailing whether a form submission was successful and if not, what the errors are. This is useful for submitting forms via Javascript.
pipit_form_response($formID, $opts, $return);
Parameters:
Type | Description |
---|---|
String | The form ID. This should match the ID in your perch:form tag |
Array | Options array, see below |
Boolean | Set to true to have the value returned instead of echoed. |
Options array:
Option | Value |
---|---|
app | The Perch app(s) that should handle the form submission |
template | The Perch template that should be used to validate the submission |
dispatch | Boolean. Set to true for the Pipit app to pass the form submission to Perch. Useful when submitting from a non-Perch-templated form, to a Runway endpoint or when submitting the data as JSON. |
Responses
The function returns a JSON response like this:
{
"status": 200,
"errors": false
}
{
"status": 422,
"errors": {
"name": {"type": "required"},
"email": {"type": "format"}
}
}
If you turn on Perch debug mode, the response will include a debug message set by the Pipit app as well as the Perch debug message:
{
"status": 422,
"errors": {
"name": {"type": "required"},
"email": {"type": "format"}
},
"debug": "You have some errors",
"perch_debug": [...]
}
This is can be useful to diagnose issues in your set up. For instance if you specify a validation template that does not exist, you will get this response:
{
"status": 500,
"debug": "Template not found",
"perch_debug": [...]
}
It is then your responsibility to proceed based on the response however you see best. For example, it is your responsibility to display error messages on the front-end.
Customising error data
By default the response only includes the error type:
"email": {"type": "format"}
You can from the template specify additional data to be returned for errors using Perch’s perch:error conditional tags. Any response-*
attributes on the tag is returned with the response:
<perch:error for="email" type="format" response-message="Please enter a valid email address"></perch:error>
"email": {
"type": "format",
"message": "Please enter a valid email address"
}
If you follow progressive enhancement principles and the form works without Javascript too, you can still include your server-rendered error message markup inside the perch:error
tags:
<perch:error for="email" type="format" response-message="Please enter a valid email address">
<span class="error">Please enter a valid email address.</span>
</perch:error>
<perch:error for="email" type="format" response-message="This is returned with the JSON response">
<span class="error">This is a server-rendered error message. It is used when you submit the form without JS.</span>
</perch:error>
Usage
Where to add
Perch Runway: API endpoints
On Perch Runway you can add endpoints to templates/api/
. You can add an endpoint like /api/enquiry
for a contact form. In this context, you need to use the dispatch
option:
pipit_form_response('contact', ['dispatch' => true]);
Standard Perch
On standard Perch you can add it to the same page as the form or on a separate page on its own. Add it right after the runtime include (before outputting anything) and inside a condition that only evaluates to true if your form has been posted.
<?php
include('perch/runtime.php');
if(!empty($_POST)) {
pipit_form_response('contact');
exit;
}
If you are posting JSON, you can use:
<?php
include('perch/runtime.php');
if(Pipit_Util::is_json_content_type()) {
pipit_form_response('contact', ['dispatch' => true]);
exit;
}
Non-Perch-templated forms
If you are using a non-Perch-template form (or even programmatically posting with JS), you need to specify a validation template and an app to handle the submission. You also need to use the dispatch
option:
pipit_form_response('contact', [
'template' => 'forms/contact.html',
'app' => 'perch_forms',
'dispatch' => true,
]);
Posting JSON
If you are posting the data as JSON, Perch won’t automatically handle this so you have to use the dispatch
option:
pipit_form_response('contact', ['dispatch' => true]);
Submitting a Perch-templated form via JS
There are multiple ways of posting forms with Javascript. For instance, you can use XMLHttpRequest
, fetch
or a third-party library like axios.
Here is a basic contact form:
<perch:form id="contact" method="post" app="perch_forms" data-form="contact">
<div class="field">
<perch:label for="name">Name</perch:label>
<perch:input id="name" type="text" label="Name" required />
</div>
<div class="field">
<perch:label for="email">Email</perch:label>
<perch:input type="email" id="email" label="Email" required />
</div>
<div class="field">
<perch:label for="message">Message</perch:label>
<perch:input id="message" type="textarea" label="Message" required />
</div>
<perch:input type="submit" id="submit" value="Send" />
</perch:form>
Submitting using XMLHttpRequest
:
const myform = document.querySelector('[data-form="contact"]');
myform.addEventListener('submit', function(event) {
event.preventDefault();
let formData = new FormData(myform);
let xhr = new XMLHttpRequest();
xhr.open("POST", '/api/endpoint', true);
xhr.send(formData);
xhr.onload = function() {
if (xhr.status == 200) {
console.log('Success!');
console.log(JSON.parse( this.responseText ));
} else {
console.log("Error " + xhr.status + " occurred.");
console.log(JSON.parse( this.responseText ));
}
};
});
Submitting using axios:
const myform = document.querySelector('[data-form="contact"]');
myform.addEventListener('submit', function(event) {
event.preventDefault();
let formData = new FormData(myform);
axios.post('/api/endpoint', formData)
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.log(error);
console.log(error.response);
});
});