How to read deep JSON data using Vuejs and Axios - vue.js

How would I read deep JSON data nested deep inside a file? I've tried different methods and can't seem to get this to work.
<template>
<div>
<div v-for="edu in info" :key="edu">
<div>{{ edu.section.title }}</div> // this is what im trying to get to work
</div>
<div class="card container">
{{ info }}
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
info: null
}
},
mounted() {
axios
.get('./calculus.json') // Data Below
.then(response => (this.info = response.data.edu))
.catch(error => console.log(error))
}
}
</script>
My JSON looks like this:
{
"edu": {
"1": {
"title": "Title One",
"subtitle": "Subtitle One",
"description": "Description One",
"section": {
"1": {
"title": "Section One Title",
"content": "Section One Content"
}
}
},
"2": {
"title": "Title Two",
"subtitle": "Subtitle Two",
"description": "Description Two",
"section": {
"1": {
"title": "Section One Title",
"content": "Section One Content"
}
}
}
}
}
How can I use vue-for and get the data inside the section to get it to display under the title? For example: title, section>title, section>subtitle, etc.

Given each section is also an object with weird numeric keys, you can iterate them in the same way you do info.
I would also advise you to use identifiable values instead of the entire edu object in your :key bindings.
<div v-for="(edu, eduId) in info" :key="eduId">
<div v-for="(section, sectionId) in edu.section" :key="sectionId">
{{ section.title }}
</div>
</div>
If possible, I would alter the format of your JSON data to use actual arrays instead of objects with numeric keys.

One way to browse your object deeply is to cumulate v-for on your object (and children) entries.
ie:
<div v-for="([category, books], catkey) in Object.entries(info)" :key="`category-${catkey}`">
<div>{{ category }} :</div>
<div v-for="([num, book], numkey) in Object.entries(books)" :key=`book-${catkey}-${numkey}`>
<div v-for="([field, value], valkey) in Object.entries(book)" :key=`field-${catkey}-${numkey}-${valkey}`>
{{ field }} : {{ value }}
</div>
</div>
</div>
If you find it too verbose, you may try to flatten your computed data to have the following structure:
[
{
"category": "edu",
"id": "1",
"title": "Title One",
"subtitle": "Subtitle One",
"description": "Description One",
"section": {
"1": {
"title": "Section One Title",
"content": "Section One Content"
}
}
}
]

Related

Nesting in VueDraggable is not not working

here's my problem :
I'm using the VueDraggable library in order to drag and drop elements between a DragBoard.vue and a DropBoard.vue, and a specific type of element should allow to be nested when it is in the DropBoard.
I'm going to take this element as an example :
"Grouped Items"
To do that I've followed this example : https://github.com/SortableJS/vue.draggable.next/blob/master/example/components/nested-example.vue
And this is what I get when I drop "Grouped Items" into the DropBoard.vue :
IMG
As you can see, the DropBoard appears a second time inside Grouped items for whatever reason. I've supposed that the nested-draggable tag also loop what is out of the draggable tag and I've no idea how to resolve that...
📄 dragItems.JSON (used in DragBoard.vue) :
1st object is a common element
2nd object is a nestable element
[
{
"type": "Simple list",
"title": "Simple list",
"id": 1,
"properties": "this is an item property"
},
...
{
"type": "Grouped items",
"title": "Grouped items",
"id": 10,
"properties": "this is an item property",
"tasks": []
},
...
]
🚩 DropBoard.vue template:
<template>
<div class="board">
<div class="head">Mock</div>
<div class="dd-container">
<draggable
:list="tasks"
v-model="dropItems"
item-key="title"
:group="{ name: 'items', put: true }"
#change="log"
>
<template #item="{ element }">
<div
class="item"
:key="element"
>
<div>
{{ element.title }}
</div>
<nested-draggable
v-if="element.tasks"
:tasks="element.tasks"
class="group-container"
/>
<div class="trashico" :key="index">
<i class="fas fa-trash" #click="deleteItem(index)"></i>
</div>
</div>
</template>
</draggable>
</div>
</div>
</template>
🚩 DropBoard.vue script
<script>
import draggable from "vuedraggable";
export default {
name: "nested-draggable",
components: {
draggable,
},
props: {
dropItems: {
type: Array,
required: true,
},
tasks: {
required: true,
type: Array,
},
},
data() {
return {
dropItems: [],
};
},
methods: {
deleteItem(id) {
this.dropItems.splice(id, 1);
},
},
};
</script>
Here is what I found while using the Vue DevTools, it's quit explicit about the problem.
See image: IMG

Checking if something exists in json in Vue

I've got a json API that I'm using like this:
[{
"name": "Thing",
"id": 1234,
"total": 1,
"stock": [
{
"size": "Small",
"id": 1,
"count": 10
},{
"size": "Medium",
"id": 2,
"count": 5
},{
"size": "Large",
"id": 3,
"count": 5
}
]
}]
I'm looping over these in Vue, but want to check if anything exists in the 'stock' element outside of the v-for loop.
I can use v-if to check if the overall json exists, but can't seem to narrow it down to checking if the stock element contains anything.
Any pointers?
What about a v-if & v-else condition on the length of the stocks array? If the length is greater than zero we have stocks, so display them, else, display a message. Something like this.
Vue.component('your-component', {
template:
`
<div v-for="(item, i) in items" :key="i">
<p>{{ item.name }}<p>
<p>{{ item.id }}<p>
<div v-if="item.stock && item.stock.length > 0">
<p v-for="(stock, j) in item.stock" :key="j">
There'are {{ stock.count }} of size {{ stock.size }}.
<p>
</div>
<div v-else>
Ops... stocks not available.
</div>
</div>
`,
data () {
return {
items: []
}
},
created () {
fetch('your-api')
.then((res) => res.json())
.then((res) => { this.items = res })
}
})

V-for is not iterating through objects

I have an array of coupon objects named offers:
[{ "coupon":
{ "id": "1", "name": "Coupon 1" }
},
{ "coupon":
{ "id": "2", "name": "Coupon 2" }
}]
And i try to iterate trough it like this:
<div v-for="(coupon, $index) in offers" :key="$index">
<p>{{coupon.id}}</p>
</div>
The problem is that div does not iterate anything.
<div v-for="{ coupon } in offers" :key="coupon.id">
<p>{{ coupon.name }}</p>
</div>
Dont use index as key
you have to travel through the object, the First coupon is an element name so try this. This should work
div v-for="(coupon, $index) in offers" :key="$index">
<p>{{coupon.coupon.id}}</p>
</div>

Add dynamically data-bound text in Vue.js

My case must be weird, but I have a good for it.
Here's my situation:
I have a Vue app that renders a form based on a json.
For example, the JSON:
{
"fields": [{
"name": "firstName",
"title": "Name"
}, {
"name": "lastName",
"title": "Last Name"
}, {
"title": "Hello {{ firstName }}!"
}]
}
From that json, the final render has to be:
<input type="text" name="firstName" v-model="firstName" />
<input type="text" name="lastName" v-model="lastName" />
<p>Hello {{ firstName }}</p>
I'm able to render all of that, except for the <p> which is rendered as raw {{ firstName }} and not data-bound/reactive.
My question is:
How do I insert dynamic templates (can come from a Rest API) into the component, and make them have the full power of the mustache expressions.
The component will have something like
{...firstName field...}
<dynamic template will be added here and update whenever firstName changes>
Please let me know if I'm not too clear on this issue
Thank you!!!
Is this the sort of thing you're trying to do? I've created a dynamic component whose template is generated from a JSON string which is editable.
new Vue({
el: '#app',
data: {
componentData: {
firstName: 'Jason',
lastName: 'Bourne',
},
jsonString: `
{
"fields": [{
"name": "firstName",
"title": "Name"
}, {
"name": "lastName",
"title": "Last Name"
}, {
"title": "Hello {{ firstName }}!"
}]
}`
},
computed: {
template() {
const json = JSON.parse(this.jsonString);
return json.fields.map((s) => {
if ('name' in s) {
return `<input type="text" name="${s.name}" v-model="${s.name}">`;
}
return s.title;
}).join('\n');
},
componentSpec() {
return {
template: `<div>${this.template}</div>`,
data: () => this.componentData
};
}
}
});
<script src="https://unpkg.com/vue#latest/dist/vue.js"></script>
<div id="app">
<textarea rows="16" cols="40" v-model.lazy="jsonString">
</textarea>
<component :is="componentSpec"></component>
</div>

Vue,js Display data from json

How to fetch the product name from the below result. I tried
<div class="card-divider">
{{ post.basic_info.prod_name }}
</div>
But it is not working
Many thanks
{
"name":"Test ProductCategory",
"updated":"2018-07-16 15:00:03",
"12":{
"basic_info":{
"prod_name":"Product name 1",
"status":"Active",
"image":""
},
},
"13":{
"basic_info":{
"prod_name":"Product name 2",
"status":"Active",
"image":""
},
}
}
Try this:
{{ post["12"].basic_info.prod_name }}
Your JSON have two same keys, so you will receive Product name 2 only, because, latter will replace previous key "12"
My suggestion, modify data to receive something like:
{
"name": "Test ProductCategory",
"updated": "2018-07-16 15:00:03",
"data": [
{
"basic_info": {
"prod_name": "Product name 1",
"status": "Active",
"image": ""
},
}, {
"basic_info": {
"prod_name": "Product name 2",
"status": "Active",
"image": ""
},
}
]
}
you can loop over data and get basic_info.prod_name then your html will be like:
<div class="card-divider" v-for="obj in post.data">
{{ obj.basic_info.prod_name }}
</div>