I am proceeding with Vue.js exercises that I create. I am populating a json api to a table, everything works but I am facing a limitation where there is multiple keys in api with almost same name(strIngredient1,strIngredient2,strIngredient3, ..etc) and some of these keys are null. Is there a way to include regex when doing mapping searching for the substring(strIngredientx) where x is a number ? and also to exclude the null values? I did use axios but not sure if is the prefect way, this is my code:
Ingredient.vue( parent):
<template>
<div>
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Category</th>
<th scope="col">strIBA</th>
<th scope="col">Ingredients</th>
</tr>
</thead>
<tbody>
<tr v-for="item in all_cocktails" v-bind:key="item">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.strIBA }}</td>
<td>{{ item.category }}</td>
<td><subComponent :item="item"></subComponent></td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import subComponent from "./subComponent";
import axios from "axios";
export default {
data() {
return {
loading: false,
all_cocktails: {},
};
},
components: {
subComponent,
},
async mounted() {
this.loading = true;
await this.getData();
},
computed: {},
methods: {
getData() {
axios
.get(
"https://www.thecocktaildb.com/api/json/v1/1/search.php?s=margarita"
)
.then((response) => (this.all_cocktails = response.data.drinks))
.then(
(response) =>
(this.all_cocktails = this.all_cocktails.map((d) => ({ //using map to pick the keys that I want.
id: d.idDrink,
name: d.strDrink,
category: d.strCategory,
strIBA: d.strIBA,
Ingredients: [ //here is there a way to loop for substring and not null instead of going through all of them ?
d.strIngredient1,
d.strIngredient2,
d.strIngredient3,
],
})))
)
.catch((error) => console.log(error))
.finally(() => (this.loading = false));
},
},
};
</script>
<style>
</style>
subComponent.vue (child):
<template>
<div>
<select>
<option
v-for="(item, index) in item.Ingredients"
:key="index"
v-bind:value="item"
>
{{ item }}
</option>
</select>
</div>
</template>
<script>
export default {
props: {
item: {},
},
data() {
return {};
},
};
</script>
CodePudding user response:
is this clean enough?
axios
.get("https://www.thecocktaildb.com/api/json/v1/1/search.php?s=margarita")
.then((response) => (this.all_cocktails = response.data.drinks))
.then((response) =>
(this.all_cocktails = this.all_cocktails.map((d) => {
let obj = {
id: d.idDrink,
name: d.strDrink,
category: d.strCategory,
strIBA: d.strIBA,
}
let Ingredients = []
for(let i = 0; i < Object.keys(d).length; i ) {
if(d["strIngredient" i]) Ingredients.push(d["strIngredient" i])
}
obj.Ingredients = [...new Set(Ingredients)]
return obj
})))
output:
{
id: '178332',
name: 'Smashed Watermelon Margarita',
category: 'Cocktail',
strIBA: null,
Ingredients: [
'Watermelon',
'Mint',
'Grapefruit Juice',
'Lime',
'Tequila'
]
}
CodePudding user response:
When you transform this.allCoktails
after getting the request, you may create an array for the Ingredients
property that contains not null ingredients like this :
// current element (we are inside the 'map')
const d = {
"strMeasure1": "1/2 cup",
"strIngredient1": "Watermelon",
"strIngredient2": "Mint",
"strIngredient3": null,
"strIngredient4": null,
}
// getting the keys
const keys = Object.keys(d)
// filtering the keys (keeping not null and ingredient related keys)
const nonNullIngredientsRelatedKeys = keys.filter(key => key.includes('strIngredient') && d[key] !== null)
// mapping of keys and values
const ingredients = nonNullIngredientsRelatedKeys.map(key => d[key])
console.log(ingredients)
Here is a one-liner version :
Object.keys(d).filter(key => key.includes('strIngredient') && d[key] !== null).map(key => d[key])
CodePudding user response:
let data = [ { a: 1, b: 2, strIngredient1: 3, strIngredient2: 4, strIngredient3: null }, { a: 1, b: 2, strIngredient1: 3, strIngredient2: 4, strIngredient3: null }, { a: 1, b: 2, strIngredient1: 3, strIngredient2: 4, strIngredient3: null }]
console.log(
data.map(itm => Object.entries(itm)
.filter(([key, value]) => (key.indexOf('strIngredient') !== -1 && value) || key.indexOf('strIngredient') === -1)
.reduce((obj, itm) => ({ ...obj, [itm[0]]: itm[1]}), {}))
)
For your code, it will be used like:
(this.all_cocktails = this.all_cocktails.map((d) => ({ //using map to pick the keys that I want.
id: d.idDrink,
name: d.strDrink,
category: d.strCategory,
strIBA: d.strIBA,
Ingredients: Object.entries(d)
.filter(([key, value]) => (key.indexOf('strIngredient') !== -1 && value))
.reduce((obj, itm) => ({ ...obj,
[itm[0]]: itm[1]
}), {}),
})))