MERN, how to update multiple input field from frontend in MongoDB - mongodb

I am trying to update multiple fields and also want to keep data as it was previously which I don't want to edit.
I can update a single field but by manual typing not dynamically and also have no idea how to grab all other fields with which one I won't change.
I attached my code by which I can set only one field update,
const EventEdit = () => {
const [events, setEvents] = useState([]);
useEffect(() => {
const uri = `http://localhost:5000/eventss/${keyId}`;
fetch(uri)
.then((res) => res.json())
.then((data) => setEvents(data));
}, [user, keyId]);
return (
<form onSubmit={submitRegister} method="">
<div className="event_details">
<Form.Group className="mb-3" controlId="eventName">
<Form.Label>Event Name</Form.Label>
<Form.Control
type="text"
name="name"
placeholder=""
defaultValue={events?.name}
onChange={handleOnChange}
required
/>
</Form.Group>
<div className="event_type_check">
<label>
<input
type="checkbox"
defaultChecked={evTypeFilm}
onChange={() => setEvTypeFilm(!evTypeFilm)}
/>
Film Festival
</label>
<label>
<input
type="checkbox"
defaultChecked={evTypeScreen}
onChange={() => setEvTypeScreen(!evTypeScreen)}
/>
Screenwriting Contest
</label>
<label>
<input
type="checkbox"
defaultChecked={evTypeMusic}
onChange={() => setEvTypeMusic(!evTypeMusic)}
/>
Music Contest
</label>
<label>
<input
type="checkbox"
defaultChecked={evTypePhoto}
onChange={() => setEvTypePhoto(!evTypePhoto)}
/>
Photography Contest
</label>
<label>
<input
type="checkbox"
defaultChecked={evTypeOnline}
onChange={() => setEvTypeOnline(!evTypeOnline)}
/>
Online Festival / Awards Event
</label>
</div>
<Form.Group className="mb-3" controlId="runningYears">
<Form.Label>Running Years</Form.Label>
<Form.Control
type="text"
name="runningYears"
defaultValue={events?.runningYears}
placeholder=""
onChange={handleOnChange}
required
/>
</Form.Group>
<Form.Group className="mb-3" controlId="eventDescription">
<Form.Label>Event Description</Form.Label>
<textarea
type="text"
name="eventDescription"
placeholder=""
onChange={handleOnChange}
defaultValue={events?.eventDescription}
required
rows="3"
cols="88"
></textarea>
</Form.Group>
<Button type="submit">Submit</Button>
</form>
);
export default EventEdit;
backend, manual value update code.
app.put('/events/:id', async(req, res) => {
const id = req.params.id;
const query = {keyId:id}
const options = {upsert: true};
const updateDoc = { $set: { name: "Titas"} };
const result = await eventsCollection.updateOne(query, updateDoc, options);
res.json(result);
})

Related

Why am I getting "500 (Internal Server Error)" and "Uncaught (in promise) SyntaxError: Unexpected token < "?

I am trying to insert some data into the database through a fetch API POST request to a Next.js API route but I am getting the following two error messages in the browser's console:
api/addCompany/addCompany:1 Failed to load resource: the server responded with a status of 500 (Internal Server Error) register:1
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
These are my project's folders (it's relevant because of Next.js's routing system)
This is the component where I am doing the fetch API request (please don't judge my poor Typescript skills, I am new to it, still not finding the propper event type):
import styles from '../styles/Register.module.css'
import { NextPage } from "next"
import { prisma } from '../prisma/prisma_client';
import { Prisma } from '#prisma/client';
import { useSession } from "next-auth/react"
const Register: NextPage = () => {
const createCompany: any = async (event: any) => {
event.preventDefault()
const company: Prisma.CompanyCreateInput = {
companyName: event.target.companyName.value,
gender: event.target.gender.value,
firstName: event.target.firstName.value,
lastName: event.target.lastName.value,
street: event.target.street.value,
houseNumber: parseInt(event.target.houseNumber.value),
postcode: parseInt(event.target.postcode.value),
city: event.target.city.value,
country: event.target.country.value,
countryCode: event.target.countryCode.value,
callNumber: parseInt(event.target.callNumber.value),
emailAddress: event.target.emailAddress.value,
website: event.target.website.value,
socials: {},
companyUser: {
connect: { id: 'cl0y4y8xo0021mwtcmwlqfif6' }
}
}
const companyJSON = JSON.stringify(company)
const endpoint = '/api/addCompany/addCompany'
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: companyJSON,
}
const response = await fetch(endpoint, options)
const data = await response.json()
console.log(data)
}
return (
<form onSubmit={createCompany} className={styles.form} id="signupForm" noValidate>
<h2>Company Information</h2>
<div className="fieldWrapper">
<input type="text" id="companyName" name="companyName" placeholder=" " />
<label htmlFor="companyName">Company Name<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="text" list="genders" id="gender" name="gender" placeholder=" " />
<label htmlFor="gender">Gender<span>*</span></label>
<div className='errorMessage'></div>
<datalist id="genders">
<option>Female</option>
<option>Male</option>
</datalist>
</div>
<div className="fieldWrapper">
<input type="text" id="firstName" name="firstName" placeholder=" " />
<label htmlFor="firstName">First Name<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="text" id="lastName" name="lastName" placeholder=" " />
<label htmlFor="lastName">Last Name<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="text" id="street" name="street" placeholder=" " />
<label htmlFor="street">Street<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="number" id="houseNumber" name="houseNumber" placeholder=" " />
<label htmlFor="houseNumber">House Number<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="number" id="postcode" name="postcode" placeholder=" " />
<label htmlFor="postcode">Postcode<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="text" id="city" name="city" placeholder=" " />
<label htmlFor="city">City<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="text" id="country" name="country" placeholder=" " />
<label htmlFor="country">Country<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="text" id="countryCode" name="countryCode" placeholder=" " />
<label htmlFor="countryCode">Country Code<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="number" id="callNumber" name="callNumber" placeholder=" " />
<label htmlFor="callNumber">Call Number<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="email" id="emailAddress" name="emailAddress" placeholder=" " />
<label htmlFor="emailAddress">Email Address<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="text" id="website" name="website" placeholder=" " />
<label htmlFor="website">Website</label>
</div>
<div className="fieldWrapper">
<input type="text" id="socials" name="socials" placeholder=" " />
<label htmlFor="socials">Socials</label>
</div>
<div className="fieldWrapper">
<button type="submit">Save</button>
</div>
</form>
)
}
export default Register
And this is the the addCompany file's code which serves as the Next.js API route for my fetch API request:
import { Prisma } from '#prisma/client';
import { NextApiRequest, NextApiResponse } from 'next';
import { prisma } from '../../../prisma/prisma_client';
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const {body} = req;
const companyData: Prisma.CompanyCreateInput = JSON.parse(body);
const addCompany = await prisma.company.create({
data: companyData
})
res.status(200).json(addCompany);
}
export default handler
I appreciate any help. Thank you.
I tried to comment out
const data = await response.json() console.log(data)
in the Register component so the error "Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0" disappeared but that is no solution to the problem at all.
I also tried to adjust the route of my fetch request to any possible option because I wasn't sure how exactly Next.js autocompletes it, for example I tried: '/api/addCompany/addCompany.ts' and so on.
I expect the problem to be something small, I hope it isn't typo.
Thank you again.
PS: I also checked similar posts on this matter but couldn't find a fix for my problem.
There is no need to reparse the body data in the API endpoint because Next.js middleware convert that data to an object already:
API routes provide built in middlewares which parse the incoming
request (req). Those middlewares are:
req.cookies - An object containing the cookies sent by the request. Defaults to {}
req.query - An object containing the query string. Defaults to {}
req.body - An object containing the body parsed by content-type, or null if no body was sent
something like below should work:
import { Prisma } from '#prisma/client';
import { NextApiRequest, NextApiResponse } from 'next';
import { prisma } from '../../../prisma/prisma_client';
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const {body: companyData} = req;
//const companyData: Prisma.CompanyCreateInput = JSON.parse(body);<- No need to reparse the data here
const addCompany = await prisma.company.create({
data: companyData
})
res.status(200).json(addCompany);
}
export default handler
Thanks to this answer here for clarification.

why PUT request is sending NULL value to sql database

when i click on EDIT button to send the form data ,insted of displaying the editted text ,it displays blank field and NULL is send to the database.
i have correctly used
app.use(express.json());
app.use(express.urlencoded({extended: true}));
this problem is only there for PUT request.POST is working fine.
Can anyone please help me ?
i am using PERN stack and have made a restful API .this is the route for Updating a field:
app.put('/placements/announcements/:id',async(req,res)=>{
try{
const {id}=req.params;
const {editPost,title}=req.body;
const updatePost= await pool.query("update announcements set an_desc=$1,an_title=$2 where an_id=$3 returning *",[editPost,title,id]);
res.json("updated");
}catch(err){
console.error(err.message);
}
});
here is the form:
<Modal
size="lg"
show={lgShow}
onHide={() => setLgShow(false)}
aria-labelledby="example-modal-sizes-title-lg"
id={`id${p.an_id}`}
>
<Modal.Header closeButton>
<Modal.Title id="example-modal-sizes-title-lg">
{p.an_title}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<form onSubmit={updatePost}>
<div className="form-group">
<textarea className="form-control"
id="exampleFormControlTextarea1"
rows="3"
value={editPost}
onChange={e=>setEditPost(e.target.value)}
name="editPost"
>
</textarea>
<input type="text" value={title} onChange={e=>setTitle(e.target.value)} />
<button type="submit" value="Submit" className="btn btn-primary mt-2 float-end ">
Edit
</button>
</div>
</form>
</Modal.Body>
</Modal>
<textarea className="form-control"
id="exampleFormControlTextarea1"
rows="3"
value={editPost}
onChange={e=>setEditPost(e.target.value)}
name="editPost"
>
</textarea>
<input type="text" value={title} onChange={e=>setTitle(e.target.value)} />
<button type="submit" value="Submit" className="btn btn-primary mt-2 float-end ">
Edit
</button>
</div>
</form>
</Modal.Body>
</Modal>
and this is the update function:
const EditPost=({p,category})=>{
const [lgShow, setLgShow] = useState(false);
const [editPost,setEditPost]= useState(p.an_desc);
const [title,setTitle]=useState(p.an_title);
const updatePost= async e=>{
e.preventDefault();
try{
const body={editPost,title};
const response= await fetch(`http://localhost:5000/${category}/announcements/${p.an_id}`,{
method:"PUT",
header:{"Content-Type":"application/json"},
body: JSON.stringify(body)
})
window.location=`${category}`;
console.log("updated");
}catch(err){
console.error(err.message);
}
}

Vee Validate Nuxt JS Property or method "required" is not defined on the instance but referenced during render

I'm new to Vue and Nuxt and I can't seem to overcome this error:
[Vue warn]:Property or method "required" is not defined on the instance but referenced during render
this is the source code:
vee-validate.js :
import Vue from 'vue'
import {ValidationProvider, ValidationObserver,extend} from 'vee-validate'
import {required,email} from 'vee-validate/dist/rules'
Vue.component('ValidationProvider',ValidationProvider)
Vue.component('ValidationObserver',ValidationObserver)
extend('required' ,{
...required,
message:'This field is required'
})
extend('email',{
...email,
message:'This field is required'
})
and for the form :
<template>
<div>
<div class="col-6 pr-2">
<label for="name">*Name </label> <br />
<ValidationObserver>
<ValidationProvider v-slot="{ errors }" mode="passive" rules="required">
<input id="name" v-model="required" type="text" name="name" placeholder="Your name" />
<span class="validation-span">{{ errors[0] }}</span>
</ValidationProvider>
</ValidationObserver>
</div>
<div class="col-6 pr-2">
<label for="company">Company</label> <br />
<input id="company" type="text" label="Company" placeholder="Name of your company" />
<br />
</div>
<div class="col-6 pr-2">
<br />
<ValidationObserver>
<ValidationProvider v-slot="{ errors }" mode="passive" rules="required|email">
<label for="email">*Email</label> <br />
<input id="email" v-model="email" type="email" placeholder="example#email.com" /> <br />
<span class="validation-span">{{ errors[0] }}</span>
</ValidationProvider>
</ValidationObserver>
</div>
</div>
</template>
This is how we do it in my team.
/utils/vee-validate-rules.js
import { extend } from 'vee-validate'
import { email as defaultEmail, required as defaultRequired } from 'vee-validate/dist/rules'
const email = extend('email', {
...defaultEmail,
})
const required = extend('required', {
...defaultRequired,
})
export { extend, email, required }
Some .vue file
<script>
import { extend, required, email } from '~/utils/vee-validate-rules'
export default {
beforeCreate() {
extend('required', { ...required, message: this.$t('veeValidate.required') })
extend('email', { ...email, message: this.$t('veeValidate.email') })
},
}
</script>
This works great so far. Could be done better in terms of i18n tho.
Also, don't forget to transpile it too
nuxt.config.js
build: {
transpile: ['vee-validate/dist/rules']
}

Input field is not working

When I am using state variable as a value for the input fields, second input field is not working.
Here is the code:
<input
type="text"
className="form-control"
placeholder="mobileNumber"
onChange={this.handleLoginMobileNumber}
onKeyUp={this.handleLoginMobileNumber}
value={this.state.loginMobileNumber}
/>
<input
type="text"
className="form-control"
placeholder="Passcode"
maxLength="4"
value={this.state.loginPasscode}
/>
<br/>
<button
className="btn btn-large btn-primary medata-login-form-input medata-login-form-submit-button"
onClick={this.submitLogin}>
Log in
</button>
Help me, Thanks.
Issue is, you are using Controlled Component and you forgot to define the onChange method and update the state value with password field, because of that password field is read only.
Check this example:
class App extends React.Component{
constructor(){
super();
this.state = {
loginMobileNumber: '',
loginPasscode: ''
}
}
handleLoginMobileNumber(e){
this.setState({loginMobileNumber: e.target.value})
}
loginPasscode(e){
this.setState({loginPasscode: e.target.password})
}
render(){
return(
<div>
<input
type="text"
className="form-control"
placeholder="mobileNumber"
onChange={this.handleLoginMobileNumber.bind(this)}
value={this.state.loginMobileNumber}
/>
<input
type="password"
className="form-control"
placeholder="Passcode"
maxLength="4"
value={this.state.loginPasscode}
onChange={this.loginPasscode.bind(this)}
/>
</div>
)
}
}
ReactDOM.render(<App/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'/>

How to change URL form with GET method?

Form:
<form action="/test" method="GET">
<input name="cat3" value="1" type="checkbox">
<input name="cat3" value="5" type="checkbox">
<input name="cat3" value="8" type="checkbox">
<input name="cat3" value="18" type="checkbox">
<input type="submit" value="SUBMIT">
</form>
How to change URL form with GET method?
Before: test?cat3=1&cat3=5&cat3=8&cat3=18
After: test?cat3=1,5,8,18
I want to use jQuery.
Many thanks!
Here you go! This example, using jQuery, will grab your form elements as your question is asking and perform a GET request to the desired URL. You may notice the commas encoded as "%2C" - but those will be automatically decoded for you when you read the data on the server side.
$(document).ready(function(){
$('#myForm').submit(function() {
// Create our form object. You could optionally serialize our whole form here if there are additional parameters in the form you want
var params = {
"cat3":""
};
// Loop through the checked items named cat3 and add to our param string
$(this).children('input[name=cat3]:checked').each(function(i,obj){
if( i > 0 ) params.cat3 += ',';
params.cat3 += $(obj).val();
});
// "submit" our form by going to the properly formed GET url
var url = $(this).attr('action') + '?' + $.param( params );
// Sample alert you can remove
alert( "This form will now GET the URL: " + url );
// Perform the submission
window.location.href = url;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="/test" method="GET" id="myForm">
<input name="cat3" value="1" type="checkbox">
<input name="cat3" value="5" type="checkbox">
<input name="cat3" value="8" type="checkbox">
<input name="cat3" value="18" type="checkbox">
<input type="submit" value="SUBMIT">
</form>
My friend found a solution:
$(document).ready(function() {
// Change Url Form: &cat3=0&cat3=1&cat3=2 -> &cat3=0,1,2
var changeUrlForm = function(catName){
$('form').on('submit', function(){
var myForm = $(this);
var checkbox = myForm.find("input[type=checkbox][name="+ catName +"]");
var catValue = '';
checkbox.each(function(index, element) {
var name = element.name;
var value = element.value;
if (element.checked) {
if (catValue === '') {
catValue += value;
} else {
catValue += '‚' + value;
}
element.disabled = true;
}
});
if (catValue !== '') {
myForm.append('<input type="hidden" name="' + catName + '" value="' + catValue + '" />');
}
});
};
// Press 'Enter' key
$('.search-form .inputbox-search').keypress(function(e) {
if (e.which == 13) {
changeUrlForm('cat3');
changeUrlForm('cat4');
alert(window.location.href);
}
});
// Click to submit button
$('.search-form .btn-submit').on('click', function() {
changeUrlForm('cat3');
changeUrlForm('cat4');
alert(window.location.href);
$(".search-form").submit();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="/test" method="GET" class="search-form">
<input name="cat3" value="1" type="checkbox">1
<input name="cat3" value="3" type="checkbox">3
<input name="cat3" value="5" type="checkbox">5
<input name="cat3" value="7" type="checkbox">7
<br />
<input name="cat4" value="2" type="checkbox">2
<input name="cat4" value="4" type="checkbox">4
<input name="cat4" value="6" type="checkbox">6
<br />
<br />
Submit
<br />
<br />
<input type="text" placeholder="Search" class="inputbox-search" />
</form>