why PUT request is sending NULL value to sql database - postgresql

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);
}
}

Related

Need help getting Nuxt 3 form to post emails to my Strapi 4 Subscriber collection

I have the following code but it does not post to my Subscriber collection. When I put in an email address it does not post to my subscriber collection type. Also it does not console.log
Using Nuxt3/Strapi4
<template>
<div class="relative flex justify-center w-full h-64 pb-16 mt-14 subscribe-bg">
<Container>
<div class="w-full mx-auto lg:w-3/6">
<div class="px-10 -mt-12 text-center bg-white rounded-lg shadow-xl py-9 subscribe-box">
<Heading tag="h3" font-style="h3">Subscribe</Heading>
<Heading tag="h2" font-style="h2">Never miss a planner</Heading>
<p
class="w-full px-2 mx-auto text-center pb-7 text-brand-grey-400"
>Subscribe to receice the worlds most cutting edge planner news direct to your inbox. Our newsletter is on fire.</p>
<div class="flex items-center">
<form #submit.prevent="handleSuscribe">
<input-field
id="email"
v-model="email.email"
type="email"
name="email"
placeholder="Your email"
class="w-3/4 mr-8"
/>
<Btn class="h-full" type="submit">Subscribe</Btn>
</form>
</div>
</div>
</div>
</Container>
</div>
</template>
<script setup>
import { useToast } from 'vue-toastification';
const toast = useToast();
const email = ref({ email: "" })
const handleSuscribe = async () => {
await $fetch("http://localhost:1337/api/subscribers", {
method: "POST",
body: {
data: {
email: email.value,
}
}
})
console.log(email.value)
console.log(handleSuscribe)
}
</script>
Tried to convert from the following code from Nuxt 2. It looked pretty simple at first but now I am running into issues.
<template>
<div
class="sm:flex mx-auto items-center m-10 justify-center space-x-6 sm:space-x-20 m-3 sm:m-6 mx-6"
>
<div>
<h1 class="text-lg m-7">Sign Up For NewsLetter</h1>
</div>
<div>
<form #submit="handleSuscribe">
<input
id=""
v-model="email"
class="p-2 m-3 sm:m-0 border border-solid border-t-0 border-l-0 border-r-0 border-b-1 outline-none border-black"
type="email"
name=""
placeholder="email"
/>
<button type="submit" class="button--grey">Subscribe</button>
</form>
</div>
</div>
</template>
<script>
export default {
name: 'NewsLetter',
data() {
return {
email: '',
}
},
methods: {
async handleSuscribe(e) {
e.preventDefault()
this.$swal({
title: 'Successful!',
text: 'Thanks for Subscribing',
icon: 'success',
button: 'Ok',
})
await this.$strapi.$subscribers.create({ Email: this.email })
this.email = '' // clear email input
},
},
}
</script>

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.

TypeError: editorState.getCurrentContent is not a function

I am trying to console the result from react draft wysiwyg and I am getting editorState.getCurrentContent is not a function. I am not sure where did I go wrong. Many thanks in advance and greatly appreciate any helps. Thanks
import React,{useState} from 'react'
import { render } from 'react-dom';
import { Editor } from 'react-draft-wysiwyg';
import {EditorState} from "draft-js";
import { stateToHTML } from "draft-js-export-html";
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
const AddBlog= () => {
const [editorState, setEditorState] = useState(
() => EditorState.createEmpty(),
);
const handleChange = (editorState) =>{
const contentState = stateToHTML(editorState.getCurrentContent())
// JSON.stringify(convertToRaw(editorState.getCurrentContent()))
console.log(contentState)
}
return (
<div className="container-fluid">
<div className="card-wrapper-tutorial">
<div className="card">
<div className="card-body">
<h4 className="card-title">New Code Snippet</h4>
<form autoComplete="off">
<div className="form-group">
<label htmlFor="title">Title</label>
<input id="title" type="text" className="form-control" placeholder="title" name="title" disabled = {disabled} onChange={handleChange} />
</div>
<div className="form-group">
<label htmlFor="body">Body</label>
<Editor
defaultEditorState={editorState}
onEditorStateChange={setEditorState}
wrapperClassName="wrapper-class"
editorClassName="editor-class"
toolbarClassName="toolbar-class"
onChange={handleChange}
/>
</div>
<div className="form-group">
<button type="submit" className="btn btn-primary btn-block">
{loading && <i className="fa fa-refresh fa-spin"></i>}
Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
)
}
export default AddBlog
You have the handleChange in two places which they don't belong
on the input's onChange, the callback for onChange would not
be an editorState but and input event e.
on the Editor
component, the callback for onChange would not be an editorState
also but a RawDraftContentState which is the string html.
You probably meant to place it in the onEditorStateChange for Editor:
<Editor
defaultEditorState={editorState}
onEditorStateChange={editorState => {
setEditorState(editorState);
handleChange(editorState);
}}
wrapperClassName="wrapper-class"
editorClassName="editor-class"
toolbarClassName="toolbar-class"
/>
or leaving the code as is and modifying the handleChange to expect RawDraftContentState
const handleChange = (rawDraftContentState) =>{
// no need for convertToRaw or stateToHtml anymore
console.log(rawDraftContentState)
}

getting error when update button is pressed

I have a vue application which inserts, updates and delete posts by using mongodb but i am having a problem with the update function. when i press the button which updates the posts i am getting the following error. note in the postComponent.vue i just added the template to show how the form is being submitted and the function in the sciprt tag updatePost
Access to fetch at 'http://localhost:5000/api/posts/5e31a39024a21d44bc4654af' from origin 'http://localhost:8080' has been blocked by CORS policy: Method UPDATE is not allowed by Access-Control-Allow-Methods in preflight response.
posts.js
//update posts
router.put('/:id', async (req,res) => {
const posts = await loadpostscollection();
await posts.updateOne({
topic: req.body.topic,
price: req.body.price,
location: req.body.location,
provider: req.body. provider,
createdAt: new Date()
});
res.status(201).send();
});
postServise.js
//update Posts
static updatePost( id, topic, price, location, provider) {
return fetch(url + id, {
method: "UPDATE",
mode: 'cors',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=UTF-8'
},
body: JSON.stringify({
topic,
price,
location,
provider
}
)
});
}
postComponent.vue
<template>
<div class ="container">
<router-link to="/postComponent" >Show me post component</router-link>
<h1>Create a new course</h1>
<div class="create-post">
<label for="create-topic">Add topic: </label>
<br>
<br>
<input type="text" id="create-topic" v-model="topic" placeholder="enter" required>
<br>
<br>
<label for="create-price">Add a price: </label>
<br>
<br>
<input type="text" id="create-price" v-model="price" placeholder="enter">
<br>
<br>
<label for="create-location">Add a location: </label>
<br>
<br>
<input type="text" id="create-location" v-model="location" placeholder="enter">
<br>
<br>
<label for="create-provider">Add a provider: </label>
<br>
<br>
<input type="text" id="create-provider" v-model="provider" placeholder="enter">
<br>
<br>
<button v-on:click="insertPost">Create course</button>
</div>
<hr>
<p class="error" v-if="error">{{ error }}</p>
<div class="posts-container">
<div class="post"
v-for="(post, index) in posts"
v-bind:item="post"
v-bind:index="index"
v-bind:key="post._id">
<br>
<p>Course topic:</p>
<p class="text">{{post.topic}} </p>
<p>Course price:</p>
<p class="text"> {{post.price}} </p>
<p>Course location:</p>
<p class="text">{{post.location}} </p>
<p>Created by:</p>
<p class="text"> {{post.provider}} </p>
<button v-on:click="deletePost(post._id)">Delete course</button>
<br>
<br>
<br>
<br>
<input type="text" v-model="post.topic"/>
<input type="text" v-model="post.price"/>
<br>
<br>
<input type="text" v-model="post.location"/>
<br>
<br>
<input type="text" v-model="post.provider"/>
<button v-on:click="updatePost(post)">Update course</button>
</div>
</div>
</div>
</template>
<script>
async updatePost({ _id: id, topic, price, location, provider }) {
await postService.updatePost(id, topic, price, location, provider);
this.posts = await postService.getPosts();
},
</script>
index.js
const express = require ('express');
const bodyparser = require ('body-parser');
const cors = require ('cors');
const app = express();
app.use(bodyparser.json());
app.use(cors({ origin: '*'}));
const posts = require('./api/posts');
const users = require('./api/users');
app.use('/api/posts', posts);
app.use('/api/users', users);
const port = process.env.port || 5000;
app.listen(port, () => console.log(`Server started on port ${port}`));
https://i.stack.imgur.com/75fRb.png
Is not a problem of vue or JS, it's the CORS request problem. You must to allow CROS request on backend, or change request URI to http://localhost:8080/api/posts/5e31a39024a21d44bc4654af.

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'/>