skip to Main Content

I am currently working on a javascript project with HTMl, CSS and Vue. The Project is to make a cookbook online that you can add your own recipes, and also delete recipes from. The issue that I have is that when I try to implement a delete button for the added recipes, it breaks the website so that it doesn’t show the given recipes anymore and I cant add any more new recipes either. I am using this as a baseline for the delete code:

which makes the button work but it does not delete anything

I have tried changed the base recipe to a ref and the function to add a new recipe to a ref as well but then I have the issue of the base recipe not showing up anymore and the button for adding a new recipe either. So now I do not know how to change my code for both the add recipe button and the delete button to work.

Below is my code and I have changed it back to before the ref changes so that at least the add recipe button works:

import {loadThings} from "@/components/script.js";
import { ref } from 'vue';
let showRecipeName = true;
let showForm = ref(false);
let recipes =  [
  {
    name: "Spaghetti Carbonara",
    picture: 
    preparationTime: "20 Minuten",
    cookingTime: "15 Minuten",
    description: "Spaghetti Carbonara ist ein klassisches italienisches Nudelgericht, das in der Regel aus Spaghetti, Guanciale, Ei, Pecorino Romano und Pfeffer zubereitet wird. Die Zutaten werden in einer Pfanne gemischt, bis sie eine cremige Konsistenz haben. Das Gericht wird oft mit zusätzlichem Pecorino Romano und Pfeffer garniert.",
    ingredients: [
      "400g Spaghetti",
      "200g Guanciale",
      "4 Eier",
      "100g Pecorino Romano",
      "Pfeffer"
    ],
    instructions: [
      "Die Spaghetti in einem großen Topf mit kochendem Salzwasser al dente kochen.",
      "In der Zwischenzeit das Guanciale in einer Pfanne bei mittlerer Hitze knusprig braten.",
      "Die Eier in einer Schüssel verquirlen und den geriebenen Pecorino Romano hinzufügen.",
      "Die gekochten Spaghetti abgießen und in die Pfanne mit dem Guanciale geben. Die Ei-Käse-Mischung darüber gießen und gut vermengen.",
      "Mit Pfeffer würzen und sofort servieren."
    ]
  }
];
let newRecipe ={
  name: "",
  picture: "",
  preparationTime: "",
  cookingTime: "",
  description: "",
  ingredients: [""],
  instructions: [""]
};

function addRecipe() {
  newRecipe.ingredients = newRecipe.ingredients.split('n');
  newRecipe.instructions = newRecipe.instructions.split('n');
  recipes.push({...newRecipe});
  newRecipe = {
    name: "",
    preparationTime: "",
    cookingTime: "",
    description: "",
    ingredients: [""],
    instructions: [""]
  };
  showForm.value = false;
}
function showAddRecipeForm() {
  showForm.value = true;
}
function deleteRecipe(index) {
  console.log("deleteRecipe function called with index: ", index);
  recipes.splice(index, 1);
}



</script>

<template>
  <div class="recipeheader">
    <h1>Rezepte</h1>
    <button @click="loadThings">Load recipes</button>
    <button @click="showAddRecipeForm">Add Recipe</button>
    <div class="addrecipe">
      <form @submit.prevent="addRecipe" v-if="showForm">
        <label>Name: <input v-model="newRecipe.name" required /></label>
        <label>Preparation Time: <input v-model="newRecipe.preparationTime" required /></label>
        <label>Cooking Time: <input v-model="newRecipe.cookingTime" required /></label>
        <label>Description: <input v-model="newRecipe.description" required /></label>
        <label>Ingredients: <textarea v-model="newRecipe.ingredients" required></textarea></label>
        <label>Instructions: <textarea v-model="newRecipe.instructions" required></textarea></label>
        <label>Picture: <input v-model="newRecipe.picture"  /></label>
        <button type="submit">Add Recipe</button>
      </form>
    </div>
  </div>
  <div class="newRecipe" v-for="(recipe, index) in recipes" :key="index">
    <h2>{{ recipe.name }}</h2>
    <button @click="deleteRecipe(index)">Delete Recipe</button>
    <img :src="recipe.picture" alt="Picture of the recipe" />
    <h3>Description</h3>
    <p>{{ recipe.description }}</p>
    <h3>Preparation Time</h3>
    <p>{{ recipe.preparationTime }}</p>
    <h3>Cooking Time</h3>
    <p>{{ recipe.cookingTime }}</p>
    <h3>Ingredients</h3>
    <ul>
      <li v-for="(ingredient, index) in recipe.ingredients" :key="index">{{ ingredient }}</li>
    </ul>
    <h3>Instructions</h3>
    <ul>
      <li v-for="(instruction, index) in recipe.instructions" :key="index">{{ instruction }}</li>
    </ul>
  </div>




</template>

<style>
.addrecipe
{
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1rem;
  margin-top: 3rem;
  padding: 50px;
}
.addrecipe button[type="submit"] {
  margin-top: 20px;
  align-items: flex-start;
}
.body {
  margin-top: 0rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start; /* Adjust this line */
  gap: 2px; /* Adjust as needed */
  background-color: whitesmoke;

}
.newRecipe{
  margin-top: 0rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start; /* Adjust this line */
  gap: 20px; /* Adjust as needed */
  background-color: whitesmoke;
  padding: 10px;
}
.recipeheader {
    min-height: 30vh;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    background-color: white;
}
@media (min-width: 1024px) {
    .recipeheader {
        height: 100vh;
      justify-content: center;
        display: flex;
        align-items: center;
    }
}
</style>

2

Answers


  1. I think the problem is that your recipes array is not reactive. You would need to define it as let recipes = ref([ { ... } ]).
    And whenever you make changes to the array, don’t forget to use recipes.value then.

    Login or Signup to reply.
  2. You don’t really use VueJS here but regular Javascript regarding the script part. As told by Lukas, feel free to use ref for the object too.

    Also "breaks the website" is a bit vague, please check your browser console and share any errors or VueJS state thanks to the Vue devtools.

    Overall, I recommend giving a try to the VueJS docs before going further.
    There are plenty of examples for all use cases.

    There is also the examples page.


    Few recommendations:

    • consider using style scoped to preserve the whole style to one component
    • consider using more flexible variables rather than px and vh for responsive purposes
    • consider NOT using the index of your v-for as a :key, it’s a bad practice and counters the whole purpose of having a :key to begin with (could be used this way if just an array of strings as in your example but I am saying this in general)
    • you don’t need to wrap an input in a label, you can put them alongside
    • loadThings could probably be used with some lifecycles like onMounted, give it a try it’s quite powerful!
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search