Skip to content

Instantly share code, notes, and snippets.

@wittyprogramming
Last active May 2, 2022 19:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wittyprogramming/730f71e0507bcf2328aafa4137876b06 to your computer and use it in GitHub Desktop.
Save wittyprogramming/730f71e0507bcf2328aafa4137876b06 to your computer and use it in GitHub Desktop.
Form Validation using Alpine.js framework applying a Vue composition-like architecture.
import {
isEmail,
isMaxLength,
isMinLength,
isRequired,
} from "./validators.mjs";
export function formValidator() {
let submitBackend;
return {
name: null,
nameDirty: false,
email: null,
emailDirty: false,
comments: null,
commentsDirty: false,
isNameValid(maxLength) {
return (
this.nameDirty &&
isRequired(this.name) &&
(maxLength ? isMaxLength(this.name, maxLength) : true)
);
},
isEmailValid() {
return this.emailDirty && isEmail(this.email);
},
isCommentsValid(minLength) {
return (
this.commentsDirty &&
isRequired(this.comments) &&
(minLength ? isMinLength(this.comments, minLength) : true)
);
},
isFormValid() {
return (
this.isNameValid() && this.isEmailValid() && this.isCommentsValid()
);
},
submitForm(formElement) {
this.nameDirty = true;
this.emailDirty = true;
this.commentsDirty = true;
if (!this.isFormValid()) return;
submitBackend(formElement);
},
formValidator_init(backend) {
submitBackend = backend;
},
};
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script type="module" defer>
import { formValidator } from "./form-validator.mjs"
import { netlifySubmission } from "./netlify.mjs"
window.contactForm = function() {
return {
...netlifySubmission(),
...formValidator(),
init() {
this.formValidator_init(this.submitToNetlify);
}
}
}
</script>
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.7.2/dist/alpine.min.js" defer></script>
<style>
[x-cloak] {
display: none;
}
</style>
<title>Sample Contact Form for Netlify using Alpine.js component-based composition approach</title>
</head>
<body>
<h1>Sample Contact Form for Netlify using Alpine.js</h1>
<form
hidden
name="contact"
method="POST"
data-netlify="true"
netlify-honeypot="bot-field"
data-netlify-recaptcha="true"
>
<label><input type="text" name="name" /></label>
<label> <input type="email" name="email" /></label>
<label><textarea name="message"></textarea></label>
<div data-netlify-recaptcha="true"></div>
</form>
<form
x-data="contactForm()"
x-on:submit.prevent="submitForm($refs.contactForm);"
x-ref="contactForm"
x-init="init()"
id="contact"
>
<p hidden>
<label>ignore: <input name="bot-field" /></label>
</p>
<input type="hidden" name="form-name" value="contact" />
<p>
<label
>Full Name: <input x-model="name" x-on:blur="nameDirty = true" type="text" name="name"
/></label>
</p>
<p x-show.transition="!isNameValid() && nameDirty" style="color: red" x-cloak>
Please fill out your full name.
</p>
<p>
<label
>Email: <input x-model="email" x-on:blur="emailDirty = true" type="email" name="email"
/></label>
</p>
<p x-show.transition="!isEmailValid() && emailDirty" style="color: red" x-cloak>
Please provide a valid email.
</p>
<p>
<label
>Message:
<textarea x-model="comments" x-on:blur="commentsDirty = true" name="message"></textarea>
</label>
</p>
<p x-show.transition="!isCommentsValid(5) && commentsDirty" style="color: red" x-cloak>
Please fill out your Message with at least 5 characters.
</p>
<div data-netlify-recaptcha="true"></div>
<p>
<button type="submit">Send</button>
</p>
</form>
</body>
</html>
export function netlifySubmission() {
return {
submitToNetlify(formElement) {
let body = new URLSearchParams(new FormData(formElement)).toString();
return fetch("/", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: body,
})
.then((response) => {
if (response.ok) {
formElement.reset();
alert("Thank you for your message!");
} else {
throw new Error(`Something went wrong: ${response.statusText}`);
}
})
.catch((error) => console.error(error));
},
};
}
export function isEmail(value) {
return new RegExp("^\\S+@\\S+[\\.][0-9a-z]+$").test(
String(value).toLowerCase()
);
}
export function isRequired(value) {
return value !== null && value !== undefined && value.length > 0;
}
export function isMinLength(value, length) {
return String(value).length >= length;
}
export function isMaxLength(value, length) {
return String(value).length <= length;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment