Search code examples
javascriptvue.jsprimevue

Rendering object as Dropdown in PrimeVue


I'm using the following script to render a Dropdown using PrimeVue:

<template lang="pug">
Dropdown#tag(v-model="tag" :options="tags")
</template>

<script setup>
import axios from 'axios'
import { ref, onMounted } from 'vue'

const tag = ref()
const tags = ref([])

onMounted(() => {
  tags.value = []

  Promise.all([
    axios.get('/api/v1/tags')
// ... some more requests here
  ]).then(([respTags]) => {
    tags.value = respTags.data
  }).catch($error => {
    toast.add({ severity: 'error', detail: $error, life: 3000 });
  }).finally(() => {
    isLoading.value = false
  })
})

</script>

My problem is that respTags is an object like {tag1: {version: "1.2.3"}, tag2: {version: "1.2.4"}} and when I pass it to the dropdown, it says [Vue warn]: Invalid prop: type check failed for prop "options". Expected Array, got Object.

My goal is that the key of the object (tag1, tag2...) are used as value and version is used as the label.

I know that I can do it using a for loop, but is there any chance to prevent implementing a separate loop for doing this?


Solution

  • Use Array instead of Object

    [Vue warn]: Invalid prop: type check failed for prop "options". Expected Array, got Object
    

    The message is clear. You are passing an object instead of an array. You should pass an array.

    const objectFromApiResult = respTags.data // {tag1: {version: "1.2.3"}, tag2: {version: "1.2.4"}}
    tags.value = Object.keys(objectFromApiResult).map((key) => ({
      value: key,
      label: objectFromApiResult[key].version
    })) // [{label: "1.2.3", value: "tag1"}, {label: "1.2.4", value: "tag2"}]
    

    With Object.keys(), I create an array containing the keys of your object. Then, I manipulate each element using .map, and instead of the string-type key name, I insert an object with two properties, label and value.

    Object.keys() - MDN Docs
    Array.property.map() - MDN Docs
    Dropdown - props.options - PrimeVue Docs (required, type array)

    An array of selectitems to display as the available options.


    How to set the names of the label and value properties

    You can specify the column names of the key and value variables in the object present within the array. The column name for the label can be passed using the props.optionLabel property, and the corresponding value can be set using the props.optionValue property.

    <Dropdown v-model="tag" :options="tags" optionLabel="name" optionValue="version" />
    
    const objectFromApiResult = respTags.data // {tag1: {version: "1.2.3"}, tag2: {version: "1.2.4"}}
    tags.value = Object.keys(objectFromApiResult).map((key) => ({
      version: objectFromApiResult[key].version,
      name: `Version: ${objectFromApiResult[key].version}, TagKey: ${key}`
    })) // [{version: "1.2.3", name: "Version: 1.2.3, TagKey: tag1"}, {version: "1.2.4", name: "Version: 1.2.4, TagKey: tag2"}]
    

    Dropdown - props.optionLabel - PrimeVue Docs - (optional, type string, default: label)
    Dropdown - props.optionValue - PrimeVue Docs - (optional, type string, default: value)


    Extracting the label and value from the same property

    So, the label and value can be referenced from a single property as well.

    <Dropdown v-model="tag" :options="tags" optionLabel="version" optionValue="version" />
    
    const objectFromApiResult = respTags.data // {tag1: {version: "1.2.3"}, tag2: {version: "1.2.4"}}
    tags.value = Object.keys(objectFromApiResult).map((key) => ({
      version: objectFromApiResult[key].version,
    })) // [{version: "1.2.3"}, {version: "1.2.4"}]
    

    If we want to convert only the values of the object into an array

    Although in this case, using the Object.values function is more reasonable than Object.keys.

    <Dropdown v-model="tag" :options="tags" optionLabel="version" optionValue="version" />
    
    const objectFromApiResult = respTags.data // {tag1: {version: "1.2.3"}, tag2: {version: "1.2.4"}}
    tags.value = Object.values(objectFromApiResult) // [{version: "1.2.3"}, {version: "1.2.4"}]
    

    Object.values() - MDN Docs