Skip to content

Instantly share code, notes, and snippets.

@neisdev
Created April 16, 2023 12:45
Show Gist options
  • Save neisdev/2881cebe16298967756aec7374070603 to your computer and use it in GitHub Desktop.
Save neisdev/2881cebe16298967756aec7374070603 to your computer and use it in GitHub Desktop.
Model based form validation with Alpine.js and Tailwindcss
<body>
<div class="bg-gray-200 h-screen">
<div class="container mx-auto w-full h-full">
<div class="max-w-screen-sm mx-auto w-full h-full flex flex-col items-center justify-center">
<div class="bg-white p-5 shadow-md w-full">
<h1 class="text-gray-900 mb-8">Form Validation</h1>
<form
method="POST"
x-data="validateForm()"
x-init="
$watch('fullname', value => { validate('fullname') })
$watch('email', value => { validate('email') })
$watch('password', value => { validate('password') })
"
class="flex flex-col space-y-4"
>
<div class="flex flex-col space-y-2">
<label for="name">Full Name</label>
<input type="text" x-model="fullname" class="px-2 py-1 border rounded-md focus:outline-none focus:border-blue-400" placeholder="Enter your full name...">
<span class="text-sm italic text-red-500">
<div x-text="validation.fullname.message"></div>
</span>
</div>
<div class="flex flex-col space-y-2">
<label for="email">Email</label>
<input type="email" x-model="email" class="px-2 py-1 border rounded-md focus:outline-none focus:border-blue-400" placeholder="Enter your email address...">
<span class="text-sm italic text-red-500">
<div x-text="validation.email.message"></div>
</span>
</div>
<div class="flex flex-col space-y-2">
<label for="password">Password</label>
<input type="password" x-model="password" class="px-2 py-1 border rounded-md focus:outline-none focus:border-blue-400" placeholder="Enter your password...">
<span class="text-sm italic text-red-500">
<div x-text="validation.password.message"></div>
</span>
</div>
<div class="flex flex-row-reverse">
<button class="px-2 py-1 uppercase border bg-gray-200 text-gray-900">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
'use strict'
window.validateForm = function () {
return {
fullname: '',
email: '',
password: '',
validation: {
fullname: {
rule: {
required: function (field) {
if (field) {
return { error: false, message: ''}
} else {
return { error: true, message: 'This field is required.'}
}
},
minLength: function (field, value = 2) {
if (field && field.length >= value) {
return { error: false, message: ''}
} else {
return { error: true, message: `This field must have minimum ${value} characters length.`}
}
}
},
error: true,
message: ''
},
email: {
rule: {
required: function (field) {
if (field) {
return { error: false, message: ''}
} else {
return { error: true, message: 'This field is required.'}
}
},
email: function (field) {
const rgx = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
if (rgx.test(field)) {
return { error: false, message: ''}
} else {
return { error: true, message: 'This field has wrong email address format.'}
}
}
},
error: true,
message: ''
},
password: {
rule: {
required: function (field) {
if (field) {
return { error: false, message: ''}
} else {
return { error: true, message: 'This field is required.'}
}
},
minLength: function (field, value = 8) {
if (field && field.length >= value) {
return { error: false, message: ''}
} else {
return { error: true, message: `This field must have minimum ${value} characters length.`}
}
}
},
error: true,
message: ''
}
},
validate (field) {
for (const key in this.validation[field].rule) {
const validationResult = this.validation[field].rule[key](this[field])
if (validationResult.error) {
this.validation[field].error = true
this.validation[field].message = validationResult.message
break
}
this.validation[field].error = false
this.validation[field].message = ''
continue
}
}
}
}
<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/1.4.6/tailwind.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment