0

I currently have a set of nested templates that loops through JSON. It outputs the key, checks if the value is not an object, outputs the value if it's not an object, otherwise it goes deeper and traverses the inner object/array for that property. It goes about 3 layers deep currently, but may potentially have to go further.

This makes it a good candidate for recursion. I'm new to front-end languages/frameworks, and I am having trouble finding good resources on finding a good resource for how to traverse JSON dynamically with Vue. This was the best I could, but I'm not using predictable properties like label/node/nodes.

I guess a good place to start would be the Vue.component template. How do I pass in the JSON from the main Vue instance, and then how do I set the template to dynamically traverse the JSON?

HMTL

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Vue: Recursion</title>

  <!-- CDNs -->
  <script
  src="https://code.jquery.com/jquery-3.3.1.min.js"
  integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
  crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>

  <!-- JS -->
  <script src="app.js" charset="utf-8"></script>
</head>
<body>

  <main id="app">
    <template>
      <section>
        <recursive-component></recursive-component>
      </section>
    </template>
  </main>

</body>
</html>

Javascript

$(function () {
  // Get JSON
  $.getJSON("./data.json", function (json) {
    app.json = json
  });


  Vue.component('recursive-component', function() {
    template: `
      <recursive-component
       v-if="node !== null"
       v-for="(node, key) in nodes"
       :nodes="node.nodes"
       :key="node.key"
       >
      </recursive-component>`
  });

  var app = new Vue({
    el: `#app`,
    data: {
      json: null
    }
  });
});

Generic JSON

{
  "details": {
    "manufacturer": "BMW",
    "seats": 4,
    "engine": {
      "torque": 500,
      "hp": 600
    },
    "breaks": {
      "front": {
        "type": "XYZ",
        "capacity": 1234
      }
    }
  }
}
2
  • Are you saying you have some json data, and you want to "import" the data into your Vue instance so you can make us of it? Commented Mar 6, 2018 at 2:39
  • I already have the data in the Vue Instance with the getJSON function setting the instance variable. I am wanting to know how to build a recursive template to output the data. Commented Mar 6, 2018 at 3:04

1 Answer 1

1

The key of the solution is just checking if the data is a value or an object, I made this example assuming values are only numbers and strings (because to check if variable is an object is quite complicated StackOverflow), then the recursive component just displays the key/value accordingly.

const jsonData = {
  "details": {
    "manufacturer": "BMW",
    "seats": 4,
    "engine": {
      "torque": 500,
      "hp": 600
    },
    "breaks": {
      "front": {
        "type": "XYZ",
        "capacity": 1234
      }
    }
  }
};

Vue.component("my-recursive-component", {
  template: '#my-recursive-component',
  props: ["depth", "payload"],
  data() {
  },
  computed: {
    indent() {
      return { transform: `translate(${this.depth * 10}px)` }
    },
    type() {
      if (typeof this.payload === "string" || typeof this.payload === "number") {
        return "value";
      }
      return "obj";
    },
    list() {
      if (this.type === "obj") {
        return Object.keys(this.payload);
      }
      return undefined;
    }
  }
});

const app = new Vue({
  el: "#app",
  data() {
    jsonData
  },
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>

<div id="app">
  Recursive Component Demo:
  <my-recursive-component
    :payload="jsonData"
    :depth="0"
  >
  </my-recursive-component>
</div>

<script type="text/x-template" id="my-recursive-component">
  <div>
    <div 
      v-if="type === 'obj'" :style="indent">
      <div v-for="item in list">
        Key: {{item}}
        <my-recursive-component
          :payload="payload[item]"
          :depth="depth + 1"
          >
         <my-recursive-component/>
       </div>
    </div>
    <div 
      v-if="type === 'value'" :style="indent">
      Value: {{payload}}
    </div>
  </div>
</script>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.