How do I do this with javascript fetch - javascript

I was checking out this answer.
It's basically a request to Mailchimp to send a confirmation email to the user when they submit their email.
The code works perfectly with jquery. But I don't like jquery. And it's kind of annoying to have to add it just for this tiny snippet, since I won't be using it in the rest of my project. I already tried "translating" this into vanilla javascript using fetch but it doesn't seem to work.
function register($form) {
$.ajax({
type: $form.attr('method'),
url: $form.attr('action'),
data: $form.serialize(),
cache : false,
dataType : 'json',
contentType: "application/json; charset=utf-8",
error : function(err) { alert("Could not connect to the registration server. Please try again later."); },
success : function(data) {
if (data.result != "success") {
// Something went wrong, do something to notify the user. maybe alert(data.msg);
} else {
// It worked, carry on...
}
}
});
}
EDIT
Some suggested I should add the HTML form:
I am doing all this because I want to send the user email to my MailChimp subscription list. But I want it to do it directly from my website without redirecting to the Mailchimp subscription page.
<form action="https://herokuapp.us5.list-manage.com/subscribe/post-json?u=070e69e5e3e6e664a8066e48f&id=0bf75ac6c4&c=?" method="get" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate newsletter__form" target="_blank">
<label for="mce-EMAIL">Ingresa tu correo electrónico:</label>
<input type="email" placeholder="ejemplo#gmail.com" value="" name="EMAIL" class="required textfield email__textfield" id="mce-EMAIL">
<input type="submit" value="suscribirme" name="subscribe" id="mc-embedded-subscribe" class="button raise">
<div id="mce-responses" class="clear">
<div class="response" id="mce-error-response" style="display:none"></div>
<div class="response" id="mce-success-response" style="display:none"></div>
</div> <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
<div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_070e69e5e3e6e664a8066e48f_0bf75ac6c4" tabindex="-1" value=""></div>
</form>
I also found out jquery ajax method get accepts the data argument but it takes what's inside of the data and adds it to the URL. So it's still a get request with no body. I am trying to find a way to do that but with fetch but somehow the jquery URL has things I don't know where they come from. I also tried doing this with POST method and fetch but apparently, the server doesn't allow that.
For what is worth this is how the URL generated by jquery request looks like:
https://herokuapp.us5.list-manage.com/subscribe/post-json?u=070e69e5e3e6e664a8066e48f&id=0bf75ac6c4&c=jQuery35105022544193369527_1633147928440&EMAIL=email123456%40gmail.com&b_070e69e5e3e6e664a8066e48f_0bf75ac6c4=&_=1633147928441
And this is how I can trick my URL to look like with fetch. Here I get a CORS error
https://herokuapp.us5.list-manage.com/subscribe/post-json?u=070e69e5e3e6e664a8066e48f&id=0bf75ac6c4&c=?&EMAIL=paula.uzcategui68%40gmail.com&b_070e69e5e3e6e664a8066e48f_0bf75ac6c4=
And this is what I'm doing with fetch
function register(form) {
data = new FormData(form);
data = Object.fromEntries(data);
data = Object.entries(data);
let arroba = /#/gi;
let action = form.getAttribute("action")+ "&"+ data[0][0] +"="+ data[0][1].replace(arroba, '%40') + "&" + data[1][0] + "=" + data[1][1]
// console.log(action)
fetch(action, {
method: 'get',
cache: 'no-cache',
headers: {
'content-type': 'application/json; charset=utf-8'
},
})
.then(response => response.json())
.catch(error => {
alert("Could not connect to the registration server. Please try again later."+ error)
});
}

Try this, it is the exact solution for your question (I hope). If you still get stuck please comment down, I will explain.
async function register(form) {
let data = new FormData(form);
data = JSON.stringify(Object.fromEntries(data)); // convert formdata to json
let response = await fetch(form.action, {
method: form.method,
body: data,
cache: 'no-cache',
headers: {
'content-type': 'application/json; charset=utf-8'
}
})
.then(response => response.json())
.catch(error => {
alert("Could not connect to the registration server. Please try again later.")
});
}

Related

Form submit value giving null - mongoose and express js

I am trying to make a way to send data from a basic html form to mongodb using express. but it's giving me null when I post it.
I used the following Schema : commentname: String.
Here's the HTML:
<form id="form" onsubmit="return false;">
<input type="textbox" id="cmt-1" placeholder="comment here"/>
</form>
<button type="button" onclick="submit()" class="submit">
submit
</button>
JS:
var cmt = document.getElementById('cmt-1').value;
var comment = {commentname: ''};
comment = {commentname: cmt};
function submit () {
async function postData (url = '', data = {}) {
const response = await fetch(url, {
method: 'POST',
mode: 'same-origin',
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data) // body data type must match "Content-Type" header
});
return response.json(); // parses JSON response into native JavaScript objects
}
postData(
'https://realtime-comt-system-100.glitch.me/comments/add',{comment}
)
.then(data => { console.log(data); });
}
What am I missing?
just try this code but check the url i put . don't put the whole url just put the path name .
also take this code copy and paste , the html and the java script take them both because i changed both of them
var form = document.getElementById('form');
form.addEventListener('submit', async(e) => {
e.preventDefault();
let cmt = form.cmt.value;
let data = {commentname: cmt};
const response = await fetch('/comments/add', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}).then(res =>{
console.log(res)
}).catch(err){
console.error(err)
}
})
<form id="form">
<input type="textbox" id="cmt-1" name='cmt' placeholder="comment here"/>
</form>
<button type="submit" onclick="submit()" class="submit">
submit
</button>
The problem is not being caused by the code posted above.
It's a Mongoose problem. You are trying to create two documents with the same id, when that id has been specified unique to Mongoose.
This is what the code is posting in the body to the backend, a JSON string:
{"comment":{"commentname":"my sample comment"}}
The fact that you're posting an object inside an object looks suspicious. This pattern would be more common:
{"commentname":"my sample comment"}
But since there is no backend code posted, it's impossible to tell if this is correct.
When I tried posting {"comment":{"commentname":"my sample comment"}} to the backend URL using Postman, I received the following response code:
400 Bad Request
The response body:
"Error: MongoError: E11000 duplicate key error collection: database.comments index: commentname_1 dup key: { commentname: null }"
From Mastering JS - Debug E11000 Errors in Mongoose
MongoDB's E11000 error is a common source of confusion. This error occurs when two documents have the same value for a field that's defined as unique in your Mongoose schema.
Mongoose models have an _id field that's always unique.

Improperly sending form data in html

So i would like to send Whatever i type in my input bar in to be sent to whatever api link via post method. But whenever i send it i get {} . The problem is when i dont send anything in the input bar A.K.A left blank and press submit i still get {}. But when i type gibberish its still {} . So i assume whatever i typed in is not being sent to the api link.
Also when i hard code something like body: JSON.stringify(this.myForm) it shows up as a response in the back end. So i believe i error lies withing this body of my fetch request. heres my code what should i put for the body.
<html>
<body>
<h1>Draft V0.1</h1>
<form class="form" id="myForm">
<label for="skill">add skill</label>
<input type="text" name="skill" id="skill">
<button type="submit">Submit</button>
</form>
<script>
const myForm = document.getElementById('myForm')
myForm.addEventListener('submit', function (e) {
e.preventDefault();
const formData = new FormData(this);
fetch('https://fj5s3i60a8.execute-api.us-east-1.amazonaws.com/updateSkill', {
method: 'post',
body: JSON.stringify(new FormData(myForm)),
headers:
{
"Content-Type": "application/json; charset=utf-8",
"Accept": 'application/json'
}
}).then(function (response) {
console.log(response)
return response.json();
});
});
</script>
</body>
</html>
Note I was blindly playing around with the body to see what i can parse through it but i would end up getting cors errors.
Thank you in advance
const thisForm = document.getElementById('myForm');
thisForm.addEventListener('submit', async function (e) {
e.preventDefault();
const formData = new FormData(thisForm).entries()
const response = await fetch('https://reqres.in/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(Object.fromEntries(formData))
});
const result = await response.json();
console.log(result)
});
<html>
<body>
<h1>Draft V0.1</h1>
<form class="form" id="myForm">
<label for="skill">add skill</label>
<input type="text" name="skill" id="skill">
<button type="submit">Submit</button>
</form>
</body>
</html>

POST convert to GET when I want to fetch formData?

I want to send an image to server
my code works perfect in Chrome Version 77.0.3865.90
BUT
in Mozilla Firefox (version 69.0.1) POST method changes to GET with this error
Form contains a file input, but is missing method=POST and enctype=multipart/form-data on the form. The file will not be sent.
Request URL: http://localhost:3000/...
Request method: GET
Status code: 200
<form class="form-horizontal" id="form" >
<div class="col">
<label for="images" class="control-label">image</label>
<input type="file" class="form-control" name="images" id="images" >
</div>
<div class="form-group row">
<div class="col">
<button type="submit" class="btn btn-danger">Send</button>
</div>
</div>
</form>
<script>
document.getElementById('form').addEventListener('submit' , async function(event) {
let images = document.querySelector('input[name="images"]');
let formData = new FormData();
formData.append('images' , images.files[0] );
try {
const response = await fetch('http://exampleurl.com/profile', {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-Token': "<%= req.csrfToken() %>",
},
body: formData,
credentials: 'same-origin'
});
} catch (error) {
console.error(error);
}
})
</script>
I can't use method ="POST" and enctype= "multipart/form-data" in the form because csrf tokens can't implement in forms with multipart/form-data enctype
I suspect your form might be submitting twice.
1) AJAX event handler
2) The submit button in the form actually posting the form through html
Try adding the event handler to the form itself, rather than the submit button.
There you can prevent the form from doing what it wants to do so only your AJAX request will go through.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event

Uploading a file with JavaScript/Ajax to SpringBoot endpoint

I am new to front-end development and am having troubles piecing together a solution for this specific form setup.
I have an already created jsp representing this instance creation page. It's a form containing numerous drop downs and check boxes. I need to add a file upload option to it.
The jsp is set up like this...
<form class="form-horizontal" id="editInstanceForm" onsubmit="return false;"> ....
Here's my input field
<div class="form-group" id="uploadForm">
<label class="col-xs-4 control-label instanceDefaultLabel" for="fileSearchField">Default Location and Zoom:</label>
<div class="col-xs-3">
<input name="myFile" type="file" id="fileSearchField" multiple=false>
<button id="upload-button">Upload</button>
</div>
.....
</div>
Now I have an ajax call that I was originally wanting to use before I realized that the whole form is attempting to submit when I uploaded the file. Here it is...
$('#upload-button').click( 'click',
function() {
var form = $('#fileSearchField')[0];
var data = new FormData(form);
$.ajax({
type: "POST",
enctype: 'multipart/form-data',
url: "/edit/uploadfile",
data: data,
processData: false,
contentType: false,
cache: false,
success: function (data) {
alert("hi stuff worked");
},
error: function (e) {
alert("nope!");
}
});
}
);
I got this suggestion in researching how to upload a file with jQuery/ajax and Spring Boot (I am using Spring Boot to create my endpoint). Here are some articles that I have been reading in an attempt to understand how to do this...
https://www.mkyong.com/spring-boot/spring-boot-file-upload-example-ajax-and-rest/
http://javasampleapproach.com/spring-framework/spring-boot/multipartfile-create-spring-ajax-multipartfile-application-downloadupload-files-springboot-jquery-ajax-bootstrap#3_Implement_upload_controller
and many more. This seemed like the solution until I realized this was a form and I think I need to save all the fields at once. This is going to mean that I have to modify the already created ajax function that saves this form and passes it to the end point. Now I don't know how to get my MulitpartFile in as part of this different function. The existing one is like this...
$.ajax({
type: "POST",
url: webroot + "/viewerConfig/mapInstance/insertOrUpdate",
data: JSON.stringify(instanceData),
processData: false,
contentType: 'application/json',
success: function (data) {
if (data.status === "OK") {
alert("Instance created/updated successfully");
} else {
alert("Unknown error");
}
},
fail: function () {
alert("Unknown error");
},
error: function (a) {
alert("Unknown error");
}
});
});
This is exactly where I am stuck and I need to be pointed in the correct and productive direction.
I don't know if this will help but here's my end point that looks like the one I have to hit with my file param added...
#RequestMapping(value = "/insertOrUpdate", method = RequestMethod.POST, consumes = "application/json")
public #ResponseBody BaseStatusResponse insertOrUpdate(final #RequestBody SaveAdminInstanceView newInstance, HttpServletResponse servletResponse,
#RequestParam MultipartFile file)
EDIT:
I have done some curl troubleshooting and it's the MulitpartFile that's failing. I am passing it as suggested yet I am getting this exception:
org.springframework.web.multipart.MultipartException: The current request is not a multipart request</p><p><b>Description</b> The server encountered an unexpected condition that prevented it from fulfilling the request.</p><p><b>Exception</b></p><pre>org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: The current request is not a multipart request
You can try below code:
$.ajax({
url: "/edit/uploadfile",
type: 'POST',
data: new FormData($(this)[0]),
enctype: 'multipart/form-data',
processData: false, // tell jQuery not to process the data
contentType: false, // tell jQuery not to set contentType
cache: false,
success: function(res) {
console.log(res);
},
error: function(res) {
console.log('ERR: ' + res);
}
});
And in controller, you needn't declare consumes = "application/json"
I figured out what I was doing wrong. It wants the form element not the file one. FormData needs the Form. Thanks for your help though! :)
There you have 3 diferent ways to do this with spring-boot at 2022 be sure the file size is lower than the server maximun file size.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Spring Boot file upload example</h1>
<form method="POST" action="http://192.168.12.168:8081/uploadfile" enctype="multipart/form-data">
<input type="file" id="fileinput" name="file" /><br/><br/>
<input type="submit" value="Submit using HTML" />
</form>
<button onclick="submitStyle1()">Submit using FETCH</button>
<button onclick="submitStyle2()">Submit using XHR</button>
</body>
<script>
function submitStyle1(){
const photo = document.getElementById("fileinput").files[0];
const formData = new FormData();
formData.append("file", photo);
fetch('http://192.168.12.168:8081/uploadfile', {method: "POST", body: formData});
}
function submitStyle2(){
const photo = document.getElementById("fileinput").files[0]; // file from input
const req = new XMLHttpRequest();
const formData = new FormData();
formData.append("file", photo);
req.open("POST", 'http://192.168.12.168:8081/uploadfile');
req.send(formData);
}
</script>
</html>
To see an example type me at https://github.com/JmJDrWrk

Stripe with Google App Engine - Upload image directly through browser using Javascript for Mananaged Account Identity Verification

Hi I've been searching for ages about how to upload directly from the browser, as is suggested in the case of using Stripe with Google App Engine at this forum. Also the Stripe documentation suggests it is possible to upload directly from a browser as is suggested here.
I have been trying with AJAX but from my effort and research it seems it is not possible to get the path to the local file because of security reasons. The code below shows the closest I've gotten, however I don't know how to upload an image through the browser without it touching the server. The console returns an error of "Invalid file: must be uploaded in a multipart/form-data request".
Next I will try using Jquery Form Plugin, however I don't know if I will have any success with that.
var formData = new FormData($('#theHTMLForm')[0]);
var sendarray={purpose:"identity_document", file:formData};
sendarray=JSON.stringify(sendarray);
$.ajax({
type:'POST',
url: 'https://uploads.stripe.com/v1/files',
data: sendarray,
mimeType: "multipart/form-data",
headers: {
"Authorization": "Bearer STRIPEPUBLISHABLEKEY"
},
contentType: 'application/json',
processData: false,
success:function(data){
alert('success');
console.log(data);
},
error: function(data){
alert('error');
console.log(data);
}
});
Thanks to a very kind person on this forumn, I was able to make it work!! I'll copy the answer here just in case anybody comes by looking for the same answer.
HTML
<div>
<form method="post" id="fileinfo" name="fileinfo" ajax="true">
<input type="file" id="file-box" name="file" required />
<input type="submit" value="Upload" />
</form>
</div>
<div>
<div id='label-results'>...</div>
<pre id="upload-results"></pre>
</div>
And Javascript
$('#fileinfo').submit(function(event) {
event.preventDefault();
var data = new FormData();
var publishableKey = 'pk_test_***';
data.append('file', $('#file-box')[0].files[0]);
data.append('purpose', 'identity_document');
$.ajax({
url: 'https://uploads.stripe.com/v1/files',
data: data,
headers: {
'Authorization': 'Bearer ' + publishableKey
},
cache: false,
contentType: false,
processData: false,
type: 'POST',
}).done(function(data) {
$('#label-results').text('Success!');
$('#upload-results').text(JSON.stringify(data, null, 3));
}).fail(function(response, type, message) {
$('#label-results').text('Failure: ' + type + ', ' + message);
$('#upload-results').text(JSON.stringify(response.responseJSON, null, 3));
});
return false;
});

Categories

Resources