Search code examples
vue.jsvuetify.js

v-select with groups from data via api


I get from my API this data:

[
   {
      "id":69,
      "name":"Baupraxis",
      "upper_id":7
   },
   {
      "id":42,
      "name":"bautipps.de",
      "upper_id":4
   },
   {
      "id":16,
      "name":"Bellevue",
      "upper_id":7
   },
   {
      "id":18,
      "name":"besser Bauen",
      "upper_id":7
   },
   {
      "id":2,
      "name":"Besuch auf Betriebsgel\u00e4nde",
      "upper_id":0
   },
   {
      "id":7,
      "name":"billiger Bauen",
      "upper_id":0
   }
]

I use it to fill a v-select like this:

<v-select
 label="Anfrageart"
 dense
 :items="itemsRequestTypes"
 item-text="name"
 item-value="id"
 v-model="requestType"
>
</v-select>

So here's what I'd like to solve, the upper_id is greater than zero if it is a subgroup of an item with the matching id. Means in upper_id is the id of the main group.

How can I group this in a v-select now? I try to add a header in the object, but this didn't help.


Solution

  • You need to transform your data from the API before passing it to the template. Also, v-select supports nested option group using items where header type represents the group header which is non-selectable item.

    const data = [
      {
        "id": 69,
        "name": "Baupraxis",
        "upper_id": 7
      },
      {
        "id": 42,
        "name": "bautipps.de",
        "upper_id": 4
      },
      {
        "id": 16,
        "name": "Bellevue",
        "upper_id": 7
      },
      {
        "id": 18,
        "name": "besser Bauen",
        "upper_id": 7
      },
      {
        "id": 2,
        "name": "Besuch auf Betriebsgel\u00e4nde",
        "upper_id": 0
      },
      {
        "id": 7,
        "name": "billiger Bauen",
        "upper_id": 0
      }
    ];
    
    // Create an intermediate object to hold categories.
    const groups = {};
    
    // Create array for each group to main subgroup list.
    data.forEach((x) => {
      // create empty object if it doesn't exists.
      groups[x.upper_id] = groups[x.upper_id] || { name: x.name, list: [] };
      
      groups[x.upper_id].list.push(x);
    });
    
    // The flattened list of items that holds items as well as unique headers
    const flattened = [];
    
    // Iterate over all the unique categories and
    // then flatten into a list that v-select needs.
    Object.keys(groups).forEach((categoryId) => {
      const catgory = groups[categoryId];
      const categoryName = category.name;
    
      // Create a group 
      flattened.push({ header: categoryName });
    
      // Add all the items followed by category header
      flattened.push(...category.list);
    });