'How to implement edit form with file upload
Trying to update a form without uploading a new image. I'm using multer for the image upload. it works very well when i create a form.
I'm using reactJs for frontend and node for the server side.
This is the front end code with react
import React, { useState, useEffect } from 'react';
import { useParams } from "react-router-dom";
import useFetch from "./fetch";
function EditForm() {
const { id } = useParams();
const { contestant: form, error, isPending } =
useFetch("http://localhost:5000/dashboard/form_single/" +
id);
const [name, setName] = useState('');
const [address, setAddress] = useState('');
const [fileName, setFileName] = useState('');
useEffect(() => {
setName(form.full_name);
setAddress(form.home_address);
}, [form])
const editForm = async (id) => {
try {
const formData = new FormData();
formData.append("name", name);
formData.append( "home_address", address);
formData.append("image", fileName);
const myHeaders = new Headers();
myHeaders.append("jwtToken", localStorage.jwtToken);
await
fetch(`http://localhost:5000/dashboard/form_update/${id}`, {
method: "PUT",
headers: myHeaders,
body: formData,
});
} catch (err) {
console.error(err.message);
}
};
const onChangeFile = e => {
setFileName(e.target.files[0]);
}
return (
<div>
{ isPending && <div>Loading...</div> }
{ error && <div>{ error }</div> }
<form encType="multipart/form-data"
onSubmit={() => editForm(form.form_id)}>
<input
type="text"
className="form-control"
value={name || ''}
onChange={e => setName(e.target.value)}
/>
<input
type="text"
className="form-control"
value={address || ''}
onChange={e => setAddress(e.target.value)}
/>
<input
type="file"
id="update"
name="image"
onChange={onChangeFile}
/>
<button type ="submit" >Save</button>
</form>
<div>
<img
alt="contestant"
src= {`http://localhost:5000/upload/${form.passport}`}
className="rounded-circle" style={{width: "100px",
height: "100px"}}/>
</div>
</div>
);
}
export default EditForm;
UNFORTUNATELY I GET Cannot read properties of undefined (reading 'filename')
. I've tried to make multer image upload optional but it did'nt work. The code bellow is the api.
This is the server side code. Nodejs
router.put("/form_update/:id", upload.single('image'), async(req,
res) => {
try {
const { id } = req.params;
const image = req.file.filename;
const { name, home_address } = req.body;
const updateForm = await pool.query("UPDATE form SET
full_name = $1, home_address = $2, passport = $3 WHERE
form_id = $4
RETURNING *", [name, home_address, image, id]);
res.json("Form was updated");
} catch (err) {
console.error(err.message);
}
});
how do i not always have to change image everytime i need to edit a form.
Solution 1:[1]
on the server, check if fields are provided, and then store values for each, and construct query dynamically, and when done checking, execute query
you could list fields in an array and then iterate them and construct query and values against req.body
you could also add some validation (check if there is id etc., you could add that on the front-end as well)
try this:
router.put("/form_update/:id", upload.single('image'), async(req, res) => {
try {
// fields. same as in req.body
const fields = ['full_name', 'home_address', 'something', 'else'];
// store values
const values = [];
// dynamic query string
let stmt = [];
const {id } = req.params;
// add some validation
if(!id) {
console.error('no id..');
return res.json({msg:"err: no id"});
}
const image = req.file ? req.file.filename : '';
// build query
fields.map((field)=>{
if(req.body[field]) {
values.push(req.body[field]);
stmt.push(`${field} = $${values.length}`);
}
});
// check image, as it's not in req.body
if(image) {
values.push(image);
stmt.push(`passport = $${values.length}`);
}
// no data..end
if(!values.length) {
console.log('no data..');
return res.json({msg:'no data..'});
}
// finish
stmt = "UPDATE form SET " + stmt.join(', ');
values.push(id);
stmt += ` WHERE form_id = $${values.length}`;
stmt += ' RETURNING *';
const updateForm = await pool.query(stmt, values);
res.json({msg:"Form was updated"});
} catch (err) {
console.error(err.message);
}
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |