huy_trvan
huy_trvan

Reputation: 67

How to prevent Select elements from having duplicating options

I am making a calendar page where users can select any day of the week but the options must not duplicate what is already selected in other ones.

Check below to see what I mean:

var elementOption = ["--", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]

function update(element) {
  //do something, IDK
}
<h4>How can we prevent selected option in A from showing in options B and C, and vice versa?</h4>
<div>
<h5> A </h5>
<select name="day_select" onchange="update(this)">
  <option value="--">--</option>
  <option value="monday">Monday</option>
  <option value="tuesday">Tuesday</option>
  <option value="wednesday">Wednesday</option>
  <option value="thursday">Thursday</option>
  <option value="friday">Friday</option>
  <option value="saturday">Saturday</option>
  <option value="sunday">Sunday</option>
</select>
</div>
<div>
<h5> B </h5>
<select name="day_select" onchange="update(this)">
  <option value="--">--</option>
  <option value="monday">Monday</option>
  <option value="tuesday">Tuesday</option>
  <option value="wednesday">Wednesday</option>
  <option value="thursday">Thursday</option>
  <option value="friday">Friday</option>
  <option value="saturday">Saturday</option>
  <option value="sunday">Sunday</option>
</select>
</div>
<h5> C </h5>
<select name="day_select" onchange="update(this)">
  <option value="--">--</option>
  <option value="monday">Monday</option>
  <option value="tuesday">Tuesday</option>
  <option value="wednesday">Wednesday</option>
  <option value="thursday">Thursday</option>
  <option value="friday">Friday</option>
  <option value="saturday">Saturday</option>
  <option value="sunday">Sunday</option>
</select>
</div>

My question: How can we do it without using Jquery or many nested For loops (as performance is key here too). Thank you

Upvotes: 1

Views: 51

Answers (1)

Marco M
Marco M

Reputation: 50

Here is a rough solution showing the dynamics in VanillaJS

https://jsfiddle.net/e5zhymwL/17/

const options = [
  "--",
  "monday",
  "tuesday",
  "wednesday",
  "thursday",
  "friday",
  "saturday",
  "sunday",
]

const daysSelected = []

const selectedListBox = document.getElementById('selected')

function update(elem, targetId) {
  const selected = elem.value
  if (selected === '--') return
  daysSelected.push(selected)
  // print out already selected days
  const otherSelector = document.getElementById(targetId)
  // replace the targeted selector with available options
  otherSelector.innerHTML = ''
  otherSelector.insertAdjacentHTML(
    'beforeend',
    options
      .filter(option => daysSelected.indexOf(option) === -1)
      .map(option => `<option value="${option}">${option}</option>`)
  )
  selectedListBox.innerHTML = daysSelected
}

const reset = () => {
  daysSelected.length = 0;
  [document.getElementById('selector1'),
   document.getElementById('selector2')].forEach(elem => {
    elem.innerHTML = ''
    elem.insertAdjacentHTML(
      'beforeend',
      options
        .filter(option => daysSelected.indexOf(option) === -1)
        .map(option => `<option value="${option}">${option}</option>`)
    )
  })
  selectedListBox.innerHTML = ''
}
<h4>Non-duplicating for each of these</h4>
<select name="day_select_1" id="selector1" onchange="update(this,'selector2')">
  <option value="--">--</option>
  <option value="monday">Monday</option>
  <option value="tuesday">Tuesday</option>
  <option value="wednesday">Wednesday</option>
  <option value="thursday">Thursday</option>
  <option value="friday">Friday</option>
  <option value="saturday">Saturday</option>
  <option value="sunday">Sunday</option>
</select>

<select name="day_select_2" id="selector2" onchange="update(this,'selector1')">
  <option value="--">--</option>
  <option value="monday">Monday</option>
  <option value="tuesday">Tuesday</option>
  <option value="wednesday">Wednesday</option>
  <option value="thursday">Thursday</option>
  <option value="friday">Friday</option>
  <option value="saturday">Saturday</option>
  <option value="sunday">Sunday</option>
</select>

<p>Selected days: <span id="selected"></span></p>

<button onclick="reset()">Reset</button>

You will need to refactor and clean up a little the code (global scoping and duplications). However, following this you should be able to improve it a little and generate dynamically more days selectors. Hope it could help!

UPDATE

New jsfiddle => https://jsfiddle.net/knopfy/vqnrtzdf/33/

const options = [
    "--",
  "monday",
  "tuesday",
  "wednesday",
  "thursday",
  "friday",
  "saturday",
  "sunday",
]

const selectors = {
    A: document.getElementById('A'),
    B: document.getElementById('B'),
    C: document.getElementById('C'),
}

const daysSelected = {}

function update(elem) {
    const selector = elem.id 
  const selected = elem.value
  if (selected === '--') {
      return
  }
    daysSelected[selector] = selected
  for (const key in selectors) {
    if (key !== selector) {
        for (const option of selectors[key].options) {
        option.disabled = daysSelected[key] !== option.value
            && Object.values(daysSelected).indexOf(option.value) !== -1
      }
    }
  }
}
<select name="A" id="A" onchange="update(this)">
  <option value="--">--</option>
  <option value="monday">Monday</option>
  <option value="tuesday">Tuesday</option>
  <option value="wednesday">Wednesday</option>
  <option value="thursday">Thursday</option>
  <option value="friday">Friday</option>
  <option value="saturday">Saturday</option>
  <option value="sunday">Sunday</option>
</select>

<select name="B" id="B" onchange="update(this)">
  <option value="--">--</option>
  <option value="monday">Monday</option>
  <option value="tuesday">Tuesday</option>
  <option value="wednesday">Wednesday</option>
  <option value="thursday">Thursday</option>
  <option value="friday">Friday</option>
  <option value="saturday">Saturday</option>
  <option value="sunday">Sunday</option>
</select>

<select name="C" id="C" onchange="update(this)">
  <option value="--">--</option>
  <option value="monday">Monday</option>
  <option value="tuesday">Tuesday</option>
  <option value="wednesday">Wednesday</option>
  <option value="thursday">Thursday</option>
  <option value="friday">Friday</option>
  <option value="saturday">Saturday</option>
  <option value="sunday">Sunday</option>
</select>

Upvotes: 1

Related Questions