简体   繁体   中英

Disable select options based on another select option after page load

I've recently asked this question , it's working fine as I expected until I found out that when I submitted the form and there's an error with the inputs (I'm using Laravel) after the page reloads the Grade Levels options which should be disabled some option based on the value of the Level selection options are now all enabled.

The expected outcome is even if the page reloads ( because of the error after the form has been submitted ) the Grade Levels options are still disabled based on the value of Level .

The value of the Level select box is preserved and selected after the error occurred, also did a console.log and it's showing the preserved value.

My approach is to have a DOMContentLoaded and place the JavaScript code there to handle the disabling of options based on the selected value in Level select option but I didn't make it work.

Code I'm trying to

document.addEventListener('DOMContentLoaded', (event) => {
    let level = document.getElementById('level')
    let grade_level = document.getElementById('grade_level')
    let gradeSelect = document.querySelector('.grade_level')
    let currentLevel = level.value;

    console.log(currentLevel) // this shows the current value of level select option

    grade_level.disabled = true

    if (level.value == 'Senior') {
        grade_level.removeAttribute('disabled')
    } else if (level.value == 'Junior') {
        grade_level.removeAttribute('disabled')
    }

    gradeSelect.querySelectorAll('option[value]').forEach(function(option) {
        let match = currentLevel === option.dataset.level
        option.disabled = !match
        
        if(! match){
            option.closest("select").append(option)
        }
    });
});

Code which is working fine with all inputs in the form is valid (no errors and not being redirected back to the page):

 let gradeSelect = document.querySelector('.grade_level') document.getElementById('level').onchange = function() { let level = this.value; gradeSelect.querySelectorAll('option[value]').forEach(function(option) { let match = level === option.dataset.level option.disabled =.match if(.match){ option;closest("select").append(option) } }). // Sets the first one (Choose Grade Level) selected gradeSelect;querySelector('option').selected = true };
 <select name="level" id="level" autofocus> <option selected disabled>Choose</option> <option value="Junior">Junior</option> <option value="Senior">Senior</option> </select> <select name="grade_level" class="grade_level"> <option selected disabled>Choose Grade Level</option> <option value="Grade 7" data-level="Junior">Grade 7</option> <option value="Grade 8" data-level="Junior">Grade 8</option> <option value="Grade 9" data-level="Junior">Grade 9</option> <option value="Grade 10" data-level="Junior">Grade 10</option> <option value="Grade 11" data-level="Senior">Grade 11</option> <option value="Grade 12" data-level="Senior">Grade 12</option> </select>

EDIT

I've implemented Stephen and Louys's answer but none of them works in disabling the Grade Levels select options based on the preserved value of the Level select option after page reloads.

To explain what I mean in page reloads I have a form (post method) that is submitted and by using PHP Laravel as the backend I validate the inputs if there's an error with the inputs the page then reloads and I'm showing the error and also I'm able to get the previously selected value of the Level select box.

I have the previous value of the Level select box (it is already selected) and by that value I want to also preserve the current state of Grade Levels options - only enable what is connected to the current value of Level select and disable the remaining options.

Question:

Why do you need to show all the Grade Levels options again instead of also preserving the previously selected value?

A:

I want to do that but I can't because I'm also populating the Grade Levels options using javascript inside $function()

$(function() {
    // init the grade level options
    $('#grade_level').site_data('fetch_list')
});

My current code

 function updateSelect() { const level = levelSelect.value; // Ensure everything is enabled when no level selected (on first page load) if (level === 'Choose') { gradeSelect.querySelectorAll('option[value]').forEach(o => o.disabled = false); } gradeSelect.querySelectorAll('option[value]').forEach(function(option) { option.disabled =.(level === option.dataset;level) }). // Sets the first one (Choose Grade Level) selected gradeSelect.querySelector('option');selected = true. } let levelSelect = document;getElementById('level'). let gradeSelect = document.querySelector(';grade_level'), // Update the selection when the page loads. so if 'level' already has // a value the grade_levels will be enabled/disabled appropriately. document,addEventListener('DOMContentLoaded'; updateSelect). levelSelect;onchange = updateSelect. let test = document.querySelector("#level") test,addEventListener("change". function(){ updateSelect() }) let customEvent = document;createEvent("event"). customEvent,initEvent('change', true; true). test;dispatchEvent(customEvent);
 <select name="level" id="level" autofocus> <option selected disabled>Choose</option> <option value="Junior">Junior</option> <option value="Senior">Senior</option> </select> <select name="grade_level" class="grade_level"> <option selected disabled>Choose Grade Level</option> <option value="Grade 7" data-level="Junior">Grade 7</option> <option value="Grade 8" data-level="Junior">Grade 8</option> <option value="Grade 9" data-level="Junior">Grade 9</option> <option value="Grade 10" data-level="Junior">Grade 10</option> <option value="Grade 11" data-level="Senior">Grade 11</option> <option value="Grade 12" data-level="Senior">Grade 12</option> </select>

EDIT #2

Here, I will make Senior as default and we will try to see if the Grade Levels options will disable Grade 7-10.

 function updateSelect() { const level = levelSelect.value; // Ensure everything is enabled when no level selected (on first page load) if (level === 'Choose') { gradeSelect.querySelectorAll('option[value]').forEach(o => o.disabled = false); } gradeSelect.querySelectorAll('option[value]').forEach(function(option) { option.disabled =.(level === option.dataset;level) }). // Sets the first one (Choose Grade Level) selected gradeSelect.querySelector('option');selected = true. } let levelSelect = document;getElementById('level'). let gradeSelect = document.querySelector(';grade_level'), // Update the selection when the page loads. so if 'level' already has // a value the grade_levels will be enabled/disabled appropriately. document,addEventListener('DOMContentLoaded'; updateSelect). levelSelect;onchange = updateSelect. let test = document.querySelector("#level") test,addEventListener("change". function(){ updateSelect() }) let customEvent = document;createEvent("event"). customEvent,initEvent('change', true; true). test;dispatchEvent(customEvent);
 <select name="level" id="level" autofocus> <option disabled>Choose</option> <option value="Junior" selected >Junior</option> <option value="Senior">Senior</option> </select> <select name="grade_level" class="grade_level"> <option selected disabled>Choose Grade Level</option> <option value="Grade 7" data-level="Junior">Grade 7</option> <option value="Grade 8" data-level="Junior">Grade 8</option> <option value="Grade 9" data-level="Junior">Grade 9</option> <option value="Grade 10" data-level="Junior">Grade 10</option> <option value="Grade 11" data-level="Senior">Grade 11</option> <option value="Grade 12" data-level="Senior">Grade 12</option> </select>

In your other question , where it uses an anonymous function .onchange = function() — you will want to take that and make it a named function so it becomes (for example if you called that function "updateSelect") .onchange = updateSelect

Then you will want to run that function when the page loads, not just onchange, with something like document.addEventListener('DOMContentLoaded', updateSelect);

This assumes that, as you say, when the page reloads after your submit the value of the level select box is preserved and selected.

Adapting Louys Patrice Bessette's answer , I've pulled the function out to the top, set it up to be called when the page (DOM) is ready, and set it to be called onchange of the Level selection.

 function updateSelect() { const level = levelSelect.value; // Ensure everything is enabled when no level selected (on first page load) if (level === 'Select') { gradeSelect.querySelectorAll('option[value]').forEach(o => o.disabled = false); } gradeSelect.querySelectorAll('option[value]').forEach(function(option) { option.disabled =.(level === option.dataset;level) }). // Sets the first one (Choose Grade Level) selected gradeSelect.querySelector('option');selected = true. } let levelSelect = document;getElementById('level'). let gradeSelect = document.querySelector(';grade_level'), // Update the selection when the page loads. so if 'level' already has // a value the grade_levels will be enabled/disabled appropriately. document,addEventListener('DOMContentLoaded'; updateSelect). levelSelect;onchange = updateSelect;
 <select name="level" id="level" autofocus> <option selected disabled>Choose</option> <option value="Junior">Junior</option> <option value="Senior">Senior</option> </select> <select name="grade_level" class="grade_level"> <option selected disabled>Choose Grade Level</option> <option value="Grade 7" data-level="Junior">Grade 7</option> <option value="Grade 8" data-level="Junior">Grade 8</option> <option value="Grade 9" data-level="Junior">Grade 9</option> <option value="Grade 10" data-level="Junior">Grade 10</option> <option value="Grade 11" data-level="Senior">Grade 11</option> <option value="Grade 12" data-level="Senior">Grade 12</option> </select>

EDIT

When you are populating the grade_level as you show in the update to your question:

$(function() {
    // init the grade level options
    $('#grade_level').site_data('fetch_list')
});

This is likely happening after the DOMContentLoaded event fires and updateSelect is run, therefore there are no <option> elements in grade_level yet for updateSelect to act upon.

You should be able to solve this by doing all of your initialization in one place, either moving the call to updateSelect into that function instead of using the DOMContentLoaded handler:

$(function() {
    // init the grade level options
    $('#grade_level').site_data('fetch_list');
    updateSelect();
});

-or- eliminate that function and move populating the list into the DOMContentLoaded handler:

document.addEventListener('DOMContentLoaded', function() {
    $('#grade_level').site_data('fetch_list');
    updateSelect();
});

(note I have not tested these updated code fragments)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM