javascriptslimselect

How can I prevent duplicate and blank entries in a slimselectjs multiselect?


I am using a slimselectjs multiselect plugin and have an HTML form which submits to it in order to add selected option values. However, when adding selected option values via the form, duplicates can be created if I enter the same text and label. Also, if I just click "add", it will add an entry without a "food name".

For example, I type in "tacos" in the input box, in the drop down select "food" and then click "Add" and re-do that 3 more times, then I will have 4 of the same entry - "food: tacos".

If I just click "Add", it will just enter "food:" without anything after the semicolon.

How can both of these situations be prevented? How can I prevent 1. duplicate entries 2. blank/incomplete submissions from being added?

 <script src="https://cdnjs.cloudflare.com/ajax/libs/slim-select/1.26.0/slimselect.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/slim-select/1.26.0/slimselect.min.css" rel="stylesheet"></link>

<select id="multiple" multiple>
  <option value="value 1">drinks: lemonade</option>
  <option value="value 2">food: hot dog</option>
  <option value="value 3" selected>food: mac & cheese</option>
  <option value="value 4">food: pizza</option>
   <option value="value 8" selected>supplements: vitamin e</option>
</select>
<br><br>
<form>
  <label for="fname">food name:</label>
  <input type="text" id="fname" name="fname"><br><br>
  <label for="type">Choose a label:</label>
  <select name="type" id="type">
    <option value="value 5">food</option>
    <option value="value 6">drinks</option>
    <option value="value 25">drugs</option>
    <option value="value 50">supplements</option>
  </select><br><br>
   <input type="submit" value="Add">
</form>

<script type="text/javascript">
new SlimSelect({
  select: '#multiple'
});

const btnAdd = document.querySelector('input[type="submit"]');
btnAdd.addEventListener('click', function(e) {
e.preventDefault();

let input = document.querySelector('#fname');
let select = document.querySelector('#type');
let selectOptions = document.querySelectorAll('#type > option');
let selectMultiple = document.querySelector('#multiple');

// create option element
let option = document.createElement('option');
let optionContent = selectOptions[select.selectedIndex].textContent+':'+input.value;
option.value = optionContent;
option.textContent = optionContent;
option.setAttribute('selected', '');
// insert in select multiple
selectMultiple.appendChild(option);

// reset input and select
input.value = '';
select.selectedIndex = 0;
})
</script>

Solution

  • You can simplify your script by using .innerHTML instead of building the optionelements laboriously. I also simplified your type.options in the way that I removed their value attributes. You only refer to their text values in your script. And when you omit the value attribute the option text will automatically become the value of that option.

    I kept your clearing the input field value as you don't want to accept any repetitions but I left the current selection of type in place to make things easier for the user when they want to enter another item of the same type.

    Also: There is no jQuery in your code, so I removed the tag.

    new SlimSelect({ select: '#multiple' });
    let mul=document.querySelector('#multiple');
    
    document.querySelector('#add').addEventListener('click', function(e) {
      e.preventDefault();
      let inp=document.querySelector('#fname'), foodName=inp.value.trim();
      if (foodName) {
        let newval = document.querySelector('#type').value+': '+foodName;
        // create option element and insert it in select multiple:
        if ([...mul.children].every(o=>o.textContent!=newval))
          mul.innerHTML+=`<option selected>${newval}</option>`;
        // reset input:
        inp.value = '';
      }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/slim-select/1.26.0/slimselect.min.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/slim-select/1.26.0/slimselect.min.css" rel="stylesheet"></link>
    
    <select id="multiple" multiple>
      <option value="value 1">drinks: lemonade</option>
      <option value="value 2">food: hot dog</option>
      <option value="value 3" selected>food: mac & cheese</option>
      <option value="value 4">food: pizza</option>
       <option value="value 8" selected>supplements: vitamin e</option>
    </select>
    <br><br>
    <form>
      <label for="fname">food name:</label>
      <input type="text" id="fname" name="fname"><br><br>
      <label for="type">Choose a label:</label>
      <select name="type" id="type">
        <option>food</option>
        <option>drinks</option>
        <option>drugs</option>
        <option>supplements</option>
      </select><br><br>
       <button id="add">Add</button>
    </form>

    The main part of the action is in

    if ([...mul.children].every(o=>o.textContent!=newval))
      mul.innerHTML+=`<option selected>${newval}</option>`;
    

    I first assert that there is no other option in the multiple select with a text content equal to newval and only then will I append an option with that text and value.