多个嵌套选择下拉列表依赖于JavaScript中的输入元素

发布于 2025-02-11 11:08:06 字数 1180 浏览 1 评论 0原文

我将输入元素作为范围多年。我可以通过按钮更改年度价值。我想在第二个选择中创建嵌套列表,这些列表取决于范围输入和第一次选择 - ID Countrysect。

<input type="range" id="yearRange" min="0" max="3" list="yearsDatalist" value="3"
onChange="changeYear(value)" onInput="changeYearLite(value)">
    <datalist id="yearsDatalist">
        <option value="0" label="1918"></option>
        <option value="1" label="1936"></option>
        <option value="2" label="1950"></option>
        <option value="3" label="1981"></option>
    </datalist>

然后我有两个选择的元素。第一个是静态的 - 不需要更改那里的值:

<select id="countrySelect">
    <option value="0">Sweden</option>
    <option value="1">Germany</option>
    <option value="2">USA</option>
</select>

第二选择取决于年份和第一个选择中的值id = countryselect

<select id="itemSelection"></select>

我在某些不同的项目中使用了类似的对象:

const yearsFilterDataList = {
    "1918": {
        "0": "Choose model",
        "volvo": "Volvo",
        "mercedes": "Mercedes",
        "saab": "Saab"
    }, ...

I have input element as range for years. I can change value of year by buttons. I would like to create nested list in second select that depends on year from range input and on first select - id countrySelect.

<input type="range" id="yearRange" min="0" max="3" list="yearsDatalist" value="3"
onChange="changeYear(value)" onInput="changeYearLite(value)">
    <datalist id="yearsDatalist">
        <option value="0" label="1918"></option>
        <option value="1" label="1936"></option>
        <option value="2" label="1950"></option>
        <option value="3" label="1981"></option>
    </datalist>

Then I have two select elements. The first one is static - not necessary to change the values there:

<select id="countrySelect">
    <option value="0">Sweden</option>
    <option value="1">Germany</option>
    <option value="2">USA</option>
</select>

Second select is dependent on year and on values in first select with id=countrySelect

<select id="itemSelection"></select>

I used object for values like this in some different project:

const yearsFilterDataList = {
    "1918": {
        "0": "Choose model",
        "volvo": "Volvo",
        "mercedes": "Mercedes",
        "saab": "Saab"
    }, ...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

阳光下慵懒的猫 2025-02-18 11:08:06

我建议使用a QuerySelector中找到所选选项上的标签属性。

function changeYear (value) {
  let selectedOption = document.querySelector(`option[value="${value}"]`);
  let selectedYear = selectedOption.label;
  
  let data = yearsFilterDataList[selectedYear];
  // Do what you want with the car information
}

下次尝试以更好的方式提供和组织您的代码(HTML,CSS,JS),以便人们不必猜测您的设置是什么。您还没有提供完整的年filterdatalist对象,因此滑块仅在第一个tick上填充选择表单。

但这是一个假定的实现:

const yearsFilterDataList = {
    "1918": {
        "0": "Choose model",
        "volvo": "Volvo",
        "mercedes": "Mercedes",
        "saab": "Saab"
    }
}

function changeYearLite (value) {
    // ?
}
    
function changeYear (value) {
  let selectedOption = document.querySelector(`option[value="${value}"]`);
  let selectedYear = selectedOption.label;
  
  let data = yearsFilterDataList[selectedYear];
  if (!data) return console.warn('no data found')
  let wrapper = document.getElementById('itemSelection');
  
  Object.keys(data).forEach((key, index) => {
      let option = document.createElement('option');
      option.value = index;
      option.textContent = data[key];
      wrapper.appendChild(option);
  })
}
<input type="range" id="yearRange" min="0" max="3" list="yearsDatalist" value="3"
onChange="changeYear(value)" onInput="changeYearLite(value)">
<datalist id="yearsDatalist">
  <option value="0" label="1918"></option>
  <option value="1" label="1936"></option>
  <option value="2" label="1950"></option>
  <option value="3" label="1981"></option>
</datalist>

<select id="countrySelect">
    <option value="0">Sweden</option>
    <option value="1">Germany</option>
    <option value="2">USA</option>
</select>

<select id="itemSelection"></select>

I would suggest using a template literal for string interpolation in a querySelector to find the label attribute on the selected option.

function changeYear (value) {
  let selectedOption = document.querySelector(`option[value="${value}"]`);
  let selectedYear = selectedOption.label;
  
  let data = yearsFilterDataList[selectedYear];
  // Do what you want with the car information
}

Next time try to provide and organize your code (HTML, CSS, JS) in a better way so people don't have to guess what your setup exactly is. You also didn't provide the full yearsFilterDataList object so the slider only populates the select form on the first tick.

But here is an assumed implementation:

const yearsFilterDataList = {
    "1918": {
        "0": "Choose model",
        "volvo": "Volvo",
        "mercedes": "Mercedes",
        "saab": "Saab"
    }
}

function changeYearLite (value) {
    // ?
}
    
function changeYear (value) {
  let selectedOption = document.querySelector(`option[value="${value}"]`);
  let selectedYear = selectedOption.label;
  
  let data = yearsFilterDataList[selectedYear];
  if (!data) return console.warn('no data found')
  let wrapper = document.getElementById('itemSelection');
  
  Object.keys(data).forEach((key, index) => {
      let option = document.createElement('option');
      option.value = index;
      option.textContent = data[key];
      wrapper.appendChild(option);
  })
}
<input type="range" id="yearRange" min="0" max="3" list="yearsDatalist" value="3"
onChange="changeYear(value)" onInput="changeYearLite(value)">
<datalist id="yearsDatalist">
  <option value="0" label="1918"></option>
  <option value="1" label="1936"></option>
  <option value="2" label="1950"></option>
  <option value="3" label="1981"></option>
</datalist>

<select id="countrySelect">
    <option value="0">Sweden</option>
    <option value="1">Germany</option>
    <option value="2">USA</option>
</select>

<select id="itemSelection"></select>

尐籹人 2025-02-18 11:08:06

我创建了一个小提琴,我为每个年度国家对创建optgroup,每个optgroup都有两个元素,具体取决于年度和国家/地区的ID(您当然可以更改每个选项optgroup,这种选项定义的唯一原因是简化我的测试)。更改yeargelaydatalist触发ChangeOptions的的值,找到这些元素optgroup要显示,然后循环optgroup,并隐藏所有与ID匹配的内容。将显示匹配的optgroup,并且,由于任何先前选择在逻辑上都是无效的,因此我更新itemselection.value to所选第一个孩子的值optgroup < /代码>。

最后,我无论如何我都会调用更改,以便甚至在触发任何触发器之前初始化适当的状态。

function changeOptions() {
    let yearRange = document.getElementById("yearRange").value;
    let countrySelect = document.getElementById("countrySelect").value;
    let id = `options-${yearRange}-${countrySelect}`;
    let itemSelection = document.getElementById("itemSelection");
    for (let optgroup of itemSelection.children) {
        let match = optgroup.id === id;
        optgroup[(match ? "remove" : "set") + "Attribute"]("hidden", "hidden");
        if (match) {
            itemSelection.value = optgroup.children[0].value;
        }
    }
}

changeOptions();
<input type="range" id="yearRange" min="0" max="3" list="yearsDatalist" value="3"
onChange="changeOptions()" onInput="changeOptions()">
    <datalist id="yearsDatalist">
        <option value="0" label="1918"></option>
        <option value="1" label="1936"></option>
        <option value="2" label="1950"></option>
        <option value="3" label="1981"></option>
    </datalist>

<select id="countrySelect" onchange="changeOptions()">
    <option value="0">Sweden</option>
    <option value="1">Germany</option>
    <option value="2">USA</option>
</select>

<select id="itemSelection">
    <optgroup id="options-0-0">
        <option value="0-0-1">0-0-1</option>
        <option value="0-0-1">0-0-2</option>
    </optgroup>
    <optgroup id="options-0-1">
        <option value="0-1-1">0-1-1</option>
        <option value="0-1-1">0-1-2</option>
    </optgroup>
    <optgroup id="options-0-2">
        <option value="0-2-1">0-2-1</option>
        <option value="0-2-1">0-2-2</option>
    </optgroup>
    <optgroup id="options-0-3">
        <option value="0-3-1">0-3-1</option>
        <option value="0-3-1">0-3-2</option>
    </optgroup>
    <optgroup id="options-1-0">
        <option value="1-0-1">1-0-1</option>
        <option value="1-0-1">1-0-2</option>
    </optgroup>
    <optgroup id="options-1-1">
        <option value="1-1-1">1-1-1</option>
        <option value="1-1-1">1-1-2</option>
    </optgroup>
    <optgroup id="options-1-2">
        <option value="1-2-1">1-2-1</option>
        <option value="1-2-1">1-2-2</option>
    </optgroup>
    <optgroup id="options-1-3">
        <option value="1-3-1">1-3-1</option>
        <option value="1-3-1">1-3-2</option>
    </optgroup>
    <optgroup id="options-2-0">
        <option value="2-0-1">2-0-1</option>
        <option value="2-0-1">2-0-2</option>
    </optgroup>
    <optgroup id="options-2-1">
        <option value="2-1-1">2-1-1</option>
        <option value="2-1-1">2-1-2</option>
    </optgroup>
    <optgroup id="options-2-2">
        <option value="2-2-1">2-2-1</option>
        <option value="2-2-1">2-2-2</option>
    </optgroup>
    <optgroup id="options-2-3">
        <option value="2-3-1">2-3-1</option>
        <option value="2-3-1">2-3-2</option>
    </optgroup>
    <optgroup id="options-3-0">
        <option value="3-0-1">3-0-1</option>
        <option value="3-0-1">3-0-2</option>
    </optgroup>
    <optgroup id="options-3-1">
        <option value="3-1-1">3-1-1</option>
        <option value="3-1-1">3-1-2</option>
    </optgroup>
    <optgroup id="options-3-2">
        <option value="3-2-1">3-2-1</option>
        <option value="3-2-1">3-2-2</option>
    </optgroup>
    <optgroup id="options-3-3">
        <option value="3-3-1">3-3-1</option>
        <option value="3-3-1">3-3-2</option>
    </optgroup>
</select>

I have created a fiddle where I have created an optgroup for each year-country pair, each optgroup has two elements, depending on the ids of the year and country (you can of course change the options of each optgroup, the lone reason for this kind of option definition was to ease my testing). Changing the value of yearRange or yearsDatalist triggers a call to changeOptions, which finds these elements, defines the id of the optgroup to show, then loops the optgroups and hides everything except the one that matches the id. The matching optgroup will be shown and, since any prior selection is logically invalidated, I update itemSelection.value to the value of the first child of the chosen optgroup.

Finally I call changeOptions anyway, in order to initialize a proper state even before any of the triggers are triggered.

function changeOptions() {
    let yearRange = document.getElementById("yearRange").value;
    let countrySelect = document.getElementById("countrySelect").value;
    let id = `options-${yearRange}-${countrySelect}`;
    let itemSelection = document.getElementById("itemSelection");
    for (let optgroup of itemSelection.children) {
        let match = optgroup.id === id;
        optgroup[(match ? "remove" : "set") + "Attribute"]("hidden", "hidden");
        if (match) {
            itemSelection.value = optgroup.children[0].value;
        }
    }
}

changeOptions();
<input type="range" id="yearRange" min="0" max="3" list="yearsDatalist" value="3"
onChange="changeOptions()" onInput="changeOptions()">
    <datalist id="yearsDatalist">
        <option value="0" label="1918"></option>
        <option value="1" label="1936"></option>
        <option value="2" label="1950"></option>
        <option value="3" label="1981"></option>
    </datalist>

<select id="countrySelect" onchange="changeOptions()">
    <option value="0">Sweden</option>
    <option value="1">Germany</option>
    <option value="2">USA</option>
</select>

<select id="itemSelection">
    <optgroup id="options-0-0">
        <option value="0-0-1">0-0-1</option>
        <option value="0-0-1">0-0-2</option>
    </optgroup>
    <optgroup id="options-0-1">
        <option value="0-1-1">0-1-1</option>
        <option value="0-1-1">0-1-2</option>
    </optgroup>
    <optgroup id="options-0-2">
        <option value="0-2-1">0-2-1</option>
        <option value="0-2-1">0-2-2</option>
    </optgroup>
    <optgroup id="options-0-3">
        <option value="0-3-1">0-3-1</option>
        <option value="0-3-1">0-3-2</option>
    </optgroup>
    <optgroup id="options-1-0">
        <option value="1-0-1">1-0-1</option>
        <option value="1-0-1">1-0-2</option>
    </optgroup>
    <optgroup id="options-1-1">
        <option value="1-1-1">1-1-1</option>
        <option value="1-1-1">1-1-2</option>
    </optgroup>
    <optgroup id="options-1-2">
        <option value="1-2-1">1-2-1</option>
        <option value="1-2-1">1-2-2</option>
    </optgroup>
    <optgroup id="options-1-3">
        <option value="1-3-1">1-3-1</option>
        <option value="1-3-1">1-3-2</option>
    </optgroup>
    <optgroup id="options-2-0">
        <option value="2-0-1">2-0-1</option>
        <option value="2-0-1">2-0-2</option>
    </optgroup>
    <optgroup id="options-2-1">
        <option value="2-1-1">2-1-1</option>
        <option value="2-1-1">2-1-2</option>
    </optgroup>
    <optgroup id="options-2-2">
        <option value="2-2-1">2-2-1</option>
        <option value="2-2-1">2-2-2</option>
    </optgroup>
    <optgroup id="options-2-3">
        <option value="2-3-1">2-3-1</option>
        <option value="2-3-1">2-3-2</option>
    </optgroup>
    <optgroup id="options-3-0">
        <option value="3-0-1">3-0-1</option>
        <option value="3-0-1">3-0-2</option>
    </optgroup>
    <optgroup id="options-3-1">
        <option value="3-1-1">3-1-1</option>
        <option value="3-1-1">3-1-2</option>
    </optgroup>
    <optgroup id="options-3-2">
        <option value="3-2-1">3-2-1</option>
        <option value="3-2-1">3-2-2</option>
    </optgroup>
    <optgroup id="options-3-3">
        <option value="3-3-1">3-3-1</option>
        <option value="3-3-1">3-3-2</option>
    </optgroup>
</select>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文