'Not able to get invalid feedback message for input field Bootstrap 5 validation
I have created a simple form page for people to submit change requests and am struggling to get the invalid validation working for the input field where type="file".
I have written a function to run the object through custom validation (similar to how I handle Email validation), but I never receive the red outline and error message like I do for email. I am logging my "Not valid" message successfully when I try to upload more than 5 files, but still receive a green outline and the valid message on the input.
I think I've tried so much at this point I'm just confusing myself. I was able to get both valid and invalid messages at one point, but nothing beyond that.
I am trying to avoid validating every input individually if possible.
Thanks for any help in advance!
<!DOCTYPE html>
<html lang="en" class="vh-100">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="" />
<meta name="author" content="AWright" />
<link rel="icon" href="##URL_FAV_ICON##" />
<title>Change Request Form</title>
<!-- Bootstrap 5 CSS -->
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous"
/>
<!-- /Bootstrap 5 CSS-->
<!-- Axios Library -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!-- /Axios Library -->
<style></style>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
</head>
<body>
<div id="awApp" class="d-flex flex-column vh-100">
<!-- FIXED NAVBAR AND/OR HEADER -->
<header>
<nav
class="navbar navbar-expand-md navbar-light fixed-top bg-light"
></nav>
</header>
<!-- / HEADER/NAVBAR -->
<!-- MAIN CONTENT -->
<main role="main" class="flex-shrink-0">
<div class="container">
<div class="row mt-5 pt-5">
<div class="col-md-8 offset-md-2">
<h2 class="mt-5 text-center" style="font-size: 3rem">
Program Change Request Form
</h2>
<p class="text-center">
Please complete the below form to submit your program change
request:
</p>
</div>
</div>
<div class="row">
<div class="col-md-6 offset-md-3">
<div class="card shadow p-3 my-5">
<div class="card-body">
<form
novalidate
class="needs-validation"
name="mainForm"
@submit="submitForm"
method="post"
ref="requestForm"
>
<div class="row mb-2">
<div class="col-md-6 mb-3">
<label for="firstname" class="form-label mb-0"
>First Name*</label
>
<input
id="firstname"
type="text"
name="firstname"
class="form-control"
v-model="contact.firstName"
required
/>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">
Please enter a first name.
</div>
</div>
<div class="col-md-6 mb-3">
<label for="lastname" class="form-label mb-0"
>Last Name*</label
>
<input
id="lastname"
type="text"
name="lastname"
class="form-control"
v-model="contact.lastName"
required
/>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">
Please enter a last name.
</div>
</div>
</div>
<div class="row mb-3">
<div class="col">
<label for="email" class="form-label mb-0"
>Email Address*</label
>
<input
id="email"
type="text"
name="email"
class="form-control"
v-model="contact.email"
pattern="\b[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,100}\b"
required
/>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">
Please enter a valid email.
</div>
</div>
</div>
<div class="row mb-3">
<div class="col">
<label for="name" class="form-label mb-0"
>Name of Request*</label
>
<input
id="name"
type="text"
name="RequestName"
class="form-control"
v-model="contact.name"
required
/>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">
Please enter a name for the change request being made.
</div>
</div>
</div>
<div class="row mb-3">
<div class="col">
<label for="description" class="form-label mb-0"
>Description of Request*</label
>
<textarea
id="description"
type="text"
name="RequestDetails"
class="form-control"
v-model="contact.description"
required
></textarea>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">
Please enter a description for the request being made.
</div>
</div>
</div>
<div class="row mb-3">
<div class="col">
<label for="due_date" class="form-label mb-0"
>Estimated Due Date*</label
><br />
<em
><small
>Please note that this subject to change.</small
></em
>
<input
id="due_date"
type="text"
name="CompletionDate"
class="form-control"
v-model="contact.dueDate"
v-maska="dateMask"
required
/>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">
Please enter a desired due date for the change request
in MM/dd/yyyy format.
</div>
</div>
</div>
<div class="row mb-3">
<div class="col">
<label for="files" class="form-label mb-0"
>Please attach any assets (images, font files, etc)
here to upload*:</label
><br />
<small
><em
>*Maximum of 5 files can be uploaded at a time</em
></small
>
<input
type="file"
class="form-control"
id="files"
name="files"
@change="handleFilesUpload( $event )"
multiple
/>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">
Please do not upload more than 5 files at a time.
</div>
</div>
</div>
<button
type="submit"
class="btn btn-primary px-4 py-2"
value="Submit"
>
Submit
</button>
<div>
<small class="form-text text-muted">
<em>* Denotes a required field.</em>
</small>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</main>
<!-- /MAIN CONTENT -->
</div>
<!--Bootstrap 5 JS-->
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"
></script>
<!--/Bootstrap 5 JS-->
<!-- Maska JS -->
<script src="https://cdn.jsdelivr.net/npm/maska@latest/dist/maska.js"></script>
<!-- /Maska JS -->
<!-- VUE APP CODE -->
<script>
const app = Vue.createApp({
data() {
return {
currentYear: new Date().getFullYear(),
now: new Date().toISOString(),
contact: {
firstName: "##firstname##",
lastName: "##lastname##",
email: "##email##",
name: "",
description: "",
dueDate: "",
},
files: "",
};
},
methods: {
submitForm(e) {
const isValid =
this.contact.firstName &&
this.contact.lastName &&
this.contact.email &&
this.contact.name &&
this.contact.description &&
this.contact.dueDate &&
this.validEmail(this.contact.email) &&
this.files.length <= 5 &&
this.multipleFilesValidation(this.files);
e.target.classList.add("was-validated");
if (!isValid) {
e.preventDefault();
console.log("Not valid");
} else {
e.preventDefault();
this.postToZapier();
console.log("Success");
}
},
multipleFilesValidation: function (files) {
if (this.files.length > 5) {
console.log(this.files);
return false;
} else {
return true;
}
},
handleFilesUpload(event) {
this.files = event.target.files;
},
postToZapier() {
console.log(this.files);
var formData = new FormData();
for (var i = 0; i < this.files.length; i++) {
let file = this.files[i];
formData.append("files[" + i + "]", file);
}
console.log(formData);
var url = "https://hooks.zapier.com/hooks/catch/159749/b9h6kww/";
var requestForm = this.$refs.requestForm;
console.log(requestForm);
axios
.post(url, formData, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then(function () {
console.log("Success!");
setTimeout(function () {
requestForm.submit();
}, 0);
})
.catch(function () {
console.log("Fail.");
});
},
validEmail: function (email) {
const re = /\b[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,100}\b/;
return re.test(email);
},
},
computed: {
dateMask: function () {
return "##/##/####";
},
},
});
app.directive("maska", Maska.maska);
app.mount("#awApp");
</script>
<!-- /VUE APP CODE-->
</body>
</html>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
