'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