Adding and reading json data stored in vuex - vue.js

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 = '';
},

Related

Nuxt.js - Unable to output nested array elements in Nuxt.js array

I have json object but I am not able to output the nested arrays and really need some help!
Here is my script tag:
<script>
export default {
data() {
return {
mountains: []
}
},
async fetch() {
this.mountains = await fetch(
'https://api.knack.com/v1/objects/object_2/records'
, {
method: "GET",
headers: {
"X-Knack-Application-Id": "appIDhere",
"X-Knack-REST-API-KEY": "keyIDhere",
},
}).then(res => res.json())
// .then((res) => {
// console.log(res);
// })
}
}
</script>
and it gives me in my console:
{
"id": "60f648317f54bf001f516226",
"field_77_raw": {
"id": "60f6479f6bcca0001e7ebf28",
"application_id": "60da978576b89a001fbc7e36",
"s3": true,
"type": "image",
"filename": "screenshot20210625at1.38.44pm.png",
"url": "https://s3-ap-southeast-2.amazonaws.com/ap-southeast-2-assets.knack.com/assets/60da978576b89a001fbc7e36/60f6479f6bcca0001e7ebf28/original/screenshot20210625at1.38.44pm.png",
"thumb_url": "https://s3-ap-southeast-2.amazonaws.com/ap-southeast-2-assets.knack.com/assets/60da978576b89a001fbc7e36/60f6479f6bcca0001e7ebf28/thumb/screenshot20210625at1.38.44pm.png",
"size": 2621440,
"field_key": "field_77"
},
but when I do my loops in my template section I can't the thumb_url:
<template>
<div v-for="mountain of mountains.records">
{{mountain.id}}
{{mountain.field_77_raw.url}}
</div>
</template>
I just get a message: Cannot read property 'url' of undefined
If I put {{mountain.field_77_raw}} I get:
{ "id": "60f6479f6bcca0001e7ebf28", "application_id": "60da978576b89a001fbc7e36", "s3": true, "type": "image", "filename": "screenshot20210625at1.38.44pm.png", "url": "https://s3-ap-southeast-2.amazonaws.com/ap-southeast-2-assets.knack.com/assets/60da978576b89a001fbc7e36/60f6479f6bcca0001e7ebf28/original/screenshot20210625at1.38.44pm.png", "thumb_url": "https://s3-ap-southeast-2.amazonaws.com/ap-southeast-2-assets.knack.com/assets/60da978576b89a001fbc7e36/60f6479f6bcca0001e7ebf28/thumb/screenshot20210625at1.38.44pm.png", "size": 2621440, "field_key": "field_77" }
But don't know how to iterate through this nested array. I think it is an object so possibly I just don't know how to handle an object...
Thanks!
Edit:
Here is the whole json output https://codepen.io/MikedNZ/pen/JjNrJgV
Answer thanks #tony19
<template>
<div>
<div v-for="mountain of mountains.records">
{{mountain.id}}
</div>
<div v-if="mountain.field_77_raw">.
{{mountain.field_77_raw.url}}
</div>
</div>
</template>
The JSON response you posted has 8 array elements without field_77_raw, so your template needs to conditionally render that field with v-if.
Also, I don't see the records key in the data. If the API response is just an array, you're assigning the response directly to this.mountains, so the v-for should iterate mountains (not mountains.records).
<div v-for="mountain of mountains">
{{mountain.id}}
<template v-if="mountain.field_77_raw">
{{mountain.field_77_raw.url}}
</template>
</div>
demo

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.

VueJS - Auto create a A-Z letters list from the data

Is it possible to create a A-Z letters list (like this) from the data from a API and Vue to be able to determine if a property in a data contains a name that starts with what letter. If the data doesn't contain a specific letter name then remove/disable the href attribute from the letter anchor tag.
In the linked example, letters K, X and Z are missing coz they don't have the data
JSON
[
{
"id": 77,
"link": "http://my-site/cosmoquotes/authors/anonymous/",
"name": "Anonymous",
"slug": "anonymous"
},
{
"id": 72,
"link": "http://my-site/authors/ferdinand-marcos/",
"name": "Ferdinand Marcos",
"slug": "ferdinand-marcos"
},
{
"id": 75,
"link": "http://my-site/authors/john-f-kennedy/",
"name": "John F. Kennedy",
"slug": "john-f-kennedy"
},
{
"id": 67,
"link": "http://my-site/authors/john-maxwell/",
"name": "John Maxwell",
"slug": "john-maxwell"
}
]
Component
export default {
data() {
return {
authorsRequest: {
type: 'authors',
params: {
per_page: 100
}
},
}
},
computed: {
authors () {
return this.$store.getters.requestedItems(this.authorsRequest)
},
},
methods: {
getAuthors() {
return this.$store.dispatch('getItems', this.authorsRequest)
},
},
created() {
this.getAuthors()
}
}
So as per the returned data, only the letters 'A', 'F' and 'J' should be clickable/displayed.
I managed to do it like this,
unfortunatly it needs the authors array and the conditionnal function to be outside of the Vue component because I couldn't find how to pass argument to computed values
But since I'm new to vue (didn't even finish reading the introduction) I'm sure there has to be a better solution
EDIT: found the way to have the function in the component with methods, I could then move the data in the component too
let a = new Vue({
el: "#selector",
data: {
authors: [{"id": 77,"link": "http://my-site/cosmoquotes/authors/anonymous/","name": "Anonymous","slug": "anonymous"},{"id": 72,"link": "http://my-site/authors/ferdinand-marcos/","name": "Ferdinand Marcos","slug": "ferdinand-marcos"},{"id": 75,"link": "http://my-site/authors/john-f-kennedy/","name": "John F. Kennedy","slug": "john-f-kennedy"},{"id": 67,"link": "http://my-site/authors/john-maxwell/","name": "John Maxwell","slug": "john-maxwell"}]
},
computed: {
// there have to be a way to get this array without doing it like this but I don't know it ^^
letters() {
let letters = []
for(let i = "A".charCodeAt(0); i <= "Z".charCodeAt(0); i++) {letters.push(String.fromCharCode([i]))}
return letters
}
},
methods: {
// you may add a toUpperCase()/toLowerCase() if you're not sure of the capitalisation of you datas
isALink(letter) {
return this.authors.some(aut => aut.name.startsWith(letter))
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="selector">
<template v-for="letter in letters">
<a v-if="isALink(letter)" :href="letter">{{ letter }}</a>
<a v-else>{{ letter }}</a>
</template>
</div>
you can set the unique name as the id of dom. when you click to letter X, just get the first name start with X , and use getElementById to match the dom and scroll to the dom.

How get the data from an array like this with axiosjs

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>

Plotting multiple Points from html spans in ArcGIS

I'm trying to plot multiple Points on an ArcGIS map using span#longitude and span#latitude in the HTML. I can get the very first point to plot, but not any subsequent points.
I'm new to ArcGIS, and my javascript knowledge is limited. Any help is appreciated!
<script>
var map, agraphicsLayer, symbol;
function addPointtoMap(x, y) {
require([
"esri/geometry/Point",
"esri/graphic",
"dojo/domReady!"],
function(Point, Graphic) {
var pt = new Point(x, y);
map.centerAt(pt);
agraphicsLayer.add(new Graphic(pt, symbol));
});
}
(function($) {
if($("div#mapDiv").length) {
$.getScript( "http://js.arcgis.com/3.14/" )
.done(function( script, textStatus ) {
require(["esri/map",
"esri/symbols/SimpleMarkerSymbol",
"esri/geometry/Point",
"esri/graphic",
"esri/Color",
"esri/layers/GraphicsLayer",
"dojo/domReady!"
],
function(
Map,
SimpleMarkerSymbol,
Point,
Graphic,
Color,
GraphicsLayer) {
map = new Map("mapDiv", {
center: [-56.049, 32.485],
zoom: 5,
basemap: "topo",
logo: false
});
map.on("load", function() {
map.disableScrollWheelZoom();
});
agraphicsLayer = new GraphicsLayer();
map.addLayer(agraphicsLayer);
symbol = new SimpleMarkerSymbol();
symbol.setColor(new Color("#00ADA1"));
var pt = new Point($("span#longitude").html(), $("span#latitude").html());
map.centerAt(pt);
agraphicsLayer.add(new Graphic(pt, symbol));
});
})
.fail(function( jqxhr, settings, exception ) { });
}
</script>
<div id="mapDiv"></div>
<span id="longitude">37.82</span>
<span id="latitude">-2.28</span>
<span id="longitude">34.82</span>
<span id="latitude">1.36</span>
<span id="longitude">34.31</span>
<span id="latitude">-0.67</span>
<span id="longitude">40.19</span>
<span id="latitude">.10</span>
in both the HTML 4.01 and HTML 5 specifications the "id" attribute must be unique among all the IDs in the document so
$("span#longitude").html()
is only ever going to give you the first longitude (or at least it's not going to give you what you want which is to loop through all the lat/longs)
There's are a lot of ways to accomplish your goal. One way is to store the lat/longs in your javascript instead of in the HTML.
you would do that like so
<script>
var map, agraphicsLayer, symbol,
data = {"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [37.82, -2.28]
}},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [34.82, 1.36]
}},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [34.31, -0.67]
}},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [40.19, 0.10]
}}]
};
...code snipped for brevity
//here you want to loop through the points
data.features.forEach(function(feature){
var pt = new Point(feature.geometry.coordinates, map.spatialReference);
agraphicsLayer.add(new Graphic(pt, symbol));
})
</script>
if you really want to store the data in spans like you are now then you need to change the "id" attribute to a "class" attribute and then wrap the lat/long spans in some grouping element like a div or another span
<div class="coordinate">
<span class="longitude">37.82</span>
<span class="latitude">-2.28</span>
</div>
and then in the javascript do something like this
$(".coordinate").each(function(){
//this refers to each "coordinate" div as we loop through them
var long = $(this).find(".longitude").html()
var lat = $(this).find(".lattitude").html()
var pt = new Point(long, lat);
//etc
})