Is there a way to dynamically create a Vue component for every tier of a nested JSON object without prior knowledge of the total number of tiers available?

I am working with JSON data that includes a list of retailers, some of which have subretailers that go multiple levels deep.

My goal is to use Vue to generate markup that will show the parent retailer along with any nested subretailers underneath it, similar to this example:

https://i.sstatic.net/n05Li.png

I need to create a function that can handle any number of nested retailers in the JSON. Here is what the JSON structure looks like:

    [{
      "RetailerChilderen":[

      ],
      "Id":83107,
      "Name":"10-11",
      "HasInsightsCenter":true,
      "ParentId":0,
      "UserSelected":true,
      "UserHasAccess":true,
      "Letter":"#",
      "IsVisible":true,
      "InDepthLevel":0
   },
   {
      "RetailerChilderen":[

      ],
      "Id":82800,
      "Name":"1-800-Flowers.com",
      "HasInsightsCenter":false,
      "ParentId":0,
      "UserSelected":true,
      "UserHasAccess":true,
      "Letter":"#",
      "IsVisible":true,
      "InDepthLevel":0
   },
   ...

Currently, my code only loops through two levels in Vue markup:

<ul class="item-container">
    <li v-for="item in retailers">

        <div class="item-info">
            <span>{{ item.Name }}</span>
        </div>

        <ul v-if="item.RetailerChilderen.length">
            <li v-for="subItem in item.RetailerChilderen">
                <div class="item-info">
                    <span>{{ subItem.Name }}</span>
                </div>
            </li>
        </ul>

    </li>
</ul>

Would using a Vue template generated by a method be the best approach to enable displaying multiple levels of nested JSON in the DOM?

Answer №1

To manipulate a node and its children, you can utilize a recursive component.

  const RetailerRec = Vue.component('RetailerRec', {
    props: ['retailer'],
    template: `
      <ul>
        <li> <input type="checkbox"/> {{retailer.Name}} </li>

        <template v-for="retailer in retailer.RetailerChilderen">
          <RetailerRec :retailer="retailer"/>
        </template>
      </ul>
    `
  })
  const tree = JSON.parse('[{"RetailerChilderen":[],"Id":83107,"Name":"10-11","HasInsightsCenter":true,"ParentId":0,"UserSelected":true,"UserHasAccess":true,"Letter":"#","IsVisible":true,"InDepthLevel":0},{"RetailerChilderen":[],"Id":82800,"Name":"1-800-Flowers.com","HasInsightsCenter":false,"ParentId":0,"UserSelected":true,"UserHasAccess":true,"Letter":"#","IsVisible":true,"InDepthLevel":0},{"RetailerChilderen":[{"RetailerChilderen":[{"RetailerChilderen":[],"Id":82371,"Name":"Hervis Sports","HasInsightsCenter":false,"ParentId":82247,"UserSelected":false,"UserHasAccess":false,"Letter":null,"IsVisible":true,"InDepthLevel":0}],"Id":82247,"Name":"Spar Austria","HasInsightsCenter":false,"ParentId":648,"UserSelected":false,"UserHasAccess":false,"Letter":null,"IsVisible":true,"InDepthLevel":0},{"RetailerChilderen":[{"RetailerChilderen":[],"Id":655,"Name":"Despar Italy","HasInsightsCenter":false,"ParentId":83095,"UserSelected":false,"UserHasAccess":false,"Letter":null,"IsVisible":true,"InDepthLevel":0},{"RetailerChilderen":[],"Id":82250,"Name":"Spar Slovenia","HasInsightsCenter":false,"ParentId":83095,"UserSelected":false,"UserHasAccess":false,"Letter":null,"IsVisible":true,"InDepthLevel":0},{"RetailerChilderen":[],"Id":82370,"Name":"Spar Hungary","HasInsightsCenter":false,"ParentId":83095,"UserSelected":false,"UserHasAccess":false,"Letter":null,"IsVisible":true,"InDepthLevel":0},{"RetailerChilderen":[],"Id":82374,"Name":"Spar Croatia","HasInsightsCenter":false,"ParentId":83095,"UserSelected":false,"UserHasAccess":false,"Letter":null,"IsVisible":true,"InDepthLevel":0}],"Id":83095,"Name":"SPAR ASPIAG","HasInsightsCenter":false,"ParentId":648,"UserSelected":false,"UserHasAccess":false,"Letter":null,"IsVisible":true,"InDepthLevel":0}],"Id":648,"Name":"Spar International","HasInsightsCenter":true,"ParentId":0,"UserSelected":false,"UserHasAccess":false,"Letter":"S","IsVisible":true,"InDepthLevel":0},{"RetailerChilderen":[],"Id":860,"Name":"36.6 (Pharmacy)","HasInsightsCenter":false,"ParentId":0,"UserSelected":false,"UserHasAccess":false,"Letter":"#","IsVisible":true,"InDepthLevel":0},{"RetailerChilderen":[],"Id":82926,"Name":"Ace Hardware Indonesia","HasInsightsCenter":false,"ParentId":0,"UserSelected":false,"UserHasAccess":false,"Letter":"A","IsVisible":true,"InDepthLevel":0}]')

  new Vue({
    components: { RetailerRec },
    data () {
      return { tree }
    },
    template: `<div>
      <RetailerRec v-for="retailer in tree" :retailer="retailer" :key="retailer.Id"/>
    </div>`,
    el: '#app'
  })
li{
  list-style-type:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

Answer №2

Develop a component to represent an individual item and then utilize it to generate subitems using v-for.

Consider the following example:

ItemComponent.vue

<template>
  <li>
    <div class="item-info">
      <span>{{ item.Name }}</span>
    </div>
    <ul v-if="item.RetailerChildren.length">
      <item-component v-for="(subItem, index) in item.RetailerChildren" :item="subItem" :key="index" />
    </ul>
  <li>
</template>

MainComponent.vue

<ul class="item-container">
  <item-component v-for="(item, index) in retailers" :item="item">
</ul>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Convert JSON data into an HTML table with custom styling

If you have a set of JSON data that you want to convert into an HTML table, you can use the following code: $.each(data, function(key, val) { var tr=$('<tr></tr>'); $.each(val, function(k, v){ $('<td>' ...

Guide on utilizing VueJS plugins in the browser without any added layers

I have decided to incorporate VueJS into an old system instead of using JQuery. However, I am facing difficulties in utilizing plugins like I would with JQuery. For instance, when trying to import the "vuetable" library directly into my HTML using script t ...

Guide on extracting value from XML data using $.ajax and then displaying it within a $.each loop

As part of our study project, we have a task that involves comparing an array of strings with an XML database. My approach was to break it down into two parts since we need to perform the comparison function twice. First, I iterate through the array using ...

Unable to save a URL link in MySQL database using JSON and PHP

I am seeking some insightful advice regarding my college assignment. This time around, I have to create yearbooks using Phonegap and it's my first experience working with AJAX, JSON, and JQuery Mobile. Instead of uploading an image directly into the ...

Reveal Password Feature in Angular After User Click

I am working on an inventory page that includes a password field. My goal is to initially hide the password and display it as points (****) instead. I would like the password to be revealed either when clicked or through a pop-up. JS var retrieveCert ...

Transform Dictionary JSON into Typescript model

How can I convert the provided JSON structure into a TypeScript interface to ensure type safety? { "attributes1": { "myKey1": { "myinnerKey11": { "value": "value 1", "name&q ...

The re-assignment of `req.session.variable` in Express-session does not carry over between two different routes

I am currently working on a basic app that allows logged in users to search and book train journeys using Express, MongoDB, Mongoose, and Express-session. The selected journeys are temporarily stored in the req.session.order variable (which I believe is gl ...

The callback function is not being executed in the Ajax request

$(document).ready(function(){ var requestURL = 'http://www.football-data.org/soccerseasons?callback=?'; $.ajax({ type: 'GET', dataType: 'json', url: requestURL, success: function(data){ cons ...

Retrieve JSON encoded data from a separate AJAX request

Currently utilizing prestashop 1.6, I have a specific ajax function where I encode data that is successfully retrieved on the console using echo. Now, my task is to decode this JSON data in another ajax function in order to extract a value for a particular ...

Using Angular to display asynchronous data with ngIf and observables

In cases where the data is not ready, I prefer to display a loader without sending multiple requests. To achieve this, I utilize the as operator for request reuse. <div class="loading-overlay" *ngIf="this.indicatorService.loadingIndicators[this?.indic ...

Issue occurred in module.js:341 while attempting to include android platform to ionic using command line

For my hybrid app development using the Ionic framework, I made sure to install all required dependencies like node.js and cordova. Following their Getting started guide, I reached step 3 which instructs running this command within the app directory: > ...

Rails confirmation feature malfunctioning

I have been struggling to figure out where I am going wrong with this code even though I've checked several posts. I am using Ruby on Rails and trying to run the following snippet: <%= link_to 'Destroy', article_path(article), ...

The AJAX call returned undefined, leading to an error when trying to access the length property

I've scoured various resources to find a solution for this issue, but unfortunately, I haven't had any luck with implementing the code. The problem lies with my JSON parser function, which is designed to construct a table based on data received ...

Tips for efficiently waiting for the outcome in a unified function for multiple callbacks within node.js

Perhaps the question title is not the most appropriate, but let me explain what I am trying to achieve in my code // First Callback Function connection_db.query(get_measure_query,function(err,user_data1){ if(err){ // throw err; ...

Suggestions for preventing the highlighting of the space between buttons on a webpage

html: <button id='automoney' onclick='minusTen()'></button> <button id='automoney2' onclick='minusHundred()'></button> <button id='automoney3' onclick='minusFiveHundred()& ...

Converting video titles and descriptions on YouTube | Version 3 of the API

After spending hours searching for a solution, I am still struggling to update/upload videos in multiple languages through the YouTube V3 API. I know how to set the defaultLanguage, "defaultLanguage": string I can also set the video title and description ...

A guide to resolving the issue of invalid objects as a React child in Nextjs13

Seeking help on resolving an issue in Nextjs13, where I'm encountering the error "objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead" The scenario involves fetching ...

Angular encountered a SyntaxError due to an unexpected curly brace } character

After spending a lengthy hour trying to troubleshoot this issue, I am at a loss as to why it is not functioning correctly. I have been attempting to showcase a row of images on a webpage using Angular based on data fetched from a json file. Unfortunately, ...

Recursively converting trees in JS/ES6

Currently, I am attempting to convert a tree structure provided in the following format: {"Parent": { "Child1": ["toy1"], "Child2": { "Nephew": ["toy2", "toy3"] } } } into a standardized tree form ...

Utilizing d3.js to filter a dataset based on dropdown selection

I am working with a data set that contains country names as key attributes. When I select a country from a dropdown menu, I want to subset the dataset to display only values related to the selected country. However, my current code is only outputting [obje ...