Drag n Drop file upload MDB validation


Topic: Drag n Drop file upload MDB validation

refreshcreativemedia pro asked 6 years ago

How do I validate required on drag-n-drop file-upload in a form?

I want to submit drag-n-drop file-upload data with form submit button click. I tried adding required to the input and the validation fails but I couldn't retrieve any feedback.

I need feedback similar to when I drag-n-drop wrong filetype or file-size, where the errors are overlayed on the input.

The code I'm using after multiple "hack and fail" is below, code is modified to hide unrelated features (Edited):

<form action="/my-submission-path" class="needs-validation" method="post" enctype="multipart/form-data" id="formCreate" novalidate>
    <div class="row">
        <div class="col-md-2 mb-4">
            <div class="md-form">
                <div class="file-field pt-2">
                    <div class="file-upload-wrapper z-depth-1-half mb-4">
                        <input class="file-upload" type="file" accept="image/*" name="back_cover" id="back_cover" data-height="200" data-max-file-size="2M" data-default-file="Image" required>
                    </div>
                    <div class="invalid-feedback">Required</div>
                </div>
                <label for="back_cover" class="text-light-blue-grey mb-2 active">Back Cover<span class="text-danger">*</span>
                    <a class="text-primary px-2" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="{{ __("Recommended dimensions: 512 pixels x 910 pixels portrait image.") }}">
                        <span><i class="fas fa-question fa-sm"></i></span>
                    </a>
                </label>
            </div>
        </div>
    </div>

    <div class="row">
        <div class="col-lg-4 col-sm-6 mb-4">
            <div class="md-form">
                <input type="email" class="text-primary form-control pt-2" id="email" name="email" autocomplete="new" required>
                <label for="email" class="text-light-blue-grey mb-2">Email Address<span class="text-danger">*</span></label>
                <div class="invalid-feedback">Please enter a valid email.</div>
            </div>
        </div>
    </div>

    <div class="row">
        <div class="col-md-6">
            <button type="button" class="btn imano-light-gradient btn-rounded btn-create" id="submitButton" data-toggle="modal" data-target="#confirmCreateDialog">
                <span class="spinner-border spinner-border-sm btn-progress" role="status" aria-hidden="true"></span>
                <span>Create</span>
            </button>
        </div>
    </div>
</form>

I'm submitting the form data with ajax after the the confirmation dialog is hidden by confirmation. My submission JS script:

$(".file-upload#banner").file_upload({
    allowedFileExtensions: ["png", "jpg", "jpeg"],
    messages: {
        remove: "",
        error: "Ooops, something went wrong."
    }
});

<script type="text/javascript">
$("#confirmCreateDialog .btn-confirm").on("click", function (event) {
    event.preventDefault();

    $("#confirmCreateDialog").one("hidden.bs.modal", function (e) {
        e.preventDefault();

        let form = document.getElementById("formCreate");
        form.classList.remove("was-validated");

        if (form.checkValidity() === false) {
            form.classList.add("was-validated");
            e.stopPropagation();
            return;
        }
        $(".is-invalid").removeClass("is-invalid");

        $("#submitButton").prop("disabled", true).find("span:last").text("Creating...");

        let data = new FormData($(form)[0]);

        $.ajax({
            type: "POST",
            dataType: "json",
            data: data,
            cache: false,
            processData: false,
            contentType: false,
            enctype: "multipart/form-data",
            context: this,
            url: $("#formCreate").attr("action"),
            success: function () {
                $("#successDialog .dialog-message").html("<p>Success message here.</p>");
                $("#successDialog").one("shown.bs.modal", function () {
                    window.location.href = "./"; //Go one step back.
                }).modal("show");
            },
            error: function (xhr) {
                let response = xhr.responseJSON;
                if (xhr.status === 422) {
                    showInvalidElements(form, response.errors);
                } else {
                    const message = craftErrorMessage(response);

                    $("#errorDialog .dialog-message").html(message);
                    $("#errorDialog").modal("show");
                }
            },
            complete: function () {
                $("#submitButton").prop("disabled", false).find("span:last").text("Create");
            },
        });
        form.classList.add("was-validated");
        e.stopImmediatePropagation();
    }).modal("hide");
});
</script>

Anna Morawska staff answered 6 years ago

HI @refreshcreativemedia,

unfortunately, drag and drop plugin doesn't have this functionality - but we will add this to the list of ideas. For now, to add custom validation you can try something like this:

 <style>
    .was-validated .file-upload-wrapper+.invalid-feedback {
      display: block
    }
  </style>

</head>

<body>
  <form class="needs-validation" novalidate>
    <div class="col-md-2 mb-4">
      <div class="md-form">
        <div class="file-field pt-2">
          <div class="file-upload-wrapper z-depth-1-half mb-4">
            <input class="file-upload" type="file" name="back_cover" id="back_cover" data-height="200"
              data-max-file-size="2M" data-default-file="Image" required />

          </div>
          <div class="invalid-feedback">Required</div>
        </div>
        <label for="back_cover" class="text-light-blue-grey mb-4 active">Back Cover
          <span class="text-danger">*</span></label>
      </div>
    </div>
    <button type="submit" class="btn">Submit</button>
  </form>

  <script type="text/javascript">
    (function () {
      'use strict';
      window.addEventListener('load', function () {
        // Fetch all the forms we want to apply custom Bootstrap validation styles to
        var forms = document.getElementsByClassName('needs-validation');
        // Loop over them and prevent submission
        var validation = Array.prototype.filter.call(forms, function (form) {
          form.addEventListener('submit', function (event) {
            if (form.checkValidity() === false) {
              event.preventDefault();
              event.stopPropagation();
            }
            form.classList.add('was-validated');
          }, false);
        });
      }, false);
    })();

    $('.file-upload').file_upload();
  </script>

refreshcreativemedia pro commented 5 years ago

This works, however, if any other item on the form is invalid, the file input shows invalid as well.


Magdalena Dembna staff premium commented 5 years ago

Can you share code snippet with your implementation of this solution? It'll be much easier to spot a problem.


refreshcreativemedia pro commented 5 years ago

@Magdalena Dembna I've edited my original question to include the latest code.


Magdalena Dembna staff premium commented 5 years ago

What about javascript code and the rest of the form? I need to reproduce your case and it's not possible with only file upload input.


refreshcreativemedia pro commented 5 years ago

@Magdalena Dembna Please check my updated question.


refreshcreativemedia pro commented 5 years ago

Any update on this, please?


Magdalena Dembna staff premium commented 5 years ago

Hm, your code doesn't work for me so I'm guessing I'm still missing a piece of it - so I cannot workout a clear solution. Take a look at this code snippet here: https://mdbootstrap.com/snippets/jquery/piotr-glejzer/656100 as it contains some kind of file input validation. Does form.checkValidity() return false for incorrect file input? If not you may have to define custom logic to validate it.


refreshcreativemedia pro commented 5 years ago

@Magdalena Dembna Check this snippet: https://mdbootstrap.com/snippets/jquery/refreshcreativemedia/810780

Input validation for Drag'n'Drop works fine, but when another input on the form is invalid, the invalid-feedback element for the DnD file input is shown as well.

In other words, the validation error message is always shown when whenever the form has the class "was-validated".

I want this shown <div class="invalid-feedback">Required</div> only when below is invalid:<input class="file-upload" type="file" name="back_cover" id="back_cover" data-height="200" data-max-file-size="2M" data-default-file="Image" required />

Meaning when no file is picked.

Something like this .was-validated .file-upload-wrapper(that has an invalid child input element)+.invalid-feedback { display: block }


refreshcreativemedia pro commented 5 years ago

If I move the validation message up next to the file input and changed the CSS to below, it works, but it makes the validation message sits at the wrong place:

.was-validated .file-upload:invalid+.invalid-feedback { display: block }


refreshcreativemedia pro commented 5 years ago

To make the above method work, I had to set the invalid-feedback element position to absolute and bottom to -2.25rem and now it only shows when the file input is actually invalid.


Magdalena Dembna staff premium commented 5 years ago

I was playing with your example for a while and I see the problem. I will report this problem to our team and if it is alright for now, please use your fix and I hope some examples for validating file input will be provided in the future.


Please insert min. 20 characters.

FREE CONSULTATION

Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.

Status

Answered

Specification of the issue
  • User: Pro
  • Premium support: No
  • Technology: MDB jQuery
  • MDB Version: 4.7.7
  • Device: All
  • Browser: Google Chrome
  • OS: OS X
  • Provided sample code: No
  • Provided link: No