2
<script>
function refresh()
{
    document.forms[0].submit();
}   
</script>

<select name = "firstoption" onChange ="refresh()"></select>
<option value = "">default option</option>
<option value = "1">1</option>

if($_POST['firstoption]!= "")
<select name = "secondoption" onChange ="refresh()"></select>
<option value = "">default option</option>
<option value = "2">2</option>

if($_POST['secondoption]!= "" && $_POST['firstoption]!= "")
<select name = "thirdoption" onChange ="refresh()"></select>
<option value = "">default option</option>
<option value = "3">3</option>

if($_POST['thirdoption]!= "" && $_POST['secondoption]!= "" && $_POST['firstoption]!= "")
<select name = "fourthoption" onChange ="refresh()"></select>
<option value = "">default option</option>
<option value = "4">4</option>

Hi,

I have 6 static dropdowns. (something like this for some reason I am currently having laptop problems so I could not copy and paste the code where I wrote down generic values)

DELETED (NO LONGER AN ISSUE FIX ON MY OWN)

Basically, I need 6 dropdown (all values kept after it s refresh) and when a dropdown values changes all of the dropdowns below it get reset.

EDIT:

I am looking for code to reset select option back to the default select option (base on hierarchy). Once an select option above it gets change. so if select "2" gets change select 3,4,5 6 value should change to default option. If select "4" gets change select 5,6 would be change to default option etc.

I do not want ajax or jQuery. I am looking for a solution with php, javascript, or html. I think the way to approach it is by comparing the previous and new index number of the select option being change

Note the code I provide is sudo code I can not copy and paste code due to current laptop state.

So the answer does not need to use my code.

I just want a php/javascript/html code that has multiple select options (4-6 select with 2 option in each) the other drop down will be disable until the select above get a value. SO option 2-6 will be disable until select 1 is pick then option 3-6 will be disable until a value for option 2 is pick).

If he user changes select 1 option will select 2-6 already have a value. Select 2-6 automatically switches to default option value. and option 3-6 is now disable until user select option for select 2

Also stack overflow does not allow bounty to be given until 24 hours so I can not give bounty until tomorrow around this time.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
dragonn
  • 311
  • 5
  • 20
  • maybe you've oversimplified this example, but from what you've shown, why don't you just use Javascript for this instead of posting back to the server every time? It would be more efficient and more user-friendly than constantly refreshing the page, plus you wouldn't have to maintain the state across all the requests (which seems to be the difficulty you're having). – ADyson Jul 06 '20 at 15:04
  • I assume in reality you do have some `` tags to close the dropdown?? – RiggsFolly Jul 06 '20 at 15:06
  • @RiggsFolly yes I do sorry I'm currently having some laptop issues spilled water on it the other day haha. So i can't copy and paste the real code. and it's just a lot to type. – dragonn Jul 06 '20 at 15:09
  • @ADyson True I manager to fix that issue thanks :) Check edit. I'm just looking to reset the select value below upon an onChange right now. I can't figure that part out even though it may seem simple – dragonn Jul 06 '20 at 15:10
  • _I do not want ajax or jQuery_. Then how would you reset without some code? – nice_dev Jul 10 '20 at 20:43
  • Would you mind some PHP and javascript code? – nice_dev Jul 10 '20 at 20:47
  • everything you could do in jquery you could do in javascript I think check edit – dragonn Jul 10 '20 at 20:54
  • Do you have to submit the form on each change? Or can you submit the form once after everything is complete? With the code you've posted, it makes it seem as if the 3rd option won't be printed until after the 1st option is selected. – Chris Jul 10 '20 at 20:55
  • you only submit the form once everything is selected(completed).my bad you do see the third option. (it will be printed) but it will be disable so the user can't select anything until the user select the first and second select values – dragonn Jul 10 '20 at 20:57
  • And you require vanilla Javascript for this? A library such as jQuery, or framework such as VueJS makes this a great deal easier. – Chris Jul 10 '20 at 21:00
  • Ideally I want it in vanilla JS jqerry if it's too compliacted. But I think vanilla js would be prefer answer – dragonn Jul 10 '20 at 21:01
  • 1
    @dragonn A jQuery script makes this task much easier. – nice_dev Jul 10 '20 at 21:01

7 Answers7

2

Some suggestions to facilitate the solution:

  • Give all your drop-down lists the same class attribute.
  • Use just one change event handler on a container element (or the whole document), and let the handler find out which select value was changed.
  • Create a function that, given an index, will clear all dropdowns from that index onwards, and will disable all of those, except the first one (at that index).
  • Call this function in the event handler, and also at page load, so to initialise the enabled/disabled status of those dropdowns.

Below is how that could work. I removed all HTML that is not necessary for this solution, but of course you may need more HTML attributes for other purposes:

const dropDowns = Array.from(document.querySelectorAll(".option"));

function reset(i) {
    for (let other of dropDowns.slice(i)) {
        other.selectedIndex = 0;
        other.disabled = other !== dropDowns[i];
    }
}

document.addEventListener("change", function (e) {
    let i = dropDowns.indexOf(e.target);
    if (i < 0) return;
    // only allow input in next one if current value is not default:
    reset(i+(dropDowns[i].selectedIndex > 0));
});

reset(0); // on page load, disable all except first one
<select class="option">
  <option>default option</option>
  <option>1</option>
  <option>2</option>
</select>

<select class="option">
  <option>default option</option>
  <option>A</option>
  <option>B</option>
</select>

<select class="option">
  <option>default option</option>
  <option>x</option>
  <option>y</option>
</select>

<select class="option">
  <option>default option</option>
  <option>alpha</option>
  <option>beta</option>
</select>  

More on the following:

reset(i+(dropDowns[i].selectedIndex > 0));

dropDowns[i].selectedIndex will be 0 when the first entry (default) is selected, and a strictly positive number when any other entry is selected. So with > 0 this actually gives true for when a non-default entry is selected, false otherwise.

Now we want to make the next dropdown available only when the current one has a non-default entry selected, i.e. when this > 0 expression is true. By involving that expression in a + operation, we convert that boolean value to a number (0 for false, 1 for true). And so, that whole expression is either i+0 or i+1, depending on whether the current dropdown has the default value selected or not.

By providing that index (i or i+1) to the reset function, we make sure that the effect of selecting the default value or not is just like is needed.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • perfect this is what I was looking for. If you do have a little more time can you show how to convert the event listener to an onChange function instead – dragonn Jul 10 '20 at 22:30
  • he already commented my answer explaining why your request in this comment is a bad idea @dragonn – Daniele Ricci Jul 10 '20 at 22:43
  • Indeed, it is not such a good practice to use `onchange` attributes in HTML (or any other `onXXX` attributes). It is advised to separate JavaScript code from HTML code, and use `addEventListener` instead. This is generally considered a better practice. – trincot Jul 10 '20 at 23:07
  • thanks can you explain the reset(i+(dropDowns[i].selectedIndex > 0)); I'm confuse how that part works haha – dragonn Jul 13 '20 at 14:07
  • 1
    I added an explanation of that to the answer. – trincot Jul 13 '20 at 14:14
1

There are many ways to accomplish this. The below should work with any number of select boxes. The code is commented to explain the steps.

<form accept="#" method="POST" id="myform">
    <div>
        <select name="firstoption">
            <option value="">default option</option>
            <option value="1">1</option>
            <option value="2">2</option>
        </select>
    </div>
    <div>
        <select name="secondoption" disabled>
            <option value="">default option</option>
            <option value="2">2</option>
            <option value="3">3</option>
        </select>
    </div>
    <div>
        <select name="thirdoption" disabled>
            <option value="">default option</option>
            <option value="3">3</option>
            <option value="4">4</option>
        </select>
    </div>
    <div>
        <select name="fourthoption" disabled>
            <option value="">default option</option>
            <option value="4">4</option>
            <option value="5">5</option>
        </select>
    </div>
    <div>
        <input type="submit" value="Submit">
    </div>
</form>


<script>

//get references to the DOM elements we need
var form = document.getElementById('myform');
var selects = form.querySelectorAll('select');

//register event listeners for each of the select boxes so we know when the value changes
for( let i=0; i<selects.length; i++ ) {
    selects[i].addEventListener('change', function(evt) {
        
        //select box "i" has changed
        //since the value changed, reset other boxes after to the default value and disable
        for( let i2 = (i+1); i2 < selects.length; i2++ ) {
            selects[i2].value = "";
            selects[i2].disabled = true;

        }

        //if the value of the changed select box is not the default, enable the next one
        if( selects[i].value !== "" && selects[i+1] ) {
            selects[i+1].disabled = false;
        }

    });
}

//catch form submission so we can validate the select boxes
form.addEventListener('submit', function(evt) {

    //ensure we have all values before submitting
    try {
        for( let i=0; i<selects.length; i++ ) {
            if( selects[i].value === "" ) {
                alert(`Please select an option for box number ${i+1}`);
                throw 0;
            }
        }
    }catch(e) {
        //error, prevent submission
        evt.preventDefault();
        return false;
    }

    //all good, submit
    return true;
});
</script>
Chris
  • 4,762
  • 3
  • 44
  • 79
  • You can use a _code snippet_, so OP can test your code right here. – Triby Jul 10 '20 at 21:43
  • very close. The problem is when you select all the option 1 as 1 2 a 2 3 as 3 4 as 4. and then change select 1 to a different valuee like 2. all of them get resetted. the problem is they are no longer disable. So i could pick select 4 without chosing value with select 2 and 3 – dragonn Jul 10 '20 at 21:50
  • I updated the code to disable. Give it another shot. – Chris Jul 10 '20 at 21:50
  • 1
    Use the `< >` icon on toolbar, the last one on second tools section. It works like jsfiddle. – Triby Jul 10 '20 at 21:51
0

You can add data attribute for each dropdown, that way you can track index of that dropdown, so on change all higher than index apply action.. when option is selected, reset rest of the boxes that are in order. If previus select box not default, enable next box else disable it

var selects = document.getElementsByClassName("select")


for(var i = 0; i < selects.length; i++){
  
  selects[i].addEventListener('change', function(e){
  
for(var x = 0; x < selects.length; x++){
      
      //On select, reset selectboxes that commes after  
      if(Number(e.target.dataset.columns) < x){
        selects[x][0].selected = true;   
        
      }
      //If previus select box not default, enable next box
      if(x > 0 && selects[x -1][0].selected != true){
        selects[x].disabled = false; 
      }
      //else dissable next box..
      else if(x > 0 && selects[x -1][0].selected == true){
        selects[x].disabled= true; 
      }
  
}

  })
  
}
<select data-columns="0" class="select">
  <option value = "">default option</option>
  <option value = "1">1</option>
  <option value = "1">1</option>
</select>

<select  data-columns="1" disabled class="select">
  <option value = "">default option</option>
  <option value = "2">2</option>
  <option value = "1">1</option>
</select>
<select  data-columns="2" disabled class="select">
  <option value = "">default option</option>
  <option value = "3">3</option>
  <option value = "1">1</option>
</select>

<select data-columns="3" disabled class="select">
  <option value = "">default option</option>
  <option value = "4">4</option>
  <option value = "1">1</option>
</select>  
  
Stefan Avramovic
  • 1,365
  • 2
  • 11
  • 20
  • May be this answers the question, but please explain why. – Poul Bak Jul 10 '20 at 21:20
  • thanks but this does not work when the third select hasmore options than the first select or when any of the select has more options than those before it it no longer works. I want it to change to defualt option regardless of how many options the select has. Your works if select 2has less or equal optin to select 1 – dragonn Jul 10 '20 at 21:36
0

Load all select with document.querySelectorAll() using an expresion to get elements wich name ends with option, that's what $ do before the equal sign.

Then, in your function, check every select if one is empty, set to default value the next.

// Get all items wich name ends with "option"
let selects = document.querySelectorAll('[name$="option"]');
function refresh() {
    // Loop into all selects
    selects.forEach((item, index) => {
        // Don't do this on last one
        if(item.value == '' && index < selects.length - 2)
            selects[index + 1].value = ""
    });
    // Check here the sixthoption value if you need it not empty to submit the form
}
<select name="firstoption" onchange="refresh()">
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
<select name="secondoption" onchange="refresh()">
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
<select name="thirdoption" onchange="refresh()">
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
<select name="fourthoption" onchange="refresh()">
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
<select name="fifthoption" onchange="refresh()">
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
<select name="sixthoption" onchange="refresh()">
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>

Another way using if's:

// Get all items wich name ends with "option"
let selects = document.querySelectorAll('[name$="option"]');
function refresh() {
    // 0 = firstoption, 1 = secondoption... 5 = sixthoption
    // If value is empty string, set default value for next element too
    if(selects[0].value == "") selects[1].value = '';
    if(selects[1].value == "") selects[2].value = '';
    if(selects[2].value == "") selects[3].value = '';
    if(selects[3].value == "") selects[4].value = '';
    if(selects[4].value == "") selects[5].value = '';
}
<select name="firstoption" onchange="refresh()">
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
<select name="secondoption" onchange="refresh()">
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
<select name="thirdoption" onchange="refresh()">
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
<select name="fourthoption" onchange="refresh()">
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
<select name="fifthoption" onchange="refresh()">
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
<select name="sixthoption" onchange="refresh()">
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
Triby
  • 1,739
  • 1
  • 16
  • 18
0

You could try this:

const selects = document.querySelectorAll(".myoption");
const submit = document.getElementById("mysubmit");

selects.forEach((select, id) => select.addEventListener("change",() => {
    const last = id === selects.length - 1;

    if(! last) {
        selects[id + 1].removeAttribute("disabled");
        selects[id + 1].value = "";
    }

    for(let i = id + (select.selectedIndex ? 2 : 1); i < selects.length; ++i) {
        selects[i].value = "";
        selects[i].setAttribute("disabled", true);
    }

    submit.setAttribute("disabled", true);
    
    if(last && select.selectedIndex) submit.removeAttribute("disabled");
}));
<select class="myoption">
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>
<select class="myoption" disabled>
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>
<select class="myoption" disabled>
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>
<select class="myoption" disabled>
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>
<select class="myoption" disabled>
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>
<select class="myoption" disabled>
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>
<input type="submit" id="mysubmit" value="submit" disabled>

Hope this helps.

Daniele Ricci
  • 15,422
  • 1
  • 27
  • 55
  • It would be better to separate JavaScript from HTML code. See [this Q&A](https://stackoverflow.com/questions/37289899/is-javascript-as-html-attribute-bad-practice). – trincot Jul 10 '20 at 21:53
  • I learned another thing today, thank you @trincot . P.S. I'll not update my answer since it would become a copy of your one. – Daniele Ricci Jul 10 '20 at 21:59
  • very close. When the answer is default for any of the select option. I could pick an answer for the next option. I want it so that the next answer is disable. Unless the one before it has not default – dragonn Jul 10 '20 at 22:04
  • If you have time enough @trincot could you please check my edited answer and teach me something else? Thank you – Daniele Ricci Jul 10 '20 at 22:49
0

I assume that you not necessarily want to post upon each select change. Instead, let's see this approach:

    <select class="fancy-select" id="s-1" name = "firstoption">
        <option value = "">default option</option>
        <option value = "1">1</option>
    </select>
    
    <select class="fancy-select" id="s-2" name = "secondoption">
        <option value = "">default option</option>
        <option value = "2">2</option>
    </select>
    
    <select class="fancy-select" id="s-3" name = "thirdoption">
        <option value = "">default option</option>
        <option value = "3">3</option>
    </select>
    
    <select class="fancy-select" id="s-4" name = "fourthoption">
        <option value = "">default option</option>
        <option value = "4">4</option>
    </select>
<script type="text/javascript">
    function myHandler() {
            if (!this.value) {
                var currentID = parseInt(this.id.substring(2));
                for (let i = currentID; i < fancySelects.length; i++) fancySelects[i].value = "";
        }
    }
    var fancySelects = document.querySelectorAll(".fancy-select");
    for (let item of fancySelects) item.addEventListener("change", myHandler);
</script>

Fiddle: https://jsfiddle.net/0dfxytpc/1/

You see that despite the claims about Vue JS and jQuery making it easier, Javascript in itself is easy. If you know how to program in Javascript. My understanding is that once default is chosen you intend the subsequent items to be defaulted. If that's not the aim, then I misunderstood the goal.

Now, you can notice that this is pretty repetitive, we can surely make it nicer to appear. Let's generate the select tags on the server:

<?php 
    for ($index = 1; $index <= 4; $index++) {
    ?>
    <select class="fancy-select" id="s-<?php echo $index; ?>">
        <option value="">default option</option>
        <option value="<?php echo $index; ?>"><?php echo $index; ?></option>
    </select>
    <?php
    }
?>
<script type="text/javascript">
    function myHandler() {
            if (!this.value) {
                var currentID = parseInt(this.id.substring(2));
                for (let i = currentID; i < fancySelects.length; i++) fancySelects[i].value = "";
        }
    }
    var fancySelects = document.querySelectorAll(".fancy-select");
    for (let item of fancySelects) item.addEventListener("change", myHandler);
</script>

The code is small and easy to understand. Vue JS and jQuery would just overcomplicate this, they would add dependencies that you do not need. There is a trend of programmers who are less capable to work in Javascript and will argue that doing stuff is easier in Vue JS or jQuery. You can actually measure the power of that trend with the number of downvotes I get. I do not speak against the use of jQuery or Vue JS in general, although, I am not their fan in particular, but when you learn Javascript you should avoid getting dependant of a framework right from the start. As you get comfortable working with Javascript you might decide that Vue JS and jQuery is good for you. I would totally respect that decision, but do not make that decision before you learn Javascript properly.

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
0

As already a lot of ways are mentioned, here is what I came up with.

  • Assign every select a data-name attribute.
  • Every select would also have a class attribute. This class attribute would possess all previous parents' data-names.
  • When a particular select value changes, you get the data-name of it and use querySelectorAll to get all those elements who have this data-name in their class and set their values and disability accordingly.

var selects = document.querySelectorAll('select');
selects.forEach(function(select_dropdown){
   select_dropdown.addEventListener('change',function(){
        var kids = document.querySelectorAll('.' + this.getAttribute('data-name'));
        var parent_value = this.value;

        kids.forEach(function(child,index){
          child.value = "";
          if(parent_value == "" || index > 0){
            child.setAttribute('disabled','disabled');
          }else{
            child.removeAttribute('disabled');
          }
        });      
   });
});
<select class="" data-name="select_1">
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>
<select data-name="select_2" class="select_1" disabled>
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>
<select data-name="select_3" class="select_1 select_2" disabled>
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>
<select data-name="select_4" class="select_1 select_2 select_3" disabled>
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>
<select data-name="select_5" class="select_1 select_2 select_3 select_4" disabled>
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>
<select data-name="select_6" class="select_1 select_2 select_3 select_4 select_5" disabled>
    <option value="">Default</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>
nice_dev
  • 17,053
  • 2
  • 21
  • 35