How get the data from an array like this with axiosjs - vue.js

I connected to a URL using Axios using this:
getUsers: function() {
axios.get(urlUsers).then(response => {
this.lists = response.data
});
and get this data:
"lists": [
{
"name": "Destacados",
"tags": [
"Aguila"
],
"isRoot": true,
"products": [
{
"name": "Coors",
"code": "139017",
And tryng to list products.
How?

You can use v-for to render lists. In your case you have a nested array so you would need to do it twice. However I think you should change your data element 'lists' and remove all the excess quotes ("") so it looks like this:
lists: [
{
name: "Destacados",
tags: [
"Aguila",
],
isRoot: true,
products: [
{
name: "Coors",
code: 139017,
},
{
name: "Bud",
code: 139019,
}
],
}
]
and then run your v-for loops:
<template>
<div v-for="list in lists" :key="list.name">
<ul v-for="product in list.products :key="product.name">
<li>{{product.name}}</li>
<li>{{product.code}}</li>
</ul>
</div>
</template>

Related

Adding and reading json data stored in vuex

I have a vuex store and i am adding some josn data and this is the format.
[
{
"id":1,
"firstname": "toto",
"lastname": "titi"
},
{ "id":2,
"firstname": "one",
"lastname": "two"
}
]
I am adding the data on an on click action and this is the action method
addLink: function() {
var dt = '[{"id":1,"firstname":"xx","lastname": "yy"},{"id":2,"firstname": "one","lastname": "two"}]';
this.ADD_LINK(dt)
this.newLink = '';
},
The data is getting added to the store and i can access it like this
computed: {
users(){
return this.countLinks;
}
}
I can display the data this way {{users}} and this is getting displayed. This is because i clicked twice and added the json twice.
[ "[{\"id\":1,\"firstname\":\"xx\",\"lastname\": \"yy\"},{\"id\":2,\"firstname\": \"one\",\"lastname\": \"two\"}]", "[{\"id\":1,\"firstname\":\"xx\",\"lastname\": \"yy\"},{\"id\":2,\"firstname\": \"one\",\"lastname\": \"two\"}]" ]
However, when i try to use v-for
<ul id="users">
<li v-for="user in users" :key="user.id">
{{ users.firstname}}
</li>
</ul>
i cannot display any data and i have no error. How can i display the data saved in vuex?.
You can create a computed property that returns the objects in one list parsed as JSON:
new Vue({
el:"#app",
data: () => ({
users: [ "[{\"id\":1,\"firstname\":\"xx\",\"lastname\": \"yy\"},{\"id\":2,\"firstname\": \"one\",\"lastname\": \"two\"}]", "[{\"id\":1,\"firstname\":\"xx\",\"lastname\": \"yy\"},{\"id\":2,\"firstname\": \"one\",\"lastname\": \"two\"}]" ]
}),
computed: {
usersList: function() {
return this.users.flatMap(userList => JSON.parse(userList));
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ul id="users">
<li v-for="(user, index) in usersList" :key="index">
{{ user.firstname}}
</li>
</ul>
</div>
Note: Since ids are not unique in your example, you can use an index in v-for as the key. Also, to show the first name, you need to use the user object.
Another solution: Parse dt in the store and use Array#concat to add the elements as objects to the initial list:
let countLinks = [
{ "id":1, "firstname": "toto", "lastname": "titi" },
{ "id":2, "firstname": "one", "lastname": "two" }
];
function ADD_LINK(dt) {
countLinks = countLinks.concat(JSON.parse(dt));
}
const dt = '[{"id":1,"firstname":"xx","lastname": "yy"},{"id":2,"firstname": "one","lastname": "two"}]';
ADD_LINK(dt);
console.log(countLinks);
you have to store the data as is, rather than converting into string
addLink: function() {
var dt = [
{
"id":1,
"firstname": "xx",
"lastname": "yy"
},
{
"id":2,
"firstname": "one",
"lastname": "two"
}
];
// remove the single quote from the above array
this.ADD_LINK(dt)
this.newLink = '';
},
In case you are getting the var dt from external source then you should consider converting into valid js json format using this:
addLink: function() {
var dt = '[{"id":1,"firstname":"xx","lastname": "yy"},{"id":2,"firstname": "one","lastname": "two"}]';
// parse it to json format
var parsedDt = JSON.parse(dt);
// add the `parsedDt`
this.ADD_LINK(parsedDt)
this.newLink = '';
},

Hierarchical dynamic loaded components with children distributed along dynamic named slots

We're creating an app where the interface is dynamically mounted based on a JSON returned by an API. It looks like this:
{
"path": "Container",
"children": [
{
"slot": "default",
"path": "Banner",
"props": {
"items": [ "image1.jpg", "image2.jpg", "image3.jpg" ]
}
},
{
"slot": "header",
"path": "Flex",
"props": {
"flow": "row"
},
"children": [
{
"slot": "default",
"path": "Icon",
"props": {
"name": "mdi-forum"
}
},
{
"slot": "default",
"text": "Example of title"
}
]
}
]
}
So I created a dynamic ComponentLoader with a computed doing a dynamic import, then I also inject more dynamic component loaders recursively as needed, using a v-for through the children list:
<template>
<component v-if="component" :is="component" v-bind="$attrs">
<template v-for="(child, i) of children">
<ComponentLoader
v-if="child.path"
v-bind="child.props"
:key="`${child.path}-${i}`"
:path="child.path"
:children="child.children"
/>
<template v-else>{{ child.text || '' }}</template>
</template>
</component>
</template>
<script>
import Error from '~/components/ComponentLoaderError.vue'
export default {
name: 'ComponentLoader',
components: { Error },
props: {
path: { type: String, required: true },
children: { type: Array, default: () => [] },
},
computed: {
component() {
if (!this.path) return null
return () => import(`~/components/${this.path}`).then((m) => m || m.default).catch(() => Error)
},
},
}
</script>
It's almost working, but all children gone injected to the default slot of each loaded component, which makes all sense since I'm not informing the desired slot during the loop through the children.
Inspired in this answer, I added a v-slot bind on the <template> with the v-for, using Dynamic Slot Names to inject on the right slot based in the child.slot property already received from the JSON:
<template v-for="(child, i) of children" #[child.slot]>
For nodes with only one child to be distributed on each slot, it's working as expected. But when I have more children to be distributed in the same slot (like the last children array in that JSON), only the last child is injected, overriding others before.
So, how to inject many children to dynamic named slots inside a loop?

v-for different object properties and accessing array of objects inside it

In my application I am receiving object as below :
{
"data1":[
{},{}{}
],
"data2":[ {},{},{}....],
"data3":[ {},{},{}.....]
}
If someone can help me on how to use v-for here? I want to loop through "data1", "data2"... using v-for. ( in sinlge v-for precisely )
UPDATE:I would like to have object like this.
data :[{
title :"data1",
values: [{ } {} {}]
},
{
title :"data1",
values: [{ } {} {}]
},
.....
]
You can do something like this :
<div id="app">
<h2>Todos:</h2>
<div v-for="t1 in todos.todos1">
<label>{{t1.text}}</label>
</div>
<div v-for="t2 in todos.todos2">
<label>{{t2.text}}</label>
</div>
<div v-for="t3 in todos.todos3">
<label>{{t3.text}}</label>
</div>
</div>
new Vue({
el: "#app",
data: {
todo:{},
todos:{todos1: [
{ text: "Learn JavaScript 1", done: false },
{ text: "Learn Vue 1", done: false }
],
todos2: [
{ text: "Play around in JSFiddle 2", done: true },
{ text: "Build something awesome 2", done: true }
],
todos3: [
{ text: "Learn Vue 3", done: false },
{ text: "Play around in JSFiddle 3", done: true },
]
}
},
created(){
this.todo = Object.values(this.todos)
console.log(this.todo)
}
})
You can do something like
<div v-for="(value, propertyName, index) in items"></div>
WARNING
When iterating over an object, the order is based on the enumeration order of Object.keys(), which is not guaranteed to be consistent across JavaScript engine implementations.
The above can be found on the Vue Documentation.

Vue select with deep nested data

I'm trying to make a v-select according to instruction on official documentation but my data is more nested than it shown in documentation, i can not show in my v-select the llcName of my data, and i'm stuck with this.
This is my html div and Vue instance with data below
<div id="vs">
<h1>Vue Select</h1>
<v-select multiple :options="options" :reduce="node=> node.llcName" label='llcName' v-model='selected' />
<pre>[[$data]]</pre>
</div>
<script>
Vue.component('v-select', VueSelect.VueSelect)
new Vue({
el: '#vs',
delimiters: ["[[", "]]"],
data: {
options: [
{
"node": {
"id": "U3VwcGxpZXJPYmplY3Q6MzA1",
"llcName": "new",
"suppPayment": {
"edges": [0]
}
}
},
{
"node": {
"id": "U3VwcGxpZXJPYmplY3Q6MzA2",
"llcName": "new2",
"suppPayment": {
"edges": [1]
}
}
},
{
"node": {
"id": "U3VwcGxpZXJPYmplY3Q6MzA3",
"llcName": "rteer",
"suppPayment": {
"edges": [2]
}
}
}
],
selected:"",
}
})
</script>
I think you should use getOptionLabel instead of label and there is a mistake in your reduce property.
<v-select
multiple
v-model='selected'
:options='options'
:get-option-label='option => option.node.llcName'
:reduce='option => option.node.llcName'/>
Fiddle

Using ternary operator to render correct template in component

I'm trying to use conditional (ternary) operator to decide upon two template strings inside component's template property.
I am passing down list of jobs to my component:
<jobs :title="this.data.titles['experience']" :data="this.data.jobs"></jobs>
and here is my job and jobs component:
Vue.component('jobs', {
props: ['title', 'data'],
template: `<section id='jobs'>
<header>{{ title }}</header>
<job v-for="(job, index) in data" :job="job" :key="index"></job>
</section>`
})
Vue.component('job', {
props: ['job'],
template: job.hasOwnProperty('phases') && job.phases.length > 0
? `<p>A</p>`
: `<p>B</p>`
})
For some weird reason loop prints paragraph A even when list of jobs are:
[
{
"phases": [
{
"title": "Title 2"
},
{
"title": "Title 1"
}
],
"workPlace": "Company B"
},
{
"title": "Title 1",
"workPlace": "Company A"
}
]
I haven't conditionally rendered templates like that before, so not sure if it's good practice.
If you do it like this, does it work?
Vue.component('job', {
props: ['job'],
template: `
<p v-if="job.hasOwnProperty('phases') && job.phases.length > 0">A</p>
<p v-else>B</p>
`
})