Netlify Forms - Empty Submission - Vue (Gridsome) - javascript

I hate to do this (share the whole code), but I feel like I have no other choice. I have been banging my head against the wall for the past two days. It is one issue after another. Currently, I am soooo close to getting Forms working.
For some reason an empty field is submitted. I can't find the reason, it is really hard to debug.
<template>
<form
name="add-subscriber"
id="myForm"
method="post"
data-netlify="true"
data-netlify-honeypot="bot-field"
#submit.prevent="handleFormSubmit">
<input type="hidden" name="form-name" value="add-subscriber" />
<input type="email" name="email" v-model="formData.userEmail">
<button type="submit" name="button">Subscribe</button>
</form>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
formData: {},
}
},
methods: {
encode(data) {
return Object.keys(data)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
.join("&");
},
handleFormSubmit(e) {
const axiosConfig = {
header: { "Content-Type": "application/x-www-form-urlencoded" }
};
axios.post(
location.href,
this.encode({
'form-name': e.target.getAttribute("name"),
...this.formData,
}),
axiosConfig
)
.then(data => console.log(data))
.catch(error => console.log(error))
.then(document.getElementById("myForm").innerHTML = `<div>Almost there! Check your inbox for a confirmation e-mail.</div>`)
}
}
}
</script>
If there is anything that comes to mind or jumps at you, I would really appreciate your help! Thanks a ton in advance.
P.S. I used the guides from Netlify and CSS-Tricks
Edit
The Params of my POST request seem legit:
-----------------------------171747581031589150472368446206
Content-Disposition: form-data; name="form-name"
add-subscriber
-----------------------------171747581031589150472368446206
Content-Disposition: form-data; name="userEmail"
me#rasul.com
-----------------------------171747581031589150472368446206--
However, the response is a little weird. It is returning the whole page, for some reason:

Related

.then code in the event handler did not run after the submit button is pressed

I have the following code for my React component.
import React, {useRef, useState } from "react"
import { updateUser } from "../api callers/User"
import Loader from "../components/Loader/Loader"
import { useUser } from "./General"
export default function Settings(){
let user=useUser()
let reminderViaEmailShouldBeSendTo=useRef<HTMLInputElement|null>(null)
let reminderViaPhoneShouldBeSendTo=useRef<HTMLInputElement|null>(null)
let [isSavingSettings, setIsSavingSettings]=useState(false)
function onsubmit(event:React.FormEvent<HTMLFormElement>){
event.preventDefault();
if (reminderViaPhoneShouldBeSendTo.current==null || reminderViaEmailShouldBeSendTo
.current==null){
return;
}
setIsSavingSettings(true)
updateUser(user.email, {
reminderViaPhoneShouldBeSendTo:reminderViaPhoneShouldBeSendTo.current.value,
reminderViaEmailShouldBeSendTo:reminderViaEmailShouldBeSendTo.current.value
}, user.authToken).then(
x=>{
setIsSavingSettings(false)
}
)
}
if (user.authToken==""){
return <Loader></Loader>
}
if (isSavingSettings){
return <div className="center">
Saving settings ...
</div>
}
return <form className="container" onSubmit={onsubmit}>
<br></br>
<label>Reminder via email should be send to</label>
<br></br>
<input type="email" ref={reminderViaEmailShouldBeSendTo}
defaultValue={user.reminderViaEmailShouldBeSendTo}></input>
<br></br>
<br></br>
<label>Reminder via phone should be send to</label>
<br></br>
<input type="text" ref={reminderViaPhoneShouldBeSendTo} defaultValue={
user.reminderViaPhoneShouldBeSendTo
}
></input>
<br></br>
<br></br>
<button className="blue-button" >Save settings</button>
</form>
}
The code inside updateUser:
export function updateUser(email: string,
object: { reminderViaEmailShouldBeSendTo?: string, reminderViaPhoneShouldBeSendTo?: string },
authorizationToken: string) {
return callAnApiWithSomeJson(urlOfTheServer + "users/" + email, "PUT", authorizationToken, object)
}
The code inside callAnApiWithSomeJson
export function callAnApiWithSomeJson(
url: string,
method: string,
accessToken: string = "",
json?:Object
) {
return new Promise((resolve, reject) => {
console.log(json);
fetch(url, {
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type':'application/json'
},
method: method,
body: JSON.stringify(json),
keepalive:true,
})
.then((result) => {result.json().then((result) => resolve(result))})
.catch((error) => reject(error));
});
}
When I press the submit button, everything in the onsubmit function in the Settings component runs except for the code
in the if statement and the code in the .then block. Why the code in the .then block did not run and how to fix this issue?
I'm writing it here as comments are not suitable for code. Try to simplify your code, so it's easier to debug:
export function callAnApiWithSomeJson(
url: string,
method: string,
accessToken: string = "",
json?:Object
) {
console.log('callAnApiWithSomeJson');
return fetch(url, {
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type':'application/json'
},
method: method,
body: JSON.stringify(json),
keepalive:true,
})
.then((result) => result.json());
}
That's all you need for that function. Chaining promises is the way to go, not nesting them.
Apart from that - what browser do you use? keepalive is (or at least was) known for having issues on various browsers. Try removing it whatsoever.
Also, put logs in your code (if you're not familiar with how to debug it). IF it enters onsubmit and successfully calls callAnApiWithSomeJson, then you'll know where the issue is. Now it's like "I'm calling many things, and something is not working".

SvelteKit: cookies.set() In Form Action Not Working

I am trying to implement JWT-based user sessions with SvelteKit, and have mostly been following the explanation for form actions given on their website: https://kit.svelte.dev/docs/form-actions
+page.svelte
<form method="POST" action="?/signIn">
<input type="text" name="name" />
<input type="password" name="password" />
<button type="submit">Submit</button>
</form>
+page.server.svelte
import { fail, redirect } from "#sveltejs/kit";
import { signIn } from "$lib/server/database";
export const actions = {
signIn: async ({ cookies, request }) => {
const data = await request.formData();
const name = data.get("name");
const password = data.get("password");
if (!name || !password) {
return fail(400);
}
try {
cookies.set("jwt", await signIn(name, password));
} catch (error) {
return fail(400);
}
throw redirect(303, "/");
},
};
I have tested my signIn method which I import and use here, and it does return a token when called with the correct credentials. So far, so good. However, I noticed that I don't see any cookies in my developer tools. It seems like the cookies.set() call simply does nothing. I'd like to set the returned JWT as a cookie so that I can authenticate my users, so what am I doing wrong?
In case anybody else has this problem: While the cookie was set as it was supposed to when using Chrome, it wasn't in Safari. I solved this by setting the secure option to false, even though the SvelteKit docs state that this is done automatically on localhost.

Email.js Works Locally, But not Once Deployed With React

I have set up Email.js to make a contact page for a website built with Next.js. It works completely fine when run locally, but does not work when hosted. The form does not even reset when the submit button is clicked. I do this in the sendEmail function. The error handler does not trigger either in the .then block. I get this error in the browser console:
Uncaught The user ID is required. Visit https://dashboard.emailjs.com/admin/integration
Here is how I send the emails:
export default function Book(props) {
const form = useRef();
const [sentMessage, setSentMessage] = useState();
const sendEmail = (e) => {
e.preventDefault();
emailjs
.sendForm(
props.SERVICE_ID,
props.EMAIL_TEMPLATE_ID,
form.current,
props.USER_ID
)
.then(
function (response) {
setSentMessage("Message sent successfully!");
},
function (error) {
setSentMessage("Message failed please email directly.");
}
);
document.getElementById("form").reset();
};
return (
<div className={styles.container}>
<div className={styles.formContainer}>
<form
className={styles.form}
ref={form}
onSubmit={sendEmail}
id="form"
>
<h3>Name (required):</h3>
<input type="text" required={true} name="user_name"></input>
<h3>Email (required):</h3>
<input type="email" required={true} name="user_email"></input>
<h3>Phone number (required):</h3>
<input type="number" required={true} name="phone_number"></input>
<h3>Message (optional):</h3>
<textarea name="message"></textarea>
<button type="submit" value="Send">
Submit
</button>
{sentMessage ? <p>{sentMessage}</p> : <p></p>}
</form>
</div>
</div>
);
}
export async function getServerSideProps() {
return {
props: {
USER_ID: process.env.USER_ID,
EMAIL_TEMPLATE_ID: process.env.EMAIL_TEMPLATE_ID,
SERVICE_ID: process.env.SERVICE_ID,
},
};
}
I have a .env.local file with the template id, user id and service id that all work fine locally. I use next-env and dotenv-load in the next.config.js file like so:
dotenvLoad();
const withNextEnv = nextEnv();
module.exports = withNextEnv({
reactStrictMode: true,
webpack(config) {
config.module.rules.push({
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
use: ["#svgr/webpack"],
});
return config;
},
});
I saw some problems online that people had with Gmail and remote email servers, so I switched the account to have no 2 factor authentication and use less secure apps as well. That had no effect.
All you need to do is set up the environment variables in the next.js dashboard then rebuild the site so they take effect.

Nuxt.js page reloading on for submission even with stop.prevent

I've been reading some questions about this exact same topic like but none of them seems to be working for me and I can't spot the error.
I have this form:
<template>
<div class="container">
<form #submit.stop.prevent="submit">
<input v-model="name" type="text" />
<input v-model="email" type="text" />
<button type="submit">Submit</button>
</form>
</div>
</template>
And the following script
<script>
export default {
data() {
return {
name: '',
email: ''
}
},
methods: {
async submit() {
const res = await this.$axios.request({
url: 'locahost:3000/404', // This route doesn't exists
method: 'post',
data: this.$data
})
console.log(res.status)
}
}
}
</script>
As you can see, there are more than one input in the form and I'm using stop.prevent when binding the submit event in the form.
I want to treat any possible errors in the axios request in the script part and update the page based on that (showing an error div or whatever) but without reloading it. However, the page reloads and is going to a 404 error page.
I'm using Nuxt 2.12.2 and I can't see what I'm doing wrong. Any help would be appreciated.
Thanks all!
You can omit the form behaviour by only using the data in your submit method and trigger it by #click on the button without any submit type, like this :
<template>
<div class="container">
<form>
<input v-model="name" type="text" />
<input v-model="email" type="text" />
<button #click="() => submit()">Submit</button>
</form>
</div>
</template>
Like this you will avoid any kind of side effect from the form as you don't need any form data in your axios request...
Ok, I found the answer just by trial and error and it was easier than I thought... It was only about unhandled promise rejection. As I'm using async/await I need to treat exceptions correctly and I was not doing that, the rejection was being propagated and the error handled by nuxt. So changing my code to:
<script>
export default {
data() {
return {
name: '',
email: ''
}
},
methods: {
async submit() {
try {
const res = await this.$axios.request({
url: 'locahost:3000/404', // This route doesn't exists
method: 'post',
data: this.$data
})
console.log(res.status)
} catch (err) {
console.log(err)
}
}
}
}
</script>
That will prevent the error to be handled elsewhere and resulting in a redirection to a 404 page or whatever.

Is it necessary to submit a form wrapped by a blob ? and what's the best practice?

I'm setting up a website page, and want to submit a form with multiple fields, and the Back-end API handles the request is prepared.
Simplified Code shows below:
<form id="contact-form" #submit="postForm" ref="aGeniusForm">
<input type="text" name="companyName">
<input type="email" name="email">
<textarea type="text" name="question"></textarea>
<input type="file" name="file">
<form>
The Back-End is powered by Sprint Boot, and the Controller code is:
#RestController
#RequestMapping("/v1/emails")
class EmailController(
val emailService: EmailService,
val objectMapper: ObjectMapper
){
#PostMapping("/applications", consumes = ["multipart/form-data"])
#ApiOperation("Send a apply email")
fun sendApplyEmail(
#RequestPart body: ApplyEmailPostDto,
#RequestPart("files", required = false) files: List<MultipartFile>
): EmptyResponse {
emailService.sendApplyEmail(body, files)
return EmptyResponse
}
}
The front-end code that creates an http request, the trouble is in postForm method.
// Form component data
export default {
name: "SignupForm",
components: {},
data() {
return {
return {
form: {
companyName: "",
email: "",
question: ""
},
files: []
};
},
methods: {
postForm() {
let formData = new FormData();
// Blob is the point ↓ ↓ ↓
formData.append(
"body",
new Blob([JSON.stringify(this.form)], {
type: "application/json"
})
))
// It is the point ↑ ↑ ↑
// post request, "multipart/form-data"
axios.post(
URL,
formData, // the data to post
{
headers: {
"Content-type": "multipart/form-data"
}
}
)
.then(response => {
//...
})
.catch(error => {
//...
});
}
}
I know that Blob is not widely supported in mobile browsers and in webviews and I don't think using Blob is necessary.
But back-end developer insisted on making me do so.
If front-end code as below
formData.append("body",this.form))
//or
formData.append("body",JSON.stringify(this.form)))
The Back-end API return code 400 with message: "media-type not supported"
The kotlin developer who designed the API declared that he cannot support other media-type easily.
I'm not quite familiar with Spring Boot framework or kotlin. So I need you guys to tell me is that true?
What's the best practice for this condition?

Categories