Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to synchronize two SELECT elements

I was wondering how to synchronize the values and text of two elements. For instance,

<select id="box1" onchange="sync();">
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
<select id="box2">
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>

and then sync(); would look something like....

function sync()
{
box2.selected = box1.selected;
}

Any idea how I would do this? Thanks, Matthew

like image 615
MatthewSot Avatar asked Dec 17 '11 19:12

MatthewSot


3 Answers

One possible approach:

function sync(el1, el2) {
    // if there is no el1 argument we quit here:
    if (!el1) {
        return false;
    }
    else {
        // caching the value of el1:
        var val = el1.value;

        // caching a reference to the element with
        // with which we should be synchronising values:
        var syncWith = document.getElementById(el2);

        // caching the <option> elements of that <select>:
        var options = syncWith.getElementsByTagName('option');

        // iterating over those <option> elements:
        for (var i = 0, len = options.length; i < len; i++) {

            // if the value of the current <option> is equal
            // to the value of the changed <select> element's
            // selected value:
            if (options[i].value == val) {

                // we set the current <option> as
                // as selected:
                options[i].selected = true;
            }
        }
    }
}

// caching the <select> element whose change event should
// be reacted-to:
var selectToSync = document.getElementById('box1');

// binding the onchange event using an anonymous function:
selectToSync.onchange = function(){

    // calling the function:
    sync(this,'box2');
};

function sync(el1, el2) {
  if (!el1) {
    return false;
  } else {
    var val = el1.value;
    var syncWith = document.getElementById(el2);
    var options = syncWith.getElementsByTagName('option');
    for (var i = 0, len = options.length; i < len; i++) {
      if (options[i].value == val) {
        options[i].selected = true;
      }
    }
  }
}

var selectToSync = document.getElementById('box1');
selectToSync.onchange = function() {
  sync(this, 'box2');
};
<select id="box1">
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
</select>
<select id="box2">
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
</select>

JS Fiddle demo.

Or, revised and updated somewhat:

function sync() {

  // caching the changed element:
  let el = this;

  // retrieving the id of the element we should synchronise with
  // from the changed-element's data-syncwith custom attribute,
  // using document.getElementById() to retrieve that that element.
  document.getElementById( el.dataset.syncwith )
    // retrieving the <options of that element
    // and finding the <option> at the same index
    // as changed-element's selectedIndex (the index
    // of the selected <option> amongst the options
    // collection) and setting that <option> element's
    // selected property to true:
    .options[ el.selectedIndex ].selected = true;
}

// retrieving the element whose changes should be
// synchronised with another element:
var selectToSync = document.getElementById('box1');

// binding the snyc() function as the change event-handler:
selectToSync.addEventListener('change', sync);

function sync() {
  let el = this;
  document.getElementById(el.dataset.syncwith).options[el.selectedIndex].selected = true;
}

var selectToSync = document.getElementById('box1');
selectToSync.addEventListener('change', sync);
<select id="box1" data-syncwith="box2">
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
</select>
<select id="box2">
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
</select>

JS Fiddle demo.

Note that this approach does assume – and requires – that the <option> elements are in the same order.

To update the original approach, where the order is irrelevant, using ES6 approaches (and the same data-syncwith custom attribute approach):

function sync() {
  // caching the changed element (since
  // we're using it twice):
  let el = this;

  // retrieving the id of the element to synchronise 'to' from 
  // the 'data-syncwith' custom attribute of the changed element,
  // and retrieving its <option> elements. Converting that
  // Array-like collection into an Array using Array.from():
  Array.from(document.getElementById(el.dataset.syncwith).options)
    // Iterating over the array of options using
    // Array.prototype.forEach(), and using an Arrow function to
    // pass the current <otpion> (as 'opt') setting that current
    // <option> element's selected property according to Boolean
    // returned by assessing whether the current option's value
    // is (exactly) equal to the value of the changed element:
    .forEach(opt => opt.selected = opt.value === el.value);
}

var selectToSync = document.getElementById('box1');
selectToSync.addEventListener('change', sync);

function sync() {
  let el = this;
  Array.from(document.getElementById(el.dataset.syncwith).options).forEach(opt => opt.selected = opt.value === el.value);
}

let selectToSync = document.getElementById('box1');
selectToSync.addEventListener('change', sync);
<select id="box1" data-syncwith="box2">
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
</select>
<select id="box2">
  <option value="1">One</option>
  <option value="3">Three</option>
  <option value="2">Two</option>
</select>

JS Fiddle demo.

If you look at the HTML in the Snippet you'll see that I switched the positions of <option> elements in the second <select> element to demonstrate that the <option> position doesn't matter in this latter approach.

References:

  • Array.from().
  • Array.prototype.forEach().
  • Arrow functions.
  • document.getElementById().
  • EventTarget.addEventListener().
  • for loop.
  • HTMLElement.dataset.
  • HTMLSelectElement.
  • let statement.
  • var.
like image 142
David Thomas Avatar answered Oct 22 '22 10:10

David Thomas


In the Actual browsers you dont have to do to much...

<select id="box1" onchange="box2.value=this.value;">
    <option value="1">One</option>
    <option value="2">Two</option>
    <option value="3">Three</option>
</select>
<select id="box2">
    <option value="1">One</option>
    <option value="2">Two</option>
    <option value="3">Three</option>
</select>

Jsfiddle DEMO

like image 22
Jhim Preston Avatar answered Oct 22 '22 09:10

Jhim Preston


Without jQuery:

for (var i=0; i<document.getElementById('box1').options.length; i++)
  if (document.getElementById('box1').options[i].selected)
     for (var j=0; j<document.getElementById('box2').options.length; j++)
        if (document.getElementById('box1').options[i].value == document.getElementById('box2').options[j].value)
          document.getElementById('box2').options[j].selected = true;
like image 1
Adilson de Almeida Jr Avatar answered Oct 22 '22 11:10

Adilson de Almeida Jr