How to only allow unique answers in a number type input in a form

I have number type inputs in a form, and I have already limited their value to be from 1-14. However, I want each number to be unique. That is, if they already answered “1” to an input, they cannot input 1 again. Can someone help me start a function that does this? Thank you!

1 Like

You can use some javascript to achieve this.

Imaginin that you have an HTML like this:

<form id="myForm">
  <input type="number" min="1" max="14" class="unique-number">
  <input type="number" min="1" max="14" class="unique-number">
  <input type="number" min="1" max="14" class="unique-number">
  <button type="submit">Submit</button>
</form>

The javascript would be something like this:

document.getElementById('myForm').addEventListener('submit', function(event) {
  // Here you get all unique-number inputs.
  var inputs = Array.from(document.getElementsByClassName('unique-number'));
  
  // After that you map each input.
  var values = inputs.map(function(input) {
    return parseInt(input.value, 10);
  });

  // An if to know if there are any duplicate values.
  if (hasDuplicates(values)) {
    event.preventDefault();
    alert("Please ensure all numbers are unique.");
  }
});

function hasDuplicates(array) {
  var valueCount = {};
  
  for (var i = 0; i < array.length; i++) {
    if (valueCount[array[i]]) {
      return true;
    }
    valueCount[array[i]] = true;
  }

  return false;
}

This will prevent the form from being submitted if any two ‘unique-number’ inputs have the same value.
Also this only prevent the form submission, it doesn’t prevent the user from entering duplicate values into the inputs.

If you want to do something like that you can add an event listener to each input field that fires every time the field changes.
And your javascript code will be something like:

var inputs = Array.from(document.getElementsByClassName('unique-number'));

// Here you add a 'input' event listener to each input.
inputs.forEach(function(input, index) {
  input.addEventListener('input', function() {
    checkForDuplicates(index);
  });
});

function checkForDuplicates(changedIndex) {
  var otherValues = inputs.filter(function(input, index) {
    return index !== changedIndex;
  }).map(function(input) {
    return parseInt(input.value, 10);
  });

  // And here you make an "if" to see if the value that has been entered already exists, if it exists than clear the field.
  if (otherValues.includes(parseInt(inputs[changedIndex].value, 10))) {
    inputs[changedIndex].value = '';
    alert('Duplicate values are not allowed.');
  }
}

4 Likes

Hello! Thank you so much for your help, the first code is exactly what I was looking for!! Do I have to include the function hasDuplicates() into my submit button for it to work? When I added this code to mine it doesn’t seem to work. It should be noted that I also have some code for onInput and onInvalid in the head of my tag. So sorry for the extra question, thank you so much!

It doesn’t need to be included in your submit button directly. You just need to call it within the form’s submit event.
It should work as long as it’s added within a <script> tag (I prefer to put at the end of the body tag)

Hello, again thank you for your help! I am still not able to use this code the way I want it to. I declared my inputs in this way, do you think this is interfering with the code you provided? Thank you!

<label><input type="number" name="num"  min="1" max="14" autocomplete="off" 
oninput="this. Value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1'); this.setCustomValidity('')" 
oninvalid="this.setCustomValidity('Please enter a number between 1 and 14')" 
class="unique">  <span>Harriet Tubman</span></label><be>
1 Like

Hey again, for whatever reason I followed what you said and added the script tag at the end of the body tag and it worked, thank you so much!!

1 Like

Hi again! It seems like there is an issue with this code in that it only works once all input fields have been filled. Otherwise, the error just keep coming up. Is there a way to only make an array of inputted values instead of all POSSIBLE inputs?

Hey there!

Can I see your code to give you better instructions?

Thank you for your help! I was thinking of making a list where everytime an input is given in the number box, it appends that element to this list. That way we only iterate through values that have actually been answered. I also noticed that before I modified the array (how you originally wrote it), the left column was independent in that it didn’t matter what the right column had, the function responded to what the left column had as inputs. That is to say, if all the left column was unique and full, but the right column had mistakes or missing values, it would still let you submit.
However, the right column needed both the left and right columns to be completely full and unique in order to submit. Do you think it has to do with the div?

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>replit</title>
  <style>
    h2{
  font-size: 40px;
}

h3{
  font-size: 35px
}



input[type="number"] {
  width: 75px;
  height: 70px;

  border-radius: 4pt;
  -moz-appearance: textfield;
  font-weight: bold;
  font-size: 30px;
  margin-top: 25px;
}
input[type="number"]::-webkit-inner-spin-button, 
input[type="number"]::-webkit-outer-spin-button { 
  -webkit-appearance: none; 
  margin: 0; 
}

label span{
  line-height: 1.8;
  font-size: 30px;
}

input[type="submit"]{
  display: block;
  background-color: darkgray;
  color: black;
  padding: 12px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-weight: bold;
  font-size: xx-large;
  float: right;
  height: 100px;
  width: 200px;

}

input[type="submit"]:hover {
  background-color: lightgray;
}


* {
  box-sizing: border-box;
}

/* Create two equal columns that floats next to each other */
.col {
  float: left;
  width: 50%;
  
}

.row{
  display:block;
  border-radius: 5px;
  padding: 20px;
}

/* Clear floats after the columns */
.row:after {
  content: "";
  display: table;
  clear: both;
}



  </style>
 
</head>

<body>



  <br>
  <div class="row">
    <div class="col">
      
  <form  id="ballot1" >
    
      <label><input type="number" name="num" min="1" max="14" autocomplete="off" oninvalid="this.setCustomValidity('Please enter a number between 1 and 14')" oninput="this.setCustomValidity('')" class="unique"> <span>Mark Twain</span></label>
<br>
    <label><input type="number" name="num" min="1" max="14" autocomplete="off" oninvalid="this.setCustomValidity('Please enter a number between 1 and 14')" oninput="this.setCustomValidity('')" class="unique"> <span>Bill Gates</span></label>
    <br>

    
     <label><input type="number" name="num"  min="1" max="14" autocomplete="off" oninput="this.value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1'); this.setCustomValidity('')" oninvalid="this.setCustomValidity('Please enter a number between 1 and 14')" class="unique">  <span>Marie Antoniette</span></label>
<br>
    <label><input type="number" name="num"  min="1" max="14" autocomplete="off" oninput="this.value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1'); this.setCustomValidity('')" oninvalid="this.setCustomValidity('Please enter a number between 1 and 14')" class="unique"> <span>Oprah Winfrey</span></label>
    <br>
     <label><input type="number" name="num"  min="1" max="14" autocomplete="off" oninput="this.value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1'); this.setCustomValidity('')" oninvalid="this.setCustomValidity('Please enter a number between 1 and 14')" class="unique">  <span>Natalie Portman</span></label>
<br>
    <label><input type="number" name="num"  min="1" max="14" autocomplete="off" oninput="this.value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1'); this.setCustomValidity('')" oninvalid="this.setCustomValidity('Please enter a number between 1 and 14')" class="unique">  <span>Charles Dickens</span></label>
<br>
    <label><input type="number" name="num"  min="1" max="14" autocomplete="off" oninput="this.value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1'); this.setCustomValidity('')" oninvalid="this.setCustomValidity('Please enter a number between 1 and 14')" class="unique">  <span>Harriet Tubman</span></label><br>
    </div>

    <div class="col">
 <label><input type="number" name="num"  min="1" max="14" autocomplete="off" oninput="this.value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1'); this.setCustomValidity('')" oninvalid="this.setCustomValidity('Please enter a number between 1 and 14')" class="unique"> <span>Thomas Edison</span></label>
<br>
    <label><input type="number" name="num"  min="1" max="14" autocomplete="off" oninput="this.value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1'); this.setCustomValidity('')" oninvalid="this.setCustomValidity('Please enter a number between 1 and 14')" class="unique"> <span>Indiana Jones</span></label>
    <br>
     <label><input type="number" name="num"  min="1" max="14" autocomplete="off" oninput="this.value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1'); this.setCustomValidity('')" oninvalid="this.setCustomValidity('Please enter a number between 1 and 14')" class="unique">  <span>Michael Jordan</span></label>
<br>
    <label><input type="number" name="num"  min="1" max="14" autocomplete="off" oninput="this.value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1'); this.setCustomValidity('')" oninvalid="this.setCustomValidity('Please enter a number between 1 and 14')" class="unique">  <span>Benjamin Franklin</span></label>
    <br>
     <label><input type="number" name="num"  min="1" max="14" autocomplete="off" oninput="this.value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1'); this.setCustomValidity('')" oninvalid="this.setCustomValidity('Please enter an integer between 1 and 14')" class="unique">  <span>Helen Keller</span></label>
<br>
    <label><input type="number" name="num"  min="1" max="14" autocomplete="off" oninput="this.value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1'); this.setCustomValidity('')" oninvalid="this.setCustomValidity('Please enter a number between 1 and 14')" class="unique">   <span>Stephen Hawking</span></label>
<br>
    <label><input type="number" name="num"  min="1" max="14" autocomplete="off" oninput="this.value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1'); this.setCustomValidity('')" oninvalid="this.setCustomValidity('Please enter a number between 1 and 14')" class="unique"> <span>Martin Luther King</span></label><br>
      
    </div>
  </div>
    
  <label><input type="submit"></label> 

  </form>
<be>
<ul id ="ul"></ul>
  
  <script>
let ul=document.getElementById("ul");
  
document.getElementById('myForm').addEventListener('submit', function(event) {
  const list=document.createElement("LI");
  ul.appendChild(list);

  // After that you map each input.
  var values = list. map(function(input)  {
    return parseInt(input.value, 10);
  });

  // An if to know if there are any duplicate values.
  if (hasDuplicates(values)) {
    event.preventDefault();
    alert("Please ensure all numbers are unique.");
  }
});

function hasDuplicates(array) {
  var valueCount = {};
  
  for (var i = 0; i < array.length; i++) {
    if (valueCount[array[i]]) {
      return true;
    }
    valueCount[array[i]] = true;
  }

  return false;
}
     </script>
</body>

</html>

One little thing:

Here

<div class="row">
    <div class="col">
      
  <form  id="ballot1" >

you say that your <form id="ballot1">

But then in your script you wrote this document.getElementById('myForm'). Change myForm to ballot1.

About the second one…
To append the value of each input to the list, you need to get all the inputs from the form and add an event listener for each one…
I think you can get it with this script (remember that I’m changing your entire script so this is a new <script>, backup your code before using it so you can reverse the changes)

<ul id="ul"></ul>

<script>
// First you get the form element
const form = document.getElementById('ballot1');

// After that you get the list element
const ul = document.getElementById('ul');

// Than you listen for form submission
form.addEventListener('submit', function(event) {
  // And you have to prevent the form from actually being submitted
  event.preventDefault();

  // After you get all the number inputs in the form
  const inputs = form.querySelectorAll('input[type="number"].unique');

  // And get the values of the inputs as numbers
  const values = Array.from(inputs).map(input => parseInt(input.value, 10));

  // You need to check if there are any duplicate values
  if (hasDuplicates(values)) {
    alert("Please ensure all numbers are unique.");
  } else {
    // If there are no duplicates, append each value to the list
    values.forEach(value => {
      const li = document.createElement("LI");
      li.textContent = value;
      ul.appendChild(li);
    });
  }
});

function hasDuplicates(array) {
  var valueCount = {};
  
  for (var i = 0; i < array.length; i++) {
    if (valueCount[array[i]]) {
      return true;
    }
    valueCount[array[i]] = true;
  }

  return false;
}
</script>

And about the right and left column, I think it’s not related to the div structure but more likely due to how you’re selecting and validating inputs.

1 Like

I’m having the same issue where only the left column is being counted for the function. I have messed around with the divs and the input values and it still doesn’t work. It also fires if not all inputs are answered. Thank you so much for the help you have given me, and I will keep trying to figure this out!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.