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

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

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.

How to sort computed values in a v-data-table

I have a v-data-table from Vuetify in my Vue.js app.
The table has a column of computed values.
I wanna make that column sortable.
What do I have to do?
What I tried:
I was looking into the sort function of the v-data-table-header.
It offers: sort?: (a: any, b: any) => number.
However, when I define that function for my column the values in the column are still not sorted.
HTML:
<v-data-table
:headers='headers'
:items='items'
>
<template v-slot:item.complete='{ item }'>
<span v-if='!isComplete(item)' class='error--text'>not complete</span>
<span v-else>complete</span>
</template>
</v-data-table>
Script:
readonly headers: DataTableHeader[] = [
{
text: 'Completeness',
value: 'complete',
sort: (a, b) => {
console.log(a, b);
return 1;
}
},
];
items = [
{
name: "foo",
tasks: 3
},
{
name: "bar",
tasks: 42
}
]
isComplete(item: any): boolean {
return 12 <= item.tasks && item.tasks <= 50;
}
The order doesn't change when I enable sorting and the log says:
undefined undefined
undefined undefined
undefined undefined
...
What do I need to do to sort computed values?
I don't think you can sort computed data in a table unless the objects inside items array each have a field called complete with some value, because that's what the table is looking for to get the value (hence undefined).

ReferenceArrayInput usage with relationships on React Admin

I have followed the doc for the ReferenceArrayInput (https://marmelab.com/react-admin/Inputs.html#common-input-props) but it does not seem to be working with relationship fields.
For example, I have this many-to-many relation for my Users (serialized version) :
Coming from (raw response from my API):
I have setup the ReferenceArrayInput as followed :
<ReferenceArrayInput source="profiles" reference="profiles" >
<SelectArrayInput optionText="label" />
</ReferenceArrayInput>
I think it's making the appropriate calls :
But here is my result :
Any idea what I'm doing wrong ?
Thanks in advance for your help !
On docs, ReferenceArrayInput is said to expect a source prop pointing to an array os ids, array of primitive types, and not array of objects with id. Looks like you are already transforming your raw response from api, so if you could transform a bit more, mapping [{id}] to [id], it could work.
If other parts of your app expects profiles to be an array of objects, just create a new object entry like profilesIds or _profiles.
As gstvg said, ReferenceArrayInput expects an array of primitive type, not array of objects.
If your current record is like below:
{
"id": 1,
"tags": [
{ id: 'programming', name: 'Programming' },
{ id: 'lifestyle', name: 'Lifestyle' }
]
}
And you have a resource /tags, which returns all tags like:
[
{ id: 'programming', name: 'Programming' },
{ id: 'lifestyle', name: 'Lifestyle' },
{ id: 'photography', name: 'Photography' }
]
Then you can do something like this (it will select the tags of current record)
<ReferenceArrayInput
reference="tags"
source="tags"
parse={(value) => value && value.map((v) => ({ id: v }))}
format={(value) => value && value.map((v) => v.id)}
>
<AutocompleteArrayInput />
</ReferenceArrayInput>

v-modal with a multi part variable

I'm not sure if this is the correct way to ask this, but I'm having trouble setting up a v-model that has multiple parts.
v-model="formInputs.input_ + inputType.id"
That would end up being this in the data:
data(){
return {
formInputs: {
input_(its id here): ''
//example input_5
},
}
},
Is it possible to chain values inside a v-model?
You can use [] instead of . as key accessor:
v-model="formInputs['input_' + inputType.id]"