Search code examples
javascriptvue.jsv-for

Generate multiple select inputs with v-for


I am desperately trying to generate multiple select inputs for a given JSON from an Backend but I cant make it work. The JSON response I am getting looks smth like this:

{
    "selectData": [
        {
            "id": "ats_2323680",
            "label": "Follow up",
            "value": "option_id_1"
        },
        {
            "id": "ats_2323701",
            "label": "1st Interview, Client",
            "value": "option_id_1"
        },...
    ],
    "optionData": {
        "texts": [
            "Sourced",
            "On hold",
            ...
        ],
        "values": [
            "option_id_1",
            "option_id_2",
        ]
    }
}

Ive already tried several ways and my last attempt looks like this:

Template:

 <div v-for="select in selectData" :key="select.id">
          <p>{{ select.label }}</p>
          <v-select
            :items="optionData.texts"
            :value="getOptionById(select.value)"
            @input="(id) => updateSelect(select, id)"
          ></v-select>
  </div>

Script:

<script>
export default {
  data() {
    return {
      selectData: [],
      optionData: {
        values: [],
        texts: [],
      },
    };
  },
  methods: {
    fetchData() {
      const headers = this.authorizationHeader;
      axios
        .get(url,
          {
            headers,
          }
        )
        .then((response) => {
          let data = response.data;
          this.selectData = data.selectData;
          this.optionData = data.optionData;
        })
        .catch((error) => console.log(error));
    },
    updateSelect(select, id) {
      select.value = id;
    },
    getOptionById(id) {
      let i = this.optionData.values.findIndex((x) => x === id);
      return this.optionData.texts[i];
    },
  },
  mounted() {
    this.fetchData();
  },
};
</script>

I am also not super happy with the JSON struct I am getting. The reason that the optionTextId is also send is, that the optionTexts will be in different languages. I am really happy with any advise.


Solution

  • I think I solved it. I think it was a classy case of overthinking.

    First I changed the JSON structure in the backend like:

    {
        "selectData": [
            {
                "id": "ats_2323680",
                "label": "Follow up",
                "text": "Sourced",
            },
            {
                "id": "ats_2323701",
                "label": "1st Interview, Client",
                "text": "Kandidaten nachgefasst",
            },
            ...
        ],
        "optionData": {
            "texts": [
                "Sourced",
                "Kandidaten kontaktiert",
                ...
            ],
            "values": [
                "option_id_1",
                "option_id_2",
                ...
           ]
        }
    }
    

    Then I changed the Vue code to: Template:

    <div v-for="select in selectData" :key="select.id">
                <label for="location">{{ select.label }}</label>
                <select id="location" name="location" v-model="select.text">
                  <option
                    v-for="option in optionData.texts"
                    :key="option"
                    :value="option"
                  >
                    {{ option }}
                  </option>
                </select>
    </div>
    

    Script:

    <script>
    export default {
      data() {
        return {
          selectData: [],
          optionData: {
            values: [],
            texts: [],
          },
        };
      },
      methods: {
        fetchData() {
          const headers = this.authorizationHeader;
          axios
            .get(
              url,
              {
                headers,
              }
            )
            .then((response) => {
              let data = response.data;
              this.selectData = data.selectData;
              this.optionData = data.optionData;
            })
            .catch((error) => console.log(error));
        },
      },
      mounted() {
        this.fetchData();
      },
    };
    </script>
    
    

    Apparently changing the JSON struc and using v-model did the magic. Might be obvious. Hope this helps a lost soul like me at some point :)