Mori
Mori

Reputation: 6780

Reset form invalid values

Here's a sample form:

var form = document.querySelector('form');

function detectChange() {
  var inputs = form.querySelectorAll('input');
  for (var input of inputs) {
    if (input.value != input.defaultValue) {
      return true;
    }
  }
}

form.querySelector('button').addEventListener('click', function() {
  if (detectChange() && confirm('Are you sure you want to reset?')) {
    form.reset();
  }
});
<form>
  <input type="number">
  <input type="number" value="7">
  <button type="button">Reset</button>
</form>

I'd like the reset button to work even if the user enters non-numeric values.

Upvotes: 6

Views: 2780

Answers (8)

Anil Kumar Moharana
Anil Kumar Moharana

Reputation: 374

<form>
  <input type="number">
  <input type="number">
  <button type="button" onclick="resetData()">Reset</button>
</form>


function resetData(){
    var y = document.querySelectorAll('input,textarea');
        for (var i= 0; i < y.length; i++) {
        var id =y[i].id;
        if(y[i].value !=''&&y[i].value!= 'undefined'){
        document.getElementById(id).value="";
        }
        } 
}

Upvotes: -1

Shidersz
Shidersz

Reputation: 17190

One alternative to approach your goal is using a set of standard pseudo-classes, like :invalid and :valid. Also note, we are going to use some array methods and features, like Array.some() and the Spread Syntax:

var form = document.querySelector('form');

function detectChange()
{
    var invalids = form.querySelectorAll('input:invalid');
    var valids = form.querySelectorAll('input:valid');
    return (invalids.length > 0) || [...valids].some(i => i.defaultValue !== i.value);
}

form.querySelector('button').addEventListener('click', function()
{
    if (detectChange() && confirm('Are you sure you want to reset?'))
        form.reset();
});
<form>
  <input type="number">
  <input type="number">
  <input type="number" value="7">
  <button type="button">Reset</button>
</form>

If you are able to use placeholders on your inputs, then another possible solution is to use the CSS pseudo-class :placeholder-shown. However, give a check to the browser's support to be sure it will fit your need. Note it is experimental and is not recommended to use on production. Then, you can use the next selector:

input:not(:placeholder-shown)

to get all inputs where the placeholder is not shown, i.e, all not-empty inputs, and re-implement your code something like this:

var form = document.querySelector('form');

function detectChange()
{
    var inputs = form.querySelectorAll(
        'input:not([value]):not(:placeholder-shown), input[value]'
    );
    return [...inputs].some(i => !i.defaultValue || i.defaultValue !== i.value);
}

form.querySelector('button').addEventListener('click', function()
{
    if (detectChange() && confirm('Are you sure you want to reset?'))
        form.reset();
});
<form>
  <input type="number" placeholder="Insert a number">
  <input type="number" placeholder="Insert a number">
  <input type="number" value="7" placeholder="Insert a number">
  <button type="button">Reset</button>
</form>

Upvotes: 2

connexo
connexo

Reputation: 56753

Simply use a button type="reset", and attach an event listener on the form that listens for reset events.

The main problem with your code is that your detectChange() function will never work for invalid input because browsers will always return the empty string for any non-numeric input if you ask for the value. This is by the specification. Check https://stackoverflow.com/a/18853513/3744304

The solution to fix this has been suggested originally in @naga - elixir - jar's answer. Edited my answer a) to make it working answer and b) to put it all together in a concise, ES6 way.

const form = document.querySelector('form');

form.addEventListener('reset', (event) => {
  if (detectChange() && !confirm('Are you sure you want to reset?')) {
    event.preventDefault();
  }
});

function detectChange() { 
  return [...form.querySelectorAll('input')].some(el => el.validity.badInput || el.value !== el.defaultValue); 
};
<form>
  <input type="number" value="87">
  <input type="number">
  <button type="reset">Reset</button>
</form>

Upvotes: 0

1565986223
1565986223

Reputation: 6718

If you look at the input DOM object, there is a property badInput under validity object whose value is a boolean. For numeric entry or empty field, it's false. However it's true for non numeric values, which can interestingly be used in your case.

Note: Tested only on firefox and safari

input
|  +-- ...
|  +-- validity
|  |   +-- badInput
|  |   +-- ...
|  +-- ...

Using this knowledge you can modify the function to check for badInput to achieve what you want with minimal tweaking.

// non-empty and non default
if ((input.value && input.value != input.defaultValue) || input.validity.badInput)

var form = document.querySelector('form');

function detectChange() {
  var inputs = form.querySelectorAll('input');
  for (var input of inputs) {
    if ((input.value && input.value != input.defaultValue) || input.validity.badInput) {
      return true;
    }
  }
}

form.querySelector('button').addEventListener('click', function() {
  if (detectChange() && confirm('Are you sure you want to reset?')) {
    form.reset();
  }
});
<form>
  <input type="number">
  <input type="number" value="11">
  <button type="button">Reset</button>
</form>

Update:

update to cover:

inputs with non-empty default values

Upvotes: 10

webgodo
webgodo

Reputation: 81

Just set an event listener for onkeydown, onpaste of the input element:

const inputs = document.querySelectorAll('input[type=number]')
inputs.forEach((el) => el.onkeydown = el.onpaste = (event) => event.target.dataset.receivedEntry = 1)

Then check for the input.dataset.receivedEntry in detectChange:

function detectChange () {
  const inputs = form.querySelectorAll('input');
  for (var input of inputs) {
    if (input.dataset.receivedEntry) {
      return true;
    }
  }
}

Upvotes: 0

fila90
fila90

Reputation: 1459

var form = document.querySelector('form');
var btn = form.querySelector('button');
var inputs = form.querySelectorAll('input');
btn.disabled = true;
btn.addEventListener('click', function() {
  if (confirm('Are you sure you want to reset?')) {
    form.reset();
    btn.disabled = true;
  }
});

for (var input of inputs) {
  input.addEventListener('keypress', detectSpace)
  input.addEventListener('input', handleChange);
}

function handleChange(e) {
  var disabled = true;
  for (var input of inputs) {
    input.value = input.value.trim()
    if (input.value) {
      disabled = false
    }
  }
  btn.disabled = disabled
}

function detectSpace(e) {
  if (e.keyCode == 32) {
    e.preventDefault();
    return false
  }
}
<form>
  <input type="number">
  <input type="number">
  <button type="button">Reset</button>
</form>

will this work? it prevents user from pasting into number by trimming the value inside input type="number".

detectSpace is there because in firefox hitting space will delete the number because is not a valid one.

Upvotes: -1

Syed Mehtab Hassan
Syed Mehtab Hassan

Reputation: 1337

Loop over the input fields and manually set values = "";

var form = document.querySelector('form');

function detectChange() {
  var inputs = form.querySelectorAll('input');
  for (var input of inputs) {
    input.value = "";
  }
}

form.querySelector('button').addEventListener('click', function() {
  if (confirm('Are you sure you want to reset?')) {
    detectChange(); 
  }
});
<form>
  <input type="number">
  <input type="number">
  <button type="button">Reset</button>
</form>

Upvotes: 0

Amy
Amy

Reputation: 4032

Change this:

<button type="button">Reset</button>

TO

<input type="reset" value="Reset"/>

Upvotes: 1

Related Questions