I am looking to showcase an image, title, and description for a specific recipe that I select.
Here is my setup using ItemSwiper (parent):
<template>
<Slide
v-for="recipe in storeRecipe.data"
:key="recipe.recipe_id">
<ItemCard :data="recipe" :pending="storeRecipe.pending" />
</Slide>
</template>
<script setup>
import { onMounted } from 'vue';
import { useStoreRecipe } from '@/store/storeRecipe';
import ItemCard from '@/component/ItemCard.vue';
// Pinia store
const storeRecipe = useStoreRecipe();
onMounted(async () => {
await storeRecipe.loadRecipes();
});
</script>
Now in the child component, ItemCard:
<template>
<div class="card">
<div class="card__item">
<img
class="card__image"
:src="getSrc('.jpg')"
:alt="data.alt"/>
<div class="card__content">
<h2 class="card__title">{{ data.title }}</h2>
<p class="card__text">{{ data.short_description }}</p>
<router-link
class="card__link"
:to="{
name: 'recipeDetail',
params: { recipe: data.slug },
}"
>View more</router-link
>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const props = defineProps(['data', 'pending']);
const isLoaded = ref(false);
const getSrc = ext => {
return new URL(
`../assets/images/content/recipe/${props.data.image}${ext}`,
import.meta.url
).href;
};
onMounted(() => {
const img = new Image(getSrc('.jpg'));
img.onload = () => {
isLoaded.value = true;
};
img.src = getSrc('.jpg');
});
</script>
When clicking on the 'View More' link, it leads to the recipe detail page (ViewRecipeDetail
):
<template>
<img
class="card__image"
:src="getSrc('.jpg')"
:alt="storeRecipe.data.alt" />
<div class="card__content">
<h2 class="card__title">
{{ storeRecipe.data.title }}
</h2>
<p class="card__text">
{{ storeRecipe.data.short_description }}
</p>
</div>
</template>
<script setup>
import { useStoreRecipe } from '@/store/storeRecipe';
const storeRecipe = useStoreRecipe();
</script>
I'm trying to figure out how to show the same content (image, title, etc.) in ViewRecipeDetail
as in ItemCard
, even though they are not directly related. Additionally, I want to access the getSrc
function in ViewRecipeDetail
without duplicating code. Implementing this using a composable has proven challenging.
UPDATE:
I have added a store action and state:
Action:
export const actions = {
async loadRecipes(keyword) {
try {
this.pending = true;
keyword ??= '';
const res = await fetch(
`/api/recipe?keyword=${encodeURIComponent(keyword)}`
);
if (res.ok) {
const data = await res.json();
this.data = data;
}
} catch (err) {
console.error('Error fetching data:', err);
this.error = 'Failed to fetch data';
} finally {
this.pending = false;
}
},
};
State:
export const state = () => {
return {
data: [],
pending: false,
};
};
Please provide a possible solution. If there's a way to utilize the store without query parameters in the router-link, that would be ideal. Thank you!