Get multiple values from array fetch - vue.js

I am sending a get request to a api where the values are inside a array.
I want to get multiple values simultaneously.
How can I do this other than using index to get specific key values?
For example below, I want every result of results.data.message.body.artist_list.[4].artist.artist_name but don't want to have to use index [4].
methods: {
fetchMusic(e) {
if (e.key === 'Enter') {
// eslint-disable-next-line no-undef
axios.get(' ... ', {
headers: {
'Access-Control-Allow-Origin': '*',
},
})
.then((response) => response).then(this.setResults);
}
},
setResults(results) {
this.artists = results.data.message.body.artist_list.[4].artist.artist_name;
this.artistname = results.data.message.body.artist_list[0].artist.artist_name;
},
},
};
</script>
Thanks for any inputs on my code

Here is an example on how to fetch an API and display it's info by looping on the items: https://codesandbox.io/s/lucid-currying-nsoo3?file=/src/App.vue
Basically, get the results (an array so), then loop on each iteration of this array and display the wished data accordingly with something like
<div v-for="result in fetchedResults" :key="result.id">
<p>
<span>Name: {{ result.username }}</span> ~
<span>email: {{ result.email }}</span>
</p>
</div>
Btw, don't forget the key, it's important. More info here about this point.
Official documentation's examples on how to loop on an array.

Related

How do I split up an array while still selecting all items?

Let's say I have an array of fruits and an empty basket array. I push the fruits to the basket and loop through the basket in the template. I can output the whole array of fruits inside the basket.
<template>
<div v-for="fruit in basket">
<li>{{ fruit }}</li>
</div>
<button #click="addFruit">Add to basket</button>
</template>
<script>
data() {
return {
fruits: ['Orange', 'Apple'],
basket: [],
};
},
methods: {
addFruit() {
this.basket.push(this.fruits);
},
}
</script>
But what if I want each individual fruit to be shown as a list item? As it is right now I output the entire array of fruits.
I know that I can easilly get the individual fruits by saying
<li>{{ fruit[0] }}</li>
But that would not be practical as it requires a lot of manual work.
When I am pushing the fruits, I am looking for a way to also split them up, so that when I fire the addFruit function, I add all the fruits, but I add them as individual items.
I know there are other ways to do this, but I specifially want to know how I do this while keeping the arrays and the push method.
EDIT: I tried to write the fruit example because I wanted to keep it as simple as possible, but I will include my own code then.
In my code, I fetch an array of data from my database. I store the data results in a const called recipients. That is then pushed into an array called defaultTags. So I push an array of data into an empty array, in this case a list of emails and other contact information, which is then outputted as a tag, but what I want is to actually output the data as individual items. So instead of having one big tag that stores the whole array. Eg: [email1, email2, email3], I wish to have a seperate tag for each email in the array.
load() {
switch (this.entityType) {
case 'TENANCY':
userService.getCurrentUser().then(userResult => {
tenancyService.getTenants(this.entityId).then(result => {
const defaultTags = [];
const recipients = result.data
.map(tenant => tenant.legalEntity)
.filter(legalEntity => legalEntity.email || (!legalEntity.email && this.asNotification ? legalEntity.name : null))
.map(legalEntity => ({
emailAddress: legalEntity.email || (!legalEntity.email && this.asNotification ? legalEntity.name.concat(' ', `(${this.$t('letterMail').toLowerCase()})`) : null),
legalEntityId: legalEntity.id
}));
if (recipients.length) {
defaultTags.push(this.setText({description: this.$t('tenants'), recipients}));
}
this.autocompleteItems.push(...defaultTags);
if (this.includeUser) {
defaultTags.push(this.setText({
description: this.$t('user'),
recipients: [{emailAddress: userResult.data.email}]
}));
}
if (this.prefill) {
this.tagsChanged(defaultTags);
}
tenancyService.getUnits(this.entityId).then(result =>
result.data.forEach(unitTenancy => this.addPropertyContactsToAutocompleteItems(unitTenancy.unit.propertyId)));
});
});
break;
case 'UNIT':
unitService.get(this.entityId).then(result =>
this.addPropertyContactsToAutocompleteItems(result.data.propertyId));
break;
case 'PROPERTY':
this.addPropertyContactsToAutocompleteItems(this.entityId);
break;
}
},
I am focusing specifically on this line:
if (recipients.length) {
defaultTags.push(this.setText({description: this.$t('tenants'), recipients}));
}
It outputs the entire fruit items because you are pushing the whole array into the basket array, not the actual items. Saying basket is an array of array, not an array of fruits.
// Instead of this
this.basket.push(this.fruits); // [['Orange', 'Apple']]
// Use array destructuring
this.basket.push(...this.fruits); // ['Orange, 'Apple']
// Or concat
this.basket.concat(this.fruits); // ['Orange, 'Apple']

Vuejs Filter add Span

I'm filtering with vuejs, only the output I want is written in the ".00" span in the comma. how can i do it?
html
1.500 ,00
component
<p class="amount">{{ 1500 | toTL }}</p>
filter
Vue.filter('toTL', function (value) {
return new Intl.NumberFormat('tr-TR', { currency: 'TRY', minimumFractionDigits: 2}).format(value);
});
output
1.500,00
I declared you value in the data() function like so :
data () {
return {
number: '1500,00',
newNumber: [],
}
},
What I did to make this work is make a created function like so :
created() {
this.newNumber = this.number.split(',')
},
Then, in the frontend (your p and span) :
<p>{{ newNumber[0] }}<span>,{{newNumber[1]}}</span></p>
What I did is turn a value into an array by using the split() function.
There is probably a way better solution but this is what I came up with in a short amount of time, I hope it helps.

VueJS2: How to pluck out one property of an array and use it to find matching value in the second array?

I have two arrays. I am trying to pluck out a property from one array and use it to find the value of another property in the other way. How to do this? Let me explain:
I have an array of objects that looks like so:
languageCodes:
{
"code1234char3": "mdr",
"name": "Mandar",
},
{
"code1234char3": "man",
"name": "Mandingo",
},
{
// etc...
},
I have another array of objects that looks like so:
divisionLanguages:
[
{
p_uID: 1,
nameLang3Char: 'mdr',
},
{
p_uID: 2,
nameLang3Char: 'man'
},
{
// etc..
}
]
I have a Vue template with an unordered list like so:
<ul v-for="x in divisionLanguages" :key="x.p_uID">
<li>Name: FOO
<li>Language: {{x.nameLang3Char}} - XXX</li> <--how to get 'name' value from 'languageCodes' and place here?
</ul>
Expected output should be:
Name: FOO
Language: mdr - Mandar
Name: BAR
Language: man - Mandingo
I tried to do something like in Vue SFC template (but did not work):
<li>Language: {{ languageName(x.nameLanguage3Char) }}</li>
...
methods: {
languageName(nameLanguage3Char) {
const name = this.divisionLanguages.filter(x => x.code6392char3 === nameLanguage3Char)
return name.name
}
I hope this makes sense of what I am trying to do.
Update: Thanks to #kellen in the comments, I change from filte() to find() like so:
languageName(nameLang3Char) {
const languageName = this.languageCodes.find(
x => x.code1234char3 == nameLang3Char
)
return languageName
},
and in I did:
<li>Language: {{ languageName(x.nameLang3Char).name }}</li>
and it works...but I get error in console:
Error in render: "TypeError: Cannot read property 'name' of undefined"
Have you tried combining these arrays before rendering them? If you were able to combine both objects before creating that list, that would make your life easier. Another thing I noticed is you're using filter, when find might be a better option to return a single value rather than an array. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

Is it possible to query data while rendering and return its result

When below object is rendered I can do for example something like this:
<div v-for="(card, groupIndex) in cards" v-bind:key="card.id">
<div> {{cards[groupIndex].group.length}} </div>
</div>
This will give me the length of each group and render this in a div
With below object this will result in 2 divs of which the first will show 4
[
{
"id":"BdSxtZL8V4S576i2BTRs",
"group_name":"nameA",
"group":[{
"back":"blabla,
"delayed_till":{"nanoseconds":0,"seconds":1576729260},
"examples":[{
"answer":"blabla",
"example":"blabla"
}],
"front":"blabla"
},
{
"back":"blabla",
"delayed_till":{"nanoseconds":0,"seconds":1095337800},
"examples":[{
"answer":"blabla",
"example":"blabla"
}],
"front":"blabla"
},
{
"back":"blabla",
"delayed_till":{"nanoseconds":0,"seconds":1577219040},
"examples":[
],
"front":"blabla"
},
{
"back":"blabla",
"delayed_till":{"nanoseconds":0,"seconds":1577092680},
"examples":[{
"answer":"blabla",
"example":"blablao"
}],
"front":"blabla"
}]
},
{
"id":"UtKzLYBPygu6iWOb1KMt",
"group_name":"nameB",
"group":[
etc.etc.etc..............
]
}
]
I would like to be able to render the number of items per group for which the date has not been passed yet.
You can use your exact same logic here, and just use a function below and pass in the group which applies a filter to the object collection and uses the delayed_till.seconds property to determine the validity check, something like this:
<div v-for="(card, groupIndex) in cards" v-bind:key="card.id">
<div v-text="groupItemsNotDelayed(cards[groupIndex].group)"> </div>
</div>
Then make your function which performs the filter:
groupItemsNotDelayed(group) {
return group.filter((item) => item.delayed_till.seconds < Date.now()).length
}
By using Date.now() we can get the current time in UTC Epoch, and compare that against our item.delayed_till.seconds to determine if the delayed period has passed (it would have to be less than the current epoch timestamp).
Then we can just call .length on the filtered items to get the count.

WebdriverIO: what is the equivalent of elementIdHtml?

How do I get an element's inner HTML from an elementId using browser object?
Is there something like elementIdHtml available in the WebdriverIO API?
The getHTML link for v4 is returning 403 Forbidden.
my goal is that i need to get all text inside all a._3cnp from an elementId
example html
<div class="container">
<a class="_3cnp">first link</a>
<a class="_3cnp">second link</a>
<a class="_3cnp">third link</a>
</div>
need to convert that to ["first link", "second link", ..]
i have the .container elementId already
this is what i did
.then(() => browser.elementIdElements(someElementId, 'a._3cnp'))
.then(buttonElem => {
console.log('->', buttonElem)
console.log('-->', buttonElem.getHTML)
buttonElem.getHTML().then(x => console.log('---->', x))
return buttonElem.value
})
result of elementIdElements is
buttonElem
{ sessionId: '2e2f144c8895a03da1b8df92f4613a33',
status: 0,
value:
[ { ELEMENT: '0.6603119466268468-24',
'element-6066-11e4-a52e-4f735466cecf': '0.6603119466268468-24' } ],
selector: 'a._3cnp' }
but buttonElem.getHTML is undefined
im using webdriverio standalone from botium-webdriverio-connector
LE:
Change your code accordingly to the following:
.then(() => browser.elementIdElements(someElementId, 'a._3cnp'))
.then(buttonElem => {
// buttonElem's 'value' will contain a list of all the matching elements
// thus, you have to call getHTML() on each item from 'value'
// the following will return the HTML of the first matching element
console.log('\nPrint element HTML: ' + buttonElem.value[0].getHTML());
return buttonElem.value[0].getHTML();
})
A better approach would be to loop between them & print the HTML:
.then(() => browser.elementIdElements(someElementId, 'a._3cnp'))
.value.forEach(buttonElem => {
console.log('\nPrint element HTML: ' + buttonElem.getHTML());
return buttonElem.getHTML();
})
The .getHTML() property is scoped to all the ELEMENT objects. For the sake of more didactical approach, I'm going to consider the task to be manipulating the HTML code found in a series of list items (<li>), from am unordered list (<ul>).
So you can do the following:
browser.getHTML('ul.ourList li.ourListItems') (this will return a list of all the <li>'s HTML code)
browser.element('ul.ourList li.ourListItems').getHTML() (this will return the first <li>'s HTML code)
$('ul.ourList li.ourListItems').getHTML() (this is the equivalent of the command above, only a relaxed version)
If you need to iterate through all the <li>s & get the HTML, do this:
let locator = 'ul.ourList li.ourListItems';
browser.elements(locator).value.forEach(elem => {
let elemHTML = elem.getHTML();
console.log( JSON.stringify(elemHTML) );
elemHTML.doSomethingWithIt();
})
where, elem will is an object with the following format:
{ ELEMENT: '0.285350058261731-1',
'element-6066-11e4-a52e-4f735466cecf': '0.285350058261731-1',
selector: 'ul li.fw-item.fz-16.lh-36.pos-r',
value: { ELEMENT: '0.285350058261731-1' },
index: 0
}