Build a Customer Complaint Form - checkValidity doesn't work as intended

Tell us what’s happening:

I am having trouble with the checkValidity(). It worked when I was doing it inside the if(name == “full-name”"){Inhere}, but now it doesnt work. I was wondering why it is the case. The pattern doesn’t work anymore. For the Full-name, whenever the first character is included, it works and make it “true” (while there is no pattern), then it won’t make it true ever again. Could someone explain it to me ?

EDIT : It looks like it’s the same for some other. I have tried including if(name == “quantity”){set custom alert etc…}
then it will only make true if the very first input is true, all the other become false

EDIT 2 : Adding “ && !isTrue” to the setCustomValidity makes it so if the validity doesn’t turn false, it will keep being true up until false. Then when it’s false, it will never become true again.

EDIT 3 : Not having any setCustomValidity() makes it works. Why is that ?

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Customer Complaint Form</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
</head>

<body>
    <h1>Complaint Form</h1>
    <form id="form">
        <fieldset id="personal-info">
            <div>
                <label for="full-name">Full Name:</label>
                <input type="text" id="full-name" name="full-name" placeholder="John Doe" required>
                <!-- pattern ="\w+\s\w+" -->
            </div>

            <div>
                <label for="email" type="email">Email Address:</label>
                <input type="email" id="email" pattern=".+@.+\..+" name="email" placeholder="example@domain.com" required>
            </div>
        </fieldset>
        <hr>
        <fieldset id="product-info">
            <div>
                <label for="order-no">Order No:</label>
                <input type="text" id="order-no" name="order-no" placeholder="2024######" pattern="2024\d{6}" required>
            </div>
            <div>
                <label for="product-code">Product Code:</label>
                <input type="text" id="product-code" name="product-code" placeholder="XX##-X###-XX#" pattern="[a-zA-Z]{2}\d{2}-[a-zA-Z]\d{3}-[a-zA-Z]{2}\d" required>
            </div>
            <div>
                <label for="quantity">Quantity:</label>
                <input type="number" id="quantity" name="quantity" min="1" required>
            </div>
        </fieldset>

        <fieldset id="complaints-group">
            <legend>Complaint Reason:</legend>
            <div>
                <input type="checkbox" id="damaged-product" name="complaint" value="damaged-product">
                <label for="damaged-product">Damaged Product</label>
            </div>

            <div>
                <input type="checkbox" id="nonconforming-product" name="complaint" value="nonconforming-product">
                <label for="nonconforming-product">Nonconforming Product</label>
            </div>

            <div>
                <input type="checkbox" id="delayed-dispatch" name="complaint" value="delayed-dispatch">
                <label for="delayed-dispatch">Delayed Dispatch</label>
            </div>

            <div>
                <input type="checkbox" id="other-complaint" name="complaint" value="other">
                <label for="other-complaint">Other</label>
            </div>
        </fieldset>

        <fieldset id="complaint-description-container">
            <legend>Description of Complaint Reason</legend>
            <textarea placeholder="Describe the reason of your complaint in at least 20 characters"
                name="complaint-textarea" id="complaint-description"></textarea>
        </fieldset>

        <fieldset id="solutions-group">
            <legend>Desired Solution</legend>
            <input type="radio" name="solutions" id="refund" value="refund">
            <label for="refund">Refund</label>

            <input type="radio" name="solutions" id="exchange" value="exchange">
            <label for="exchange">Exchange</label>

            <input type="radio" name="solutions" id="other-solution" value="other">
            <label for="other-solution">Other</label>
        </fieldset>

        <fieldset id="solution-description-container">
            <legend>Description of Desired Solution</legend>
            <textarea placeholder="Describe the desired solution to your issue in at least 20 characters"
                name="solution-textarea" id="solution-description"></textarea>
        </fieldset>
        <div id="btn-container">
            <button type="submit" id="submit-btn">Submit</button>
            <span id="message-box" aria-live="polite"></span>
        </div>

    </form>

    <script src="script.js"></script>
</body>

</html>
/* file: styles.css */
* {
    box-sizing: border-box;
}

h1 {
    text-align: center;
}

#form {
    max-width: 70%;
    margin: auto;
    border-radius: 10px;
    box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
    padding: 10px;
}

input {
    border-color: rgb(118, 118, 118);
}

#personal-info input, #product-info input {
    width: 100%;
    margin-bottom: 10px;
}


fieldset {
    margin-bottom: 10px;
    border-radius: 5px;
    border-color: rgb(118, 118, 118);
}

textarea {
    width: 100%;
    border-color: rgb(118, 118, 118);
}

#btn-container {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

#submit-btn, #clear-btn {
    margin: 10px 15px 0;
}

.false{
    border-color: red;
}
.true{
    border-color: green;
}
/* file: script.js */
const inputs = document.querySelectorAll("input");

inputs.forEach(input => input.addEventListener("input", (e) => validateForm(e)));

function validateForm(e){
  let target = e.target
  let name = target.name;
  let isTrue = target.checkValidity();
  console.log(isTrue)
  let isError = false;
  if (name == "full-name"){
    target.setCustomValidity("You must enter your Full Name.")
  }
  else if(name == "email"){
    target.setCustomValidity("You must enter a valid email !")
  }
  else if(name == "order-no"){
    target.setCustomValidity("Your order number is not correct.")
  }
  
  if(!isTrue){
    isError = true;
    target.reportValidity()
    target.classList.remove("true")
    target.classList.add("false")
    return
  }
  isError = false;
  target.classList.remove("false")
  target.classList.add("true")
  return
    

}

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0

Challenge Information:

Build a Customer Complaint Form - Build a Customer Complaint Form

Hi @Mahoue,

Try testing your validation using the change event in your listeners instead of the input event.

Happy coding!

Thanks, it works. But now, the reportValidity() only works when i submit the forms. Not when i leave the box. Could you explain to me the difference of input or change ?

Also, it is still secretely false D:

The thing glow up green as it should but it still point the reportValidity()

The change event fires when the input loses focus and the input event fires when any character is entered.

But this reference probably explains it better:

Events: change, input, cut, copy, paste

Please post your updated code if you still need help.

For some reasons, i found out that the "setCustomValidity” needs to be reseted as an empty string for the whole thing to work… what a bummer. I don’t know why that is but okay

Hmmm…maybe review this theory lecture. There’s a bit in there on how to use checkValidity, reportValidity, and setCustomValidity together. Maybe that will help?

Understanding Form Validation - What Are Some Ways to Validate Forms Using JavaScript? | Learn | freeCodeCamp.org

I am having a great deal of troubles with checkboxes and radios input as they contain the “other” option. This is too much of code, I would love to narrow it down but don’t know where to start.

Since it’s a load of code, also repeating itself to check if statements, is there anyway for me to get it done more efficiently ?

/* file: script.js */
const inputs = document.querySelectorAll('input[type="text"], input[type="email"], input[type="number"]')
const checkBox = document.querySelectorAll('input[type="checkbox"]');
const checkBoxTextarea = document.querySelector("#complaint-description");
const checkBoxFieldset = document.querySelector("#complaint-description-container");
const radios = document.querySelectorAll('input[name="solutions"]')
const radioTextarea = document.getElementById("solution-description");
const radiosFieldset = document.getElementById("complaint-description-container");

const validObj = {
  "full-name": false,
  "email": false,
  "order-no": false,
  "product-code": false,
  "quantity": false,
  "complaints-groups": false,
  "complaint-description": false,
  "solutions-group": false,
  "solution-description": false
};

checkBoxFieldset.classList.add("hide");

inputs.forEach(input => input.addEventListener("change", (e) => validateForm(e)));
checkBox.forEach(box => box.addEventListener("input", (e) => validateForm(e)))
checkBoxTextarea.addEventListener("change", (e) => validateForm(e))
radios.forEach(radio => radio.addEventListener("input", (e) => validateForm(e)))

function validateForm(e){
  let targeted = e.target;
  let name = targeted.name;
  //resets v
  targeted.setCustomValidity("");
  checkBoxFieldset.classList.add("hide");
  radiosFieldset.classList.add("hide");
  //resets ^
  if(targeted.checkValidity() && validObj.hasProperty){
      validObj[name] = true;
      targeted.classList.remove("red");
      targeted.classList.add("green");
    }
  else if(!targeted.checkValidity() && validObj.hasProperty){
      if (name == "full-name"){
    targeted.setCustomValidity("You must enter your full name.")
    }
    else if(name == "email"){
      targeted.setCustomValidity("You must enter a valid email !")
    }
    else if(name == "order-no"){
      targeted.setCustomValidity("Your order number is not correct.")
    }
    else if(name == "product-no"){
      targeted.setCustomValidity("Your thingy must be the good product thingy.")
    }
    else if(name == "quantity"){
      targeted.setCustomValidity("Your thingy must be anumber tho.")
    }
    validObj[name] = false;
    targeted.reportValidity();
    targeted.classList.add("red");
    targeted.classList.remove("green");
  }
  //This is for box
    for (let box of checkBox){
      if(box.checked){
        console.log(box.value);
        validObj["complaints-groups"] = true;
        if(box.value.includes("other")){
          checkBoxFieldset.classList.remove("hide");
          validObj["complaints-groups"] = false;
        }
      }
    }
    if(!checkBoxFieldset.classList.contains("hidden") && checkBoxTextarea.value.length>=20 ){
      checkBoxFieldset.classList.remove("red")
      checkBoxFieldset.classList.add("green")
      validObj["complaints-groups"] = true;
      validObj["complaint-description"] = true
    }
    else if(!checkBoxFieldset.classList.contains("hidden")&& checkBoxTextarea.value.length<20){
      checkBoxFieldset.classList.remove("green")
      checkBoxFieldset.classList.add("red");
      validObj["complaints-groups"] = false;
      validObj["complaint-description"] = false
    }
  
  else if(name == "solutions"){
    for (let radio of radios){

    }
  }
  else{
    console.log("error, not in the form")
  }
  
  console.log(validObj)
  return validObj
}

This is one of those projects that you’ll probably go back and tweak a good bit after you get the tests to pass. I did. Don’t worry about efficiency right now…just work on making sure you are meeting the requirements in all of the user stories to get the tests to pass.

Do you have a specific question about your code?

Edit: How do you know your form is being submitted? If I just click the “Submit” button without doing anything else, nothing happens. Shouldn’t the border color change for invalid elements?