-1

I have a form.

The form has inputs and number fields.

I want to check for every gesture that the fields are filled in so I can enable/disable the submit button.

I tried with keydown/up but that doesn't help with the number fields.

I tried with onchange which generally works but I have weird effects like you have to click outside the input to trigger the event or if you fill in the fields and then delete one they are not rechecked so you can click the submit button without the form being properly filled in.

No I can't use 'required' because I'm not actually submitting the form -- it's all through js

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
  • Why not just check for completeness after they click "submit"? – mykaf Jul 05 '23 at 13:19
  • Or, if you don't actually use the submit event, you can manually check for required fields with `form.reportValidity()` – mykaf Jul 05 '23 at 13:28

3 Answers3

0

Use input: Only ones not triggering input are the buttons

const form1 = document.getElementById("form1")
form1.addEventListener("input", (e) => {
  console.log(e.target.tagName, e.target.type ? e.target.type : "");
});
form1.addEventListener("submit", (e) => {
  e.preventDefault();
  console.log("form1 submitted");
});
[type=image] {
  height: 30px;
}
<form id="form1">
  <input type="number" />
  <input type="date" />
  <input type="checkbox" />
  <input type="radio" name="a" />
  <input type="radio" name="a" />
  <input type="text" />
  <input type="password" />
  <textarea></textarea>
  <input type="button" value="click" />
  <input type="submit" />
  <input type="image" src="https://www.freeiconspng.com/uploads/red-submit-button-png-2.png" />
  <select>
    <option value="">Please select</option>
    <option value="1">One</option>
    <option value="2">Two</option>
  </select>
  <select multiple>
    <option value="">Please select one or more</option>
    <option value="1">One</option>
    <option value="2">Two</option>
  </select>
</form>

You CAN use required

document.getElementById("form1").addEventListener("submit", (e) => {
  e.preventDefault(); 
  /* here the form is valid and will not submit */
});
[type=image] {
  height: 30px;
}
<form id="form1">
  <input type="number" required min=1 max=10/>
  <input type="date" required/>
  <input type="checkbox" required/>
  <input type="radio" name="a" required/>
  <input type="radio" name="a" required/>
  <input type="text" required/>
  <input type="password" required/>
  <textarea required></textarea>
  <select required>
    <option value="">Please select</option>
    <option value="1">One</option>
    <option value="2">Two</option>
  </select>
  <select multiple required>
    <option value="">Please select one or more</option>
    <option value="1">One</option>
    <option value="2">Two</option>
  </select>
  <input type="button" value="click" />
  <input type="submit" />
  <input type="image" src="https://www.freeiconspng.com/uploads/red-submit-button-png-2.png" />

</form>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
0

Listen for any "click" or "keyup" Event on <form>

In the example below, all of the <input> have the same [name] value. If for some reason you can't have the same [name] value for all <input>s, there's plenty of other ways to get all <input>s into an Array:

Alternate Ways to Collect <input type="number">

const arrayOfNumberInputs = [...document.querySelectorAll('[type="number"]')];

const arrayOfFormControls = Array.from(this.elements).filter(fc => fc.type === "number");

Example

Details are Commented in Example

/**
 * Register the <form> to listen for the "click" and 
 * "keyup" events.
 */
document.forms.UI.onclick = allFields;
document.forms.UI.onkeyup = allFields;

// Event handler passes the Event Object by default
function allFields(event) {
  /**
   * Collect all input[name="number"] into a HTMLCollection
   * then convert that into an Array.
   */
  const numbers = Array.from(this.elements.number);
  /**
   * .every() will return true if every
   * input[name="number"] has a .value
   */
  let done = numbers.every(input => input.value.length > 0);
  // If all input[name="number"] have a value...
  if (done) {
    // ...disable <button>...
    this.elements.button.disabled = false;
  } else {
    // ...otherwise disable <button>
    this.elements.button.disabled = true;
  }
}
*,
*::before,
*::after {
  box-sizing: border-box;
}

:root {
  font: 2.25ch/1.154 'Segoe UI';
}

html,
body {
  width: 100%;
  min-height: 100%;
  margin: 0;
  padding: 0;
}

body {
  display: flex;
  flex-flow: column nowrap;
  justify-content: center;
  align-items: center;
}

form {
  width: max-content;
  margin: 0 auto;
}

fieldset {
  display: flex;
  flex-flow: column nowrap;
  justify-content: center;
  width: max-content;
  border-radius: 4px
}

legend {
  margin-bottom: 4px;
}

input,
button {
  display: inline-block;
  font: inherit;
  font-size: 100%;
  margin: 3px 0
}

input {
  font-family: Consolas;
  text-align: center;
}

button {
  align-self: flex-end;
  width: 8ch;
  margin-top: 6px;
  padding: 4px 8px 6px;
  border-radius: 4px;
  font-variant: small-caps;
  cursor: pointer;
}

[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}
<form id="UI">
  <fieldset>
    <legend>Complete All Fields</legend>
    <!-- Give all <input>s the same [name] value. -->
    <input name="number" type="number" min="-100" max="100" placeholder="-100 - 100">
    <input name="number" type="number" min="-100" max="100" placeholder="-100 - 100">
    <input name="number" type="number" min="-100" max="100" placeholder="-100 - 100">
    <input name="number" type="number" min="-100" max="100" placeholder="-100 - 100">
    <button name="button" disabled>Done</button>
  </fieldset>
</form>
zer00ne
  • 41,936
  • 6
  • 41
  • 68
-1

I hope this is helpful

Check any changed or keyup one by one:

// get all input, textarea, select box and ...
const all_input = document.querySelectorAll('input, select, textarea');
// set event
for(const item of all_input) {
    item.onchange = function(e) {checkvalidation(item)}
    item.onkeyup = function(e) {checkvalidation(item)}
}

// check validations function
function checkvalidation(obj) {
    console.log(obj,obj.value);
    // test
    if (!obj.value) {
        item.style.backgroundColor = 'red';
        alert('your error text');
    }
}

Check all together

// get all input, textarea, select box and ...
const all_input = document.querySelectorAll('input, select, textarea');
// check value
for(const item of all_input) {
    if (!item.value) {
        item.style.backgroundColor = 'red';
        alert('your error text');
    }
}

Also you can set onclick on submit button and call your validation function and after that submit form with your own code