I have just started learning mern and i making a simple app where i have to add items into a menu , update and delete them. for updating i want to pre populate the input field with the item data.
I have been sitting on this issue for a lot of time but i am not able to find a solution. I have set the value attribute of for each input but still i dont see any info in the input field.
React code
menuItems.jsx
import React, { useEffect, useState } from "react";
import edit from "/edit.png";
import rupee from "../utils/currencyFormatter.jsx";
import api from "../api/api.jsx";
import { capitalize } from "../utils/capitalize.jsx";
import available from "/available.png";
import notavailable from "/notavailable.png";
import deleteImg from "/delete.png";
import EditItem from "./editItem.jsx";
const menuItems = ({ category }) => {
const [editForm, setEditForm] = useState(false);
const [items, setItems] = useState([]);
useEffect(() => {
const getItems = async () => {
try {
const response = await api.get("/menu");
setItems(response.data);
} catch (error) {
console.log(error.message);
}
};
getItems();
}, []);
const [idi, setId] = useState(0);
return (
<ol>
{editForm && (
<EditItem
isVisible={editForm}
setIsVisible={setEditForm}
category={category}
id={idi}
/>
)}
{items.map((i, index) => (
<li
key={i._id}
className="grid grid-cols-6 text-[1.5vw] p-3 transition-all duration-100 hover:bg-orange-400 rounded-md"
>
{index + 1}
<p className=" flex flex-col justify-center font-semibold">
{capitalize(i.item)}
<span className="font-thin text-[1.3vw]">
{i.description}
</span>
</p>
<span>{rupee.format(i.price)}</span>
<span>
{i.availability ? (
<img
src={available}
alt="Available"
className=" h-8 w-8"
/>
) : (
<img
src={notavailable}
alt="Not Available"
className=" h-8 w-8"
/>
)}
</span>
<button
onClick={() => {
setEditForm(true);
setId(i._id);
}}
>
<img src={edit} alt="edit" className="h-10 w-10" />
</button>
<button>
<img
src={deleteImg}
alt="delete"
className=" h-10 w-10"
/>
</button>
</li>
))}
</ol>
);
};
export default menuItems;
editItem.jsx
import React, { useEffect, useRef, useState } from "react";
import axios from "../api/api.jsx";
const editItem = ({ isVisible, setIsVisible, category, id }) => {
const [formData, setFormData] = useState({});
useEffect(() => {
const getItems = async () => {
try {
const response = await axios.get(`/menu/${id}`);
setFormData(response.data);
console.log("updated formData:", formData);
} catch (error) {
console.log(error.message);
setFormData({});
}
};
getItems();
}, [id]);
const handleSubmit = async (event) => {
event.preventDefault();
try {
console.log(formData.category);
const response = await axios.put(`/menu/${id}`, formData);
console.log(response.data);
} catch (error) {
console.error(error.message);
}
setIsVisible(!isVisible);
};
if (!isVisible) return null;
return (
<div className="fixed inset-0 bg-black bg-opacity-25 backdrop-blur-sm flex justify-center items-center">
<div className="w-[50%] flex flex-col">
<div className="bg-white p-2 rounded">
<h2 className="mb-4 text-2xl text-center font-bold text-gray-900">
Add a new product
</h2>
<form
action="post"
className=" p-4"
onSubmit={handleSubmit}
>
<div className="grid gap-4 sm:grid-cols-2 sm:gap-6">
<div className="sm:col-span-2">
<label
htmlFor="item"
className="block mb-2 text-sm font-medium text-gray-90"
>
Item Name
</label>
<input
type="text"
name="item"
id="item"
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 "
placeholder="Type Item name"
required
value={formData.item}
onChange={(event) => {
setFormData({
...formData,
item: event.target.value,
});
console.log(
"Item input value:",
event.target.value
);
}}
/>
</div>
<div className="w-full">
<label
htmlFor="price"
className="block mb-2 text-sm font-medium text-gray-90"
>
Price
</label>
<input
type="number"
name="price"
id="price"
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 "
required
placeholder="Add the price"
value={formData.price}
onChange={(event) =>
setFormData({
...formData,
price: event.target.value,
})
}
/>
</div>
<div>
<label
htmlFor="category"
className="block mb-2 text-sm font-medium text-gray-90"
>
Category
</label>
<select
id="category"
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 "
value={formData.category}
onChange={(event) => {
setFormData({
...formData,
category: event.target.value,
});
}}
>
<option>Select category</option>
{category.map((c) => (
<option key={c._id} value={c._id}>
{c.name}
</option>
))}
</select>
</div>
<div className="flex items-center">
<label
htmlFor="availability"
className="block mb-2 text-sm font-medium text-gray-90 mr-5"
>
Availability
</label>
<input
type="checkbox"
name="avaialability"
id="availability"
value={formData.availability}
onChange={(event) => {
if (event.target.checked) {
setFormData({
...formData,
availability: true,
});
}
}}
/>
</div>
<div className="flex gap-4 items-center">
<label
htmlFor="veg"
className="block mb-2 text-sm font-medium text-gray-90"
>
Veg
</label>
<input
type="radio"
name="veg_or_nonveg"
value="veg"
id="veg"
onChange={(event) =>
setFormData({
...formData,
veg_or_nonveg: event.target.value,
})
}
/>
<label
htmlFor="nonveg"
className="block mb-2 text-sm font-medium text-gray-90"
>
Non Veg
</label>
<input
type="radio"
name="veg_or_nonveg"
value="non-veg"
id="nonveg"
onChange={(event) =>
setFormData({
...formData,
veg_or_nonveg: event.target.value,
})
}
/>
</div>
<div className="sm:col-span-2">
<label
htmlFor="description"
className="block mb-2 text-sm font-medium text-gray-90"
>
Description
</label>
<textarea
id="description"
rows="8"
className="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-primary-500 focus:border-primary-500 "
placeholder="Item Description"
value={formData.description}
onChange={(event) =>
setFormData({
...formData,
description: event.target.value,
})
}
></textarea>
</div>
</div>
<div className="flex">
<button
type="submit"
className="flex items-center px-5 py-2.5 mt-2 text-sm font-medium text-center rounded-lg focus:ring-4 focus:ring-primary-200"
>
Edit product
</button>
<button
className=" flex items-center px-5 py-2.5 mt-2 text-sm font-medium text-center rounded-lg text-red-600 focus:ring-4 focus:ring-primary-200"
onClick={() => {
setIsVisible(!isVisible);
}}
>
Cancel
</button>
</div>
</form>
</div>
</div>
</div>
);
};
export default editItem;
Express Code
controllers
import mongoose from "mongoose";
import { menuModel } from "../models/menuModel.js";
export const getMenuItems = async (req, res) => {
try {
const menuItems = await menuModel.find();
res.status(200).json(menuItems);
} catch (err) {
res.status(404).json({ message: err.message });
console.log(err);
}
};
export const getOneItem = async (req, res) => {
const id = req.params.id;
try {
const item = await menuModel.find({ _id: id });
res.status(200).json(item);
} catch (err) {
res.status(404).json({ message: err.message });
}
};
export const addMenuItems = async (req, res) => {
const item = req.body;
const newItem = new menuModel(item);
try {
await newItem.save();
res.status(201).json(newItem);
console.log(newItem);
} catch (err) {
console.log(err);
res.status(409).json({ message: err.message });
}
};
export const updateMenuItmes = async (req, res) => {
const { id: _id } = req.params;
const updatedData = req.body;
try {
if (!mongoose.Types.ObjectId.isValid(_id))
return res.status(404).send("no item with that id exists");
const updates = await menuModel.findByIdAndUpdate(_id, updatedData, {
new: true,
});
res.status(200).json(updates);
} catch (err) {
res.status(409).json({ message: err.message });
}
};
// export const deleteItems = async (req,res) =>{
// }
menuModel.jsx – contains the model of the menu
import { Decimal128 } from "mongodb";
import mongoose, { model } from "mongoose";
const { Schema } = mongoose;
const menuSchema = new Schema({
item: {
type: String,
required: true,
unique: true,
},
price: {
type: Number,
required: true,
default: 0.0,
},
availability: {
type: Boolean,
required: true,
default: true,
},
veg_or_nonveg: {
type: String,
required: true,
enum: ["Veg", "Non-Veg", "veg", "non-veg"],
},
description: {
type: String,
},
category: [
{
type: Schema.Types.ObjectId,
ref: "categoryModel",
},
],
});
export const menuModel = new model('menuModel', menuSchema);
i have added value attribute as you can see here but i find no pre populated data
Can anyone help me with the issue.
here is the github repo link:
Rakshith Raj Satrasala is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.