Skip to content

Instantly share code, notes, and snippets.

@juno-w
Created June 11, 2021 07:58
Show Gist options
  • Save juno-w/988ab8fe8232712747263d4e3df885c8 to your computer and use it in GitHub Desktop.
Save juno-w/988ab8fe8232712747263d4e3df885c8 to your computer and use it in GitHub Desktop.
Multiple emails input just with Tailwind CSS and Alpine.js
<div>
<div class="flex items-center px-1 bg-white border border-gray-300 rounded-md">
<div class="flex flex-wrap items-center flex-1 py-1 space-x-1">
<template x-for="(recipient, index) in recipients">
<div x-bind:class="{
'bg-blue-100 rounded-full': recipient.valid,
'border-b border-dashed border-red-500': !recipient.valid
}" class="inline px-2 py-px text-sm text-gray-800 ">
<span x-text="recipient.email"></span>
<button x-on:click.prevent="removeEmail(index)" class="text-gray-700 focus:outline-none hover:text-red-500">&times;</button>
</div>
</template>
<textarea
id="emails"
placeholder="Add email..."
x-ref="emails"
rows="1"
class="flex-grow py-1.5 leading-none bg-transparent border-none resize-none focus:ring-0 focus:border-none"
x-model="sendTo"
x-on:keydown.,.prevent="addEmail"
x-on:keydown.backspace="backspace"
x-on:keydown.enter.prevent="addEmail"
x-on:blur.prevent="addEmail"
x-on:paste="handlePasteEmails"></textarea>
</div>
</div>
<x-jet-input-error for="sendTo" class="mt-2" class="!text-xs mt-1" />
</div>
@push('scripts')
<script>
window.hapiForm = function() {
return {
sendTo: '',
recipients: @entangle('sendTo'),
// Method to validate input and push to recipients, return void
addEmail: function() {
if (this.isValidEmail(this.sendTo) && this.sendTo.length) {
this.recipients.push({
email: this.sendTo,
valid: true
});
this.sendTo = '';
this.$refs.emails.focus();
} else if (!this.isValidEmail(this.sendTo) && this.sendTo.length) {
this.recipients.push({
email: this.sendTo,
valid: false
});
this.sendTo = '';
this.$refs.emails.focus();
}
},
// Check if the input is a valid email address, return boolean
isValidEmail: function(input) {
if (/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/.test(input)) {
return (true);
}
return (false);
},
// Remove email address from list, return new recipients array
removeEmail: function(index) {
this.recipients = this.recipients.filter((recipient, i) => i !== index)
},
// Remove recipients last item if input is empty
backspace: function() {
if (this.sendTo.length == 0 && this.recipients.length > 0) {
this.recipients.pop();
}
},
// On paste emails john@mail.com, jimmy@mail.com, janet@mail.com,
handlePasteEmails: function(e) {
const clipboard = e.clipboardData.getData('text');
const emails = clipboard.split(',')
.filter(email => email)
.map(emailAddress => {
const trimmedEmail = emailAddress.trim()
return {
email: trimmedEmail,
valid: this.isValidEmail(trimmedEmail)
}
})
this.$refs.emails.blur();
this.recipients = emails;
setTimeout(() => this.$refs.emails.focus(), 150);
}
}
}
</script>
@endpush
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment