<!--Companion article: https://css-tricks.com/headless-form-submission-with-the-wordpress-rest-api/-->
<p class="bg-secondary text-center text-primary p-1">
There's no reply. Submissions are deleted automatically and immediately.
</p>
<div class="container">
<div class="columns col-gapless">
<div class="col-sm-12 col-md-8 col-4 col-mx-auto">
<h4>Contact Form 7</h4>
<div class="divider"></div>
<form action="https://cssformsrestapi.tastewp.com/wp-json/contact-form-7/v1/contact-forms/5/feedback" method="post" autocomplete="off">
<!--The "required" attributes are not used on purpose.-->
<div class="form-group">
<label class="form-label" for="somebodys-name">Somebody's name</label>
<input class="form-input" id="somebodys-name" type="text" name="somebodys-name">
</div>
<div class="form-group">
<label class="form-label" for="any-email">Any valid email address</label>
<!--The type="email" is not used on purpose.-->
<input class="form-input" id="any-email" type="text" name="any-email">
</div>
<div class="form-group">
<!--Space Age began at October 4, 1957-->
<label class="form-label" for="before-space-age">A date before the Space Age</label>
<!--The "max" attribute is not used on purpose.-->
<input class="form-input col-8" id="before-space-age" type="date" placeholder="yyyy-mm-dd" name="before-space-age">
</div>
<div class="form-group">
<label class="form-label" for="optional-message">Optional message to the world</label>
<textarea class="form-input" id="optional-message" name="optional-message"></textarea>
</div>
<div class="form-group">
<label class="form-switch">
<input name="fake-terms" type="checkbox" value="1">
<i class="form-icon"></i>
Fake and obligatory terms and conditions checkbox
</label>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">
Submit
</button>
</div>
</form>
<div class="mt-12 mt-6">
<h4>Gravity Forms</h4>
<div class="divider"></div>
<form action="https://cssformsrestapi.tastewp.com/wp-json/gf/v2/forms/1/submissions" method="post" autocomplete="off">
<!--The "required" attributes are not used on purpose.-->
<div class="form-group">
<label class="form-label" for="input_1">Somebody's name</label>
<input class="form-input" id="input_1" type="text" name="input_1">
</div>
<div class="form-group">
<label class="form-label" for="input_2">Any valid email address</label>
<!--The type="email" is not used on purpose.-->
<input class="form-input" id="input_2" type="text" name="input_2">
</div>
<div class="form-group">
<!--Space Age began at October 4, 1957-->
<label class="form-label" for="input_3">A date before the Space Age</label>
<!--The "max" attribute is not used on purpose.-->
<input class="form-input col-8" id="input_3" type="date" placeholder="yyyy-mm-dd" name="input_3">
</div>
<div class="form-group">
<label class="form-label" for="input_4">Optional message to the world</label>
<textarea class="form-input" id="input_4" name="input_4"></textarea>
</div>
<div class="form-group">
<label class="form-switch">
<input name="input_5_1" type="checkbox" value="1">
<i class="form-icon"></i>
Fake and obligatory terms and conditions checkbox
</label>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">
Submit
</button>
</div>
</form>
</div>
</div>
</div>
</div>
.mt-12 {
margin-top: calc(0.2rem * 12);
}
.mt-6 {
margin-bottom: calc(0.2rem * 6);
}
[x-cloak] {
display: none;
}
// https://css-tricks.com/snippets/javascript/strip-html-tags-in-javascript/
const stripHtml = (string) => string.replace(/(<([^>]+)>)/gi, "");
const normalizeResponse = (url, response) => {
if (
url.match(/wp-json\/contact-form-7\/v1\/contact-forms\/\d+\/feedback/)
) {
return normalizeContactForm7Response(response);
}
if (url.match(/wp-json\/gf\/v2\/forms\/\d+\/submissions/)) {
return normalizeGravityFormsResponse(response);
}
return {
isSuccess: false,
message: "Are you submitting to the right URL?",
validationError: {}
};
};
const normalizeGravityFormsResponse = (response) => {
const isSuccess = response.is_valid;
const message = isSuccess
? stripHtml(response.confirmation_message)
: "There was a problem with your submission.";
const validationError = isSuccess
? {}
: Object.fromEntries(
Object.entries(
response.validation_messages
).map(([key, value]) => [`input_${key}`, value])
);
return {
isSuccess,
message,
validationError
};
};
const normalizeContactForm7Response = (response) => {
const isSuccess = response.status === "mail_sent";
const message = response.message;
const validationError = isSuccess
? {}
: Object.fromEntries(
response.invalid_fields.map((error) => {
const key = /cf7[-a-z]*.(.*)/.exec(error.into)[1];
return [key, error.message];
})
);
return {
isSuccess,
message,
validationError
};
};
const formSubmissionHandler = (event) => {
event.preventDefault();
const formElement = event.target,
{ action, method } = formElement,
body = new FormData(formElement);
fetch(action, {
method,
body
})
.then((response) => response.json())
.then((response) => normalizeResponse(action, response))
.then((response) => {
alert(response.message);
if (response.isSuccess) {
formElement.reset();
}
})
.catch((error) => {
alert("Check the console for the error details.");
console.log(error);
});
};
const formElements = document.querySelectorAll("form");
formElements.forEach((formElement) =>
formElement.addEventListener("submit", formSubmissionHandler)
);
View Compiled
This Pen doesn't use any external JavaScript resources.