Search code examples
javascriptselectvuejs3formkit

Vue 3.2 Select changes subsequent select


I have two selects, material and color1. I want to change options of color1 element when material is changed. Here's what I have so far:

Script setup:

const data = ref({
    materialType: 'none',
    colors: MyData.MaterialColors['none']
});

const chgMatl = ($event) => {
    data.materialType = $event.target.value
    data.colors = MyData.MaterialColors[data.materialType];
    return data.colors
}

Vue Template:

<FormKit v-model="data.materialType" @change="chgMatl($event)" type="select" name="material" label="Material" validation="required" :options="MyData.Materials"></FormKit>
<FormKit type="select" name="color1" label="Color" validation="required" :options="data.colors"></FormKit>

Sample MyData.MaterialColors:

{
   a: { 1: '1', 2: '2', 3: '3' },
   b: { 1: '1', 2: '2', 3: '3' },
   c: { 1: '1', 2: '2', 3: '3' }
}

When MyData.Materials is changed, it's value is a. This sets data.materialType = a, which plugs into MyData.MaterialColors[a] and returns { 1: '1', 2: '2', 3: '3' } which then populates the colors element's :options.

I was able to make this work alternatively by putting MyData.MaterialColors directly into :options. The dependent select element worked as required. However, the HTML element did not like having brackets [] in the :options field so it would not process properly. I could tell because the closing FormKit tag was red and angry. The view worked when Material changed, but model output did not save to the database.

<FormKit type="select" name="color1" label="Color" validation="required" :options="MyData.MaterialColors[data.materialType]"></FormKit>

Is there a way to have data in the options field with brackets, or can this be represented another way that will produce the necessary information? Or is there a way to set the options directly from the chgMatl function, like jQuery $('#color1').val()? I'm open to a solution from any possibility. Thanks!


Solution

  • In your script, (assuming <script setup>)

    The main point is to crate a colorList computed that returns the appropriate color list

    The watch is there to clear the color selection when the material is changed

    <script setup>
      import { ref, computed, watch } from "vue";
      const materialType = ref("");
      const selectedColor = ref("");
      const colorList = computed(() => MyData.MaterialColors[materialType.value] ?? {});
      watch(materialType, () => (selectedColor.value = ""));
    </script>
    

    and in the template

    <FormKit v-model="materialType" type="select" name="material" label="Material" validation="required" :options="MyData.Materials"></FormKit>
    <FormKit v-model="selectedColor" type="select" name="color1" label="Color" validation="required" :options="colorList"></FormKit>