Foreach validation bases validation on last input in foreach list

Viewed 59

I'm building a multi-step form in jQuery and Laravel. Each step contains a few input fields, and a textarea, in this case, Step 1 contains 3 inputs, and 1 textarea, a total of 4 fields, 1 of them is optional and isn't required to proceed to Step 2.

I have a "Next Step" button, which once clicked, will find all fields within a <div> and check to see if they're empty, it will only proceed to the next step if all required fields aren't empty.

However, my code only appears to be getting the very last foreach item, regardless of whether it's required, I suspect this is a common issue on Stack Overflow, and I'm fairly new to this.

My JS code:

let currentStep = 1
    var isValid;
    function validateStep() {
      runValidation()
    }

    function goBackStep() {
      $('#pills-tab-' + currentStep).removeClass('active')
      $('#pills-' + currentStep).hide().removeClass('show')
      if (currentStep > 0) currentStep--
      $('#pills-' + currentStep).show().addClass('show')
      $('#pills-tab-' + currentStep).addClass('active')
    }

    function runValidation() {
      $('.js__step-' + currentStep).find('input, textarea, select').each(function() {
        var element = $(this)

        if (element.val() == "") {
          element.removeClass('is-valid').addClass('is-invalid')
          isValid = false;
        } else {
          element.removeClass('is-invalid').addClass('is-valid')
          isValid = true;
        }

      })
      if (isValid) {
        $('#pills-tab-' + currentStep).removeClass('active')
        $('#pills-' + currentStep).hide().removeClass('show')
        currentStep++
        $('#pills-' + currentStep).show().addClass('show')
        $('#pills-tab-' + currentStep).addClass('active')
      }
    }

From the above code, I'm using Bootstrap 4 tabs, and every time the next step button is clicked, I increment a variable in order to show the next tab without repeating blocks of code, the check at the end: isValid should only become true once ALL required fields are valid, rather than only the last field.

I can add a && element.prop('required') in the first checks, I've just missed this bit out for now.

It should also reset the validation when going back to a step just in case it thinks it's valid.

What am I missing to check the validation of ALL required fields, rather than just the last one?

Many thanks!

1 Answers

On each iteration you are redefining isValid. This means that it only checks the last value. To fix this, you can set isValid to true at the beginning and only update it if an input field is empty. This will mean that if any of the fields are empty, it will fail. Even if it is checked before a completed field.

function runValidation() {
    isValid = true;
    $('.js__step-' + currentStep).find('input, textarea, select').each(function () {
        var element = $(this)

        if (element.val() == "") {
            element.removeClass('is-valid').addClass('is-invalid')
            isValid = false;
        } else {
            element.removeClass('is-invalid').addClass('is-valid')
        }
    });

    if (isValid) {
        $('#pills-tab-' + currentStep).removeClass('active')
        $('#pills-' + currentStep).hide().removeClass('show')
        currentStep++
        $('#pills-' + currentStep).show().addClass('show')
        $('#pills-tab-' + currentStep).addClass('active')
    }
}
Related