How to get form data as a object in reactjs - node.js

I'm trying to create a google form with react,
I have been creating all the questions as a components
if (props.type == "text") {
return (
<div className="box">
<h3 className="">{props.qustion}</h3>
<input className="short-text" placeholder="Your answer" id={"text"+props.id} name={"q"+props.id} type="text" onChange={updateField}/>
</div>
)
}
else if (props.type == "choice") {
return (
<div className="box">
<h3 className="">{props.qustion}{props.requre? <label className="requir">*</label>:""}</h3>
{props.answer.map(ans=>(
<div key={ans}>
<input className="radio" type="radio" id={ans} name={"radio"+props.id} value={ans} required={props.requre} onChange={updateField}/>
<label htmlFor={ans}>{ans}</label>
</div>
))
}
</div>
)
and I have been creating a form on the app file and put the components inside him,
return (
<div className="App">
<FormTitle/>
<form>
{
error? <h1>the sorce not found</h1>:data.map((item) =>(<Qustion qustion={item.question} type={item.type} requre={item.requre} id={item.id} answer={item.answares} key={item.id} />))
}
<div className="submit-right">
<input className="submit-button" type="submit" value="Submit" />
</div>
</form>
</div>
);
how to get all the form data as an object to create a post request ??

Try this function at start of the file where the form is
const formSubmit = (event) => {
event.preventDefault();
var data = new FormData(event.target);
let formObject = Object.fromEntries(data.entries());
console.log(formObject);
}
and in the form use this onSubmit={formSubmit}
<form onSubmit={formSubmit}>
<any element or components>
</form>

entries is not a function you can just reach it
const formSubmit = (event) => {
event.preventDefault();
var data = new FormData(event.target);
let formObject = Object.fromEntries(data.entries);
console.log(formObject);
}

Related

Node js Dropzone js - Upload file without submitting form

I am new in node js and trying to integrate single file upload using dropzone js. I want to upload image before submitting form. I have managed to call the upload action before submitting.
Here is my html code:
<form id="add_user" name="add_user" class="form-horizontal" action="/add-new-user" method="POST">
<div class="directory-bg text-center">
<div class="directory-overlay">
<span id="imageuploader">
<input name="profileimg" id="profileimg" type="hidden" value="">
<img id="ws_user_avatar" class="rounded-circle thumb-lg img-thumbnail dropzone" data-thumb="public/assets/images/users/user.png" src="public/assets/images/users/user.png" alt="Generic placeholder image">
<!--<div class="fallback">
<input name="image" id="image" type="file">
</div>-->
x
</span>
</div>
</div>
<div class="directory-content p-4">
<div class="mt-4">
<% if(success != "") {%>
<div class="alert alert-success" role="alert">
<strong>Done!</strong> <%= success %>
</div>
<% } %>
<div class="row">
<div class="col-md-12">
<div class="mb-3">
<label class="form-label" for="email">Email Address</label>
<input type="email" class="form-control" name="email" id="email" placeholder="Email Address" data-key="Email Address" autocomplete="off" autofill="false">
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label" for="fname">First Name</label>
<input type="text" class="form-control" name="fname" id="fname" placeholder="First Name" data-key="First Name" autocomplete="off" autofill="false">
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label" for="lname">Last Name</label>
<input type="text" class="form-control" id="lname" name="lname" placeholder="Last Name" data-key="Last Name" autocomplete="off" autofill="false">
</div>
</div>
</div>
</div>
</div>
</form>
Here is the js code to handle dropzone event
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone(".dropzone", {
url: '/upload-image',
autoProcessQueue: false,
uploadMultiple: false,
maxFiles:2,
maxFilesize: 2,
createImageThumbnails:false,
hiddenInputContainer: "img.rounded-circle",
init: function(file) {
var prevFile = null;
this.on("addedfile", function(file) {
var $this = this;
setTimeout(function () {
if(file.status == "error"){
alert(file.previewTemplate.innerText);
} else {
if(prevFile){
$this.removeFile($this.files[0])
}
prevFile = file;
$("#user_avatar").attr('data-imgname', file.name);
previewImage($this);
}
}, 10);
});
}
});
function previewImage(input){
let fileReference = input.files && input.files[0];
if(fileReference){
var reader = new FileReader();
reader.onload = (event) => {
document.getElementById('user_avatar').src = event.target.result;
}
reader.readAsDataURL(fileReference);
}
}
$(document).on('click','#btn_submit', function(e){
e.preventDefault();
if(myDropzone.getQueuedFiles().length > 0){
myDropzone.processQueue();
} else {
$("#add_user").submit();
}
});
Here is the post handler code in router.js file:
const express = require('express');
const router = express.Router();
router.post('/upload-image', function(req, res){
console.log('requested inage',req.files.file.path);
// fs.readFile(request.files.file.path, function(err, data) {
// var newPath = __dirname + "/public/img/xspectra/customlogo.png";
// fs.writeFile(newPath, data, function (err) {
// console.log("Finished writing file..." + err);
// response.redirect("back");
// });
// });
});
When the dropzone myDropzone.processQueue() function called, I get an error message in the post handler function TypeError: Cannot read property 'file' of undefined.
Can anyone suggest me where I am doing wrong?
Many Thanks!
That means that the file uploaded didn't properly make it to your web server. Are you using express-fileupload on the nodejs side to handle the uploads?
If so, I recommend checking out this link on a really great tutorial

Cannot read property 'heading' of null

My problem is I got an unexpected error at the browser end that says Cannot read property 'heading' of null
also marks this error at the client page file like about.ejs and showing; in the snap attached
I have provided all the required codes related to this. I reviewed multiple times to find for what or to where the actual errror originated but did not able to fix it.
codes of about.ejs
<%-include('./partials/header')%>
<div class="container-fluid">
<h1>About Section</h1>
<div class="card shadow mb-4">
<div class="card-header">
<form action="/admin/portfolio/create" method="post">
<button type="submit" class="btn btn-success">Edit About Page</button>
</form>
</div>
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">About Area</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<form action="/admin/about" method="post" >
<div class="form-group">
<label for="exampleFormControlInput1">Headings:</label>
<input class="form-control" type="text" name="heading" id="exampleFormControlInput1" value="<%=about.heading%>" >
</div>
<div class="form-group">
<label for="exampleFormControlInput2">Sub-Headings:</label>
<input class="form-control" type="text" name="subheading" id="exampleFormControlInput2" value="<%=about.subheading%>" >
</div>
<div class="form-group">
<textarea id="editor1" name="content" rows="10" cols="80"><%=about.content%></textarea>
</div>
<button type="submit" class="btn btn-primary">Save & Update</button>
</form>
</div>
</div>
</div>
<%-include('./partials/footer')%>
here is my router.js file
router.get('/admin/about',serverController.isAuthenticated,serverController.about)
router.post('/admin/about',serverController.isAuthenticated,serverController.about_post)
This is also my controller file
exports.about = async function(req,res){
res.render('server/about', {
about : await aboutCollection.findOne()
})
}
exports.about_post = function(req,res){
let about = new About(req.body)
about.create().then(async()=>{
res.redirect('/admin/about')
}).catch(()=>{
res.send('404')
})
}
and finally this all about my model of about page
const aboutCollection = require('../db').db().collection('about')
const objectId = require('mongodb').ObjectID
const About = function(about){
this.about = about
}
About.prototype.create = function(){
return new Promise(async(resolve,reject)=>{
await aboutCollection.updateOne({}, {$set :
{
heading : this.about.heading,
subheading : this.about.subheading,
content : this.about.content
}
})
resolve()
})
}
module.exports = About
it's because about sent value of none at the ejs tag i mean
<%= about.heading%>
Do,
exports.about = async function(req,res){
res.render('server/about', {
about : await aboutCollection.find().toArray()
})
}
Instead of,
exports.about = async function(req,res){
res.render('server/about', {
about : await aboutCollection.findOne()
})
}
In my case, I did this; after trying then see error has gone.

Trying to display IMG with src set to Binary/Buffer image data from Mongoose

Trying to display IMGs with React/JSX with Buffered/Binary data saved to my MongoDB/Mongoose database.
i iterate over the data array with the IMG element looking like this:
<img src={`data:${item.img.contentType};base64,${item.img.data.data.toString("base64")}`} alt="" />
import React, { useState, useEffect } from "react";
import axios from "axios";
const FilesUpload = () => {
const [allPics, setAllPics] = useState([]);
useEffect(() => {
const getPics = async () => {
let res = await axios.get("http://localhost:8080/");
setAllPics(res.data);
};
// query the server for all of the picture objects
getPics();
}, []);
const [state, setState] = useState({});
const handleChange = (e) => {
e.preventDefault();
setState(e.target.value);
console.log(state);
};
return (
<>
<h1>upload an image</h1>
<hr />
<div>
<form
action="http://localhost:8080/"
method="POST"
encType="multipart/form-data"
>
<div>
<label>Image Title</label>
<input type="text" id="name" placeholder="Name" name="name" onChange={handleChange} value={state.name}/>
</div>
<div>
<label htmlFor="desc">Image Description</label>
<textarea id="desc" name="desc" rows="2" placeholder="Description"
onChange={handleChange} value={state.desc}/>
</div>
<div>
<label htmlFor="image">Upload Image</label>
<input type="file" id="image" name="image" required />
</div>
<div>
<button type="submit">Submit</button>
</div>
</form>
</div>
{allPics.length > 0 ? (
<div>
{allPics.map((item, index) => (
<div key={index}>
<div>
<img src={`data:${item.img.contentType};base64,${item.img.data.data.toString("base64")}`} alt="" />
</div>
</div>
))}
</div>
) : (
<>
<hr />
<br />
<h1>uploaded files</h1>
<h5>Loading..</h5>
</>
)}
</>
);
};
export default FilesUpload;
but I always get ERR_INVALID_URL:
from similar threads on the net I've read that I need to take those comma-delimitated values and remove the comma which will give me the proper data. having a hard time figuring that out. any help would be great. thanks
I was facing the same problem after saving image like this in my mongoose model and after many research I resolved this, hope this works for you also
const base64String = btoa(String.fromCharCode(...new Uint8Array(item.img.data.data)));
and in img tag put this -:
src={`data:image/${item?.img?.contentType};base64,${base64String}`}

Image upload in a form

I have an angular form with text fields and want to add am option for uploading image in the same form. I'm stuck with the latter.
The angular form contains html tag to upload the file. Once the file is uploaded the uploaded file's name is displayed in the input field.
<!--blog.html-->
<!--form to create new blog-->
<form #blogForm="ngForm" (ngSubmit)="Save(blogForm);">
<div class="form-group">
<label>Blog Title</label>
<input type="text" class="form-control input-text" maxlength="45" name="title" ngModel #blogtitle="ngModel" required placeholder="Blog Title">
<span class="required" *ngIf="blogtitle.errors?.required && (blogtitle.dirty||blogtitle.touched||blogtitle.untouched)">*required</span>
</div>
<div class="form-group">
<label>Blog </label>
<textarea class="textarea form-control" maxlength="150" name="summary" [(ngModel)]="summary">
Blog</textarea>
</div>
<div class="form-group">
<label>Blog Desc</label>
<textarea class="textarea form-control" name="description" ngModel #blogdescription="ngModel" required>Blog Description</textarea>
<span class="required" *ngIf="blogdescription.errors?.required && (blogdescription.dirty||blogdescription.touched||blogdescription.untouched)">*required</span>
</div>
<div class="form-group">
<label>HashTags</label>
<input type="text" class="form-control input-text" name="hashtag" [(ngModel)]="hashtag" placeholder="hashtags">
</div>
<div class="form-group">
<div class="custom-file">
<!--file upload -->
<input type="file" class="custom-file-input form-control-lg" name="file" id="customFile"
value="imageFile.name" (change)="handleImageFileInput($event)">
<input type="text" readonly="true" [value]="imageFile" class="custom-file-label" >
<button type="button" (click)="upload()">Upload</button>
</div>
</div>
<input type="button" class="btn-default" (click)="Save(blogForm)" value="Create">
</form>
//blog.ts
//function to create new blog
Save(blogForm: any) {
if (blogForm.valid === true) {
blogForm = blogForm.value;
blogForm.userId = this.user_id;
blogForm.author = this.display_name;
window.confirm('Want to Publish?');
this.blogservice.Save(blogForm).subscribe(response => {
window.alert('Blog published successfully');
this.router.navigate(['/dashboard']);
});
}
}
//function to display selected image in the input field
handleImageFileInput(event) {
const img1 =event.target.files[0];
const img =event.target.files[0].name;
const fileList: FileList = event.target.files;
const fileCount = fileList.length;
if (fileCount > 0) {
const file = fileList.item(0);
console.log(` image file: ${file.name}`);
console.log(img1);
if(img == undefined) {
this.imageFile = 'Upload an image';
} else {
this.imageFile = img;
}
}
}
Need to save file along with form submission
Here's a JavaScript script which will read your data from input and display it :
<input type='file' accept='image/*' onchange='openFile(event)'><br>
<img id='output'>
<script>
var openFile = function(event) {
var input = event.target;
var reader = new FileReader();
reader.onload = function(){
var dataURL = reader.result;
var output = document.getElementById('output');
output.src = dataURL;
};
reader.readAsDataURL(input.files[0]);
};
</script>
It come from the documentation of FileReader.
With that you should be able to store the input wherever you want and store the path inside of your MongoDB collection.
Else if you want to use Angular plugins, here's one that could be useful for you :
angular-file-upload

Handling uploads multiple images from react js

Good Morning, i got a problem about some codes, fyi im still new to react js, i try to uploads multiple images from react to express and save it to mongoDB
, i already re-search that i need to use multer in my node js, but i dont know the argument need to pass because in react i have 1 name of field of files to upload, but on my submit data has 2 data to send.
handleSubmit(e){
e.preventDefault();
// var formData = new FormData();
// formData.append('file', e.target.value)
// formData.append('file2', e.target.value)
let {imagePreviewUrl} = this.state;
const dataCategory = this.state.dataCategory;
let categoryName = this.refs.categoryName.value;
let categoryImage = this.refs.categoryImage.value;
let categoryDesc = this.refs.categoryDesc.value,
categoryImageCabor = (<img alt="www.google.com" height="100px" src={imagePreviewUrl} />),
namaCabor = this.refs.namaCabor.value,
descCabor = this.refs.descCabor.value,
imageCabor = (<img height="100px" src={this.state.imageCabor.props.src} />)
fetch('http://localhost:4000/add', {
mode:'cors',
method:'post',
headers:{
'Content-Type' : 'application/json',
// "Accept" : "application/json",
// "type" : "formData"
},
body:JSON.stringify({
categoryName : categoryName,
categoryDesc : categoryDesc,
categoryImage: categoryImage,
categoryImageCabor : categoryImageCabor,
namaCabor : namaCabor,
descCabor : descCabor,
imageCabor : imageCabor,
status : true
}),
}).then(res=>{
return res.json();
}).catch(function(err){
if(err){
console.log(err);
}
})
this.setState({
dataCategory : dataCategory,
imagePreviewUrl : false,
});
this.refs.myForm.reset();
this.refs.myForm.focus();
}
handleChange(e){
this.setState({
[e.target.categoryName] : e.target.value,
[e.target.categoryImage] : e.target.value,
[e.target.categoryDesc] : e.target.value
})
}
render(){
let {imagePreviewUrl} = this.state;
let $imagePreview = null;
if(imagePreviewUrl){
$imagePreview = (<img alt ="www.google.com" height="100px" src={imagePreviewUrl} />)
}
return this.state.imageCabor === "" ? <div></div> : (
<div>
<h3>Insert Category Cabang Olahraga </h3>
<form style={{marginTop: 10}} ref="myForm" onSubmit={this.handleSubmit} >
<div className="form-group">
<label>Nama Category</label>
<input
name="categoryName"
type="text"
className="form-control"
ref="categoryName"
onChange={this.handleChange}
/>
</div>
<div className="form-group">
<label>Deskripsi Category </label>
<textarea
name="categoryDesc"
type="text"
className="form-control"
ref="categoryDesc"
rows="5"
onChange={this.handleChange}
/>
</div>
<div className="form-group">
<label>Upload Icon Image</label> <br />
<div>{$imagePreview}</div>
<input
name="categoryImage"
type="file"
ref="categoryImage"
className="image-control"
onChange={this.imageHandleChange}
/>
</div>
<h1>Cabang Olahraga</h1>
<div className ="form-group">
<label>Nama Cabang Olahraga</label>
<input
name="namaCabor"
type="text"
className="form-control"
ref="namaCabor"
value={this.state.namaCabor}
/>
</div>
<div className ="form-group">
<label>Deskripsi Cabang Olahraga</label>
<textarea
name="descCabor"
type="text"
className="form-control"
ref="descCabor"
rows="5"
value={this.state.descCabor}
/>
</div>
<div className="form-group">
<label>Icon Cabang Olahraga</label> <br />
<div><img height="100px" src={this.state.imageCabor.props.src} /></div>
</div>
<div className="form-group">
<input type="submit" value="Apply" className ="btn btn-primary" />
</div>
</form>
</div>
);
}
//node js code
//i dont know the argument need to pass in here
app.post('/', upload.array('catagoryImage', 12), (req, res, next) =>{
const files = req.files;
if(!files){
const error = new Error('Please choose files')
error.httpStatusCode = 400
return next(err)
}
res.send(files);
}}
To send images along with data from frontend to backend, you need to wrap it inside FormData object like this:
let formData = new FormData();
formdata.append('keyName','value') //replace keyName with your key and value with its value.
And do not set any headers in your fetch request. This should do. Try it and let me know.
Hope it helps!!

Resources