Is it possible to efficiently iterate through map keys in axios using Vue.js?

Currently, I am working on Vue.js exercises that I have created. I am successfully populating a table with data from a JSON API, but I have encountered a challenge. The API contains multiple keys with similar names (strIngredient1, strIngredient2, strIngredient3, etc.), and some of these keys have null values. I am looking for a way to use regex during the mapping process to search for substrings like 'strIngredientx' where x is a number, and to exclude the null values. Below is the code I have been working on:

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>

Answer №1

Is this considered sufficiently clean?

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'
  ]
}

Answer №2

After receiving the request, when you transform this.allCoktails, you can create an array for the Ingredients property that includes only non-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,
}

// accessing the keys
const keys = Object.keys(d)

// filtering the keys to keep non-null and ingredient-related keys
const nonNullIngredientsRelatedKeys = keys.filter(key => key.includes('strIngredient') && d[key] !== null)

// mapping keys and values
const ingredients = nonNullIngredientsRelatedKeys.map(key => d[key])

console.log(ingredients)

Alternatively, here is a one-liner version :

Object.keys(d).filter(key => key.includes('strIngredient') && d[key] !== null).map(key => d[key])

Answer №3

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]}), {}))

)

When implementing your code, it will be structured as follows:

(this.all_cocktails = this.all_cocktails.map((d) => ({ //using map to select specific keys.
  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]
    }), {}),
})))

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Problem arising from animation not commencing at expected starting point

Creating a feature on an app that involves breathing exercises using CSS animations. The challenge I'm facing is ensuring the words "exhale" and "inhale" appear synchronously with the animation of a circle shrinking and enlarging. However, the animati ...

Binding arguments to child functions within Vue components

When working with React, it's a common practice to bind parameters for child components in the following manner: <Child onChange={e => doThing(complex.variable.inParentScope[3], e.target.value)} foo="bar" /> In Vue, I want to ach ...

npm ERR! Your operating system has denied the operation

When attempting to install create-react-app globally using 'npm install -g create-react-app', an error occurred due to insufficient write access to the /usr/local/lib/node_modules directory. The error message displayed was as follows ...

Guide to organizing the legend section into two columns within Apache Echarts

I'm looking to customize the legend area layout in Apache Echarts for a two-column display. Can anyone provide guidance on achieving this using legend options? I have been unable to locate any examples demonstrating this particular layout. For refere ...

Guide to smoothly transition the highlighted <tr> element to the top of the scroll bar

Is there a way to utilize jQuery for animating a selected row to the top of a div with a specific scrollbar style? #sc { border:1px solid black; width:450px; height:80px; overflow:scroll; } <div id="sc"> <table id=&quo ...

Master the art of utilizing a single array in Vue 3's composition API

Hi everyone, I'm currently learning Vue 3 and could use some assistance. I've developed a Vue application that utilizes a REST API to retrieve data. Additionally, I have implemented filtering and search features in my app. However, whenever I app ...

"Utilizing Vue.js to dynamically fill input fields based on the selection of an element

As I am still new to learning Vue.js, I may not be using the correct terminology here. My current project involves a basic Vue application where I have implemented a simple search box functionality. The search box triggers an event (v-on:blur) when text i ...

Vue.js - I am looking to create dynamic buttons that change color when clicked

I have dynamically created buttons using v-for and now I want the clicked button to change color while the others remain the same. <template> <div id="exam-screen" class="exam jumbotron"> <h1>{{ title }}</h1> <div cl ...

vuex issue - do not modify the state of vuex store directly outside of mutation handlers

Can someone assist me with this issue? I am currently working with Quasar 2 (using the Vue 3 framework). When I try to execute state.authorization = data.data.data.authorization; in a mutation, why do I receive the error message "[vuex] do not mutate vue ...

"Effortlessly Arrange Multiple Gridview Rows Using Checkbox Selection in jQuery Drag and Drop

Struggling with getting checkboxes clicked when a GridViewRow becomes selected. Utilizing jQuery Methods like .sortable and .selectable. Worked as intended but looking to have a checkmark placed on the checkbox cbBulkSort within the GridView's first c ...

The attempt to access 'reading params' is resulting in an error due to undefined properties

Looking for some assistance in resolving an error I'm encountering. Below is a snippet of my code: const ProductScreen = ({match, history}) => { const [qty, setQty] = useState(1); const dispatch = useDispatch(); const productDetail ...

Creating a clickable table row in bootstrap with optimal effectiveness

Is it better to implement a clickable row using jquery or pure JS? Consider server and client efficiency Ensure compatibility with various browsers The jquery option: // my tr (row) class <tr class='clickable-row' data-href='url:www.g ...

Employing a pair of interdependent v-select components to prevent any duplicate entries

I am currently working with two v-select boxes that share similar data. In my scenario, I extract attachments from an email and load them into an array. The issue I encountered is that the first select box should only allow the selection of one document, w ...

Using the onclick event with an image created through PHP code

I am currently in the process of developing a dynamic image represented as a graph displaying the number of documents generated each day. This interactive image is being created using PHP, and I aim to improve user engagement by enabling them to click on t ...

Formatting Numbers in HighCharts Shared Tooltip

My first experience with HighCharts JS has been quite positive. I am currently creating multiple series and using a shared tooltip feature. The numbers displayed in the shared tooltip are accurate, but the formatting is not to my liking. For instance, it s ...

Struggling to capture an error generated by Sequelize within a universal Middleware block

In a test project, I have successfully implemented CLS transaction control in Sequelize using 'cls-hooked'. The transactions work seamlessly both in the command line and with Express. They are injected and managed automatically, rolling back on a ...

Switch the image source when hovering over a text menu

Currently, I have been using the following code to switch between images. However, what I actually want to do is change the image when hovering over the title link of the image. onmouseover="this.src='Images/img.png'" onmouseout="this.src=' ...

Tabulating with jQuery Arrays

I am facing an issue when trying to perform calculations with certain numbers. Here is the specific code snippet causing trouble: for (var key in week_total) { $("." + key).html(week_total[key]); } After running this code, I keep getting a value of N ...

Is it possible to have the ShowHide plugin fade in instead of toggling?

I'm currently utilizing the ShowHide Plugin and attempting to make it fade in instead of toggle/slide into view. Here's my code snippet: showHide.js (function ($) { $.fn.showHide = function (options) { //default variables for the p ...

Encountering a sudden problem while running gulp build due to a node_module - Surprising occurrence of Unexpected

Encountering an unexpected issue while running a gulp build process for a web app that I am struggling to resolve. The problem did not exist on the evening of 25/01/2019, but when attempting to execute the gulp build process this morning (30/01/2019), an ...