I'm using node.js/express, and I've got a view with a form on it - that form POST's to a route, which then returns json.
I'd like to (to start with at least) send off my form, and have the data that's returned be shown underneath the form (on the same view).
What's the best way of doing this in the most 'express-y' way possible?
Ideally without a page refresh.
Ajax will do what I'm after - but is that a great way of doing it?
Thanks for any insight
The bare minimum of what you're looking for would look something like this:
Client side
fetch('your_endpoint', {
method: 'POST',
body: JSON.stringify(formData),
}).then((response) => {
// success
return response.json();
})
.then((data) => {
// add data to DOM
})
.catch((error) => {
// failed to send
});
}
Server side using Expressjs
router.post('/your_endpoint', (req, res, next) => {
// process request
res.status(200).json({ "data": your_data });
});
Related
I am a university student and this is my first time of putting all together of server, api and client sides.
My problem is that first I have created an API using Django-Rest framework.
When I post data to that server using fetch function in JavaScript, it keeps posting that data and does not stop until I close. In the server database, many same data have been created.
I cannot figure out how to fix it. My intention was I want to post the data just once.
Please help me how to do it.
Thank you.
This is my javascript code 👇
const testPost = () => {
fetch('http://127.0.0.1:8000/mysite/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'player1Hp': 30,
'player2Hp': 20
})
})
.then(res => {
return res.json()
})
.then(data => console.log(data))
.catch(error => console.log('ERROR'))
}
This is views.py in Django 👉
views.py photo
This is many POST messages in terminal cause of infinite looping 👉terminal photo
This is full screenshoot of script.js 👉 script.js photo
HTML just calls script and the rest is just blank. 👉 index.html photo
I want to post with the Fetch API and call an action from my controller but the action is not being loaded like when I would do it with submitting a post form.
function postQuery() {
let query = document.getElementById("query").value;
fetch('/actionName', {
method: 'POST',
body: query,
headers:
{
"Content-Type": "application/x-www-form-urlencoded"
}
})
.then(response => {
console.log(response);
})
.then(data => {
console.log('Success:', data);
})
}
/actionName is not being loaded, I am supposed to be directed to a different page.
When I would submit a form like that:
<form action="/actionName" method="post">
the public function actionName would be called but with fetch its not working.
When i try to see the $_POST with var_dump($_POST) inside of actionName, I am getting an empty array...I dont understand this
I see two questions here:
Why is the data not accessible to the server
Why is the brower not redirected to /actionName
Answer to #1:
Make sure the content type header matches the data you are sending, if it is raw json, you should use application/json rather then application/x-www-form-urlencoded. If you want to send a form using fetch API, you would need to either serialize to form to a URL encoded format, or use FormData, for example:
var fd = new FormData(document.getElementById('myForm'))
fetch('/actionName', {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data;'
},
body: fd
})
Answer to #2:
Submitting HTML Forms will direct the browser to the forms action, so if I submit a form to /actionName, I will end up seeing the HTML that is returned by the server for that route. Using Fetch API to submit a form is a type of AJAX, which means that it is capable of communicating with the server without needing to load a new page.
With that in mind, you have a few options:
Use a regular form so that the desired default behavior happens
Manually redirect the user somewhere after the fetch promise resolves, something like:
fetch(/*..*/).then(data => {
console.log('Success:', data);
window.location.href = '/otherPage'
})
Render the response HTML without redirecting the user, something like:
fetch(/*..*/).then(data => {
console.log('Success:', data);
data.text().then(rawHTML => {
document.body.parentElement.innerHTML = rawHTML
})
})
My personal intuition would be to go with the first option, as it suits your requirements and is the simplest.
I am trying to build the following and I am learning JS as I go, so I would appreciate some guidance and explanation on how to approach the following:
I have two pages, one with client-side script, that takes an uploaded image, converts it to base64 and fetches it to the second page, where the server-side script uploads it to a location via API.
This is the fetch on my first page:
fetch("xxxxxx", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
fileEnc: fileEnc,
fileName: fileName,
fileType: fileType
})
})
.then(function (res) {
console.log("Success!", res);
})
.catch(function (err) {
console.log("Error!", err);
});
};
On my second page, an API call is made and I get the following response:
console.log(uploadImage.StatusCode)
My question is:
How do I pass the response back to my first page and how do I display it?
Thanks
Second page should write the status code in the response rather than in the console. And that text will be available in the "then" part of the fetch function.
assuming that the second page was opened from the first page, write a function in the first page where you want to consume that data which is executed from the second page with the data you need as an argument:
page 1
function logData(data) {
console.log('#data from api: ', data)
}
page2
// some code here
window.opener.logData(dataFromApi)
I have an ajax post call and I want to just send the form values without waiting for a response to come. I want to redirect from my express app and not form my client side. server-side:
router.post("/", (req, res)=>{
res.status(200).send(`signup/confirm-email?v=${req.body.email}`);
// i want to be able to rediect with res.redirect("signup/confirm-email?v=${req.body.email}")
};
});
client-side:
$.post('/signup', $('#signup-form-container form').serialize())
.done(lnk=>{
window.location.replace(`${window.location}${lnk}`); })
.fail(function(xhr){ //handle errors };
The code above works, it sends a response to ajax and then i redirect from client side.
I want to redirect from server-side.
I tried to redirect from my express app using res.redirect() but it doesn't work without logging any errors to the console and in the network tab in the dev tool, it shows that the request type is xhr. If there isn't a solution to this problem, than is there a way to hide the query in the route recieved. I don't want v=${req.body.email} to be displayed in the url bar. Thank you in advance.
The point of Ajax is that the request is made by JavaScript and the response is handled by JavaScript.
If you return a redirect response, then JavaScript will follow the redirect, make a new request, and handle the response to that.
If you don't want to handle the response with JavaScript: Don't use Ajax. Use a regular form submission instead.
Avoid using jQuery, it will almost always lead to bad practices and unmaintainable code.
You should use plain Javascript or React if you need a framework (which is mainly if you need to work on a big project, but may not be suited for total JS beginner). My solution here is in plain Javascript.
As a replacement for the jQuery request util ($.post(), etc ...), browsers have a very good HTTP request API named fetch (MDN). I use it in this solution.
If you don't want to show the email param in the URL, you can set it in the localStorage.
You cannot redirect directly from Express for a POST method. Only if you were trying to GET a page, Express could redirect to another GET (and so change the URL in your browser).
The only solution to your need is to use the window.location after receiving the response from your /signup endpoint.
Server-side:
router.post('/', function (req, res) {
const form = req.body.form
// your registration code here
// ...
res.json({
success: true,
email: form.email
})
})
Client-side:
signup.js
const form = {
email: document.getElementById('email').value
// add other fields you need
}
fetch('/signup', {
method: 'POST',
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify({ form })
})
.then(res => res.json())
.then(res => {
// Set the localStorage item so you can get it back
// in the JS script of /signup/confirm-email
localStorage.setItem('email', res.email)
// Redirect to the confirm email page
window.location = '/signup/confirm-email'
})
Client-side:
confirmEmail.js
const email = localStorage.getItem('email')
if (!email) window.location = '/signup'
// proceed with your code
Code for this answer
I am using Nodejs, Express, MySQL, body-parser and EJS.
What I am trying to do is, when someone press on a button, it sends a PUT request which will update the counter by 1, I am trying to send the ID of the pressed button so it can be incremented by 1.
app.put("/toolong", function(req,res){
console.log(res.status(200).json({voteNum: 5}))
}
)
The Fetch:
function upvote(click){
// when the upvote button is clicked
let idOfClicked;
console.log(event.target.attributes[1].value)
idOfClicked = event.target.attributes[1].value
fetch(`/toolong`, { method: 'PUT', data: {id:9} })
.then(res => res.json())
.then(jsonRes => {
console.log(jsonRes.voteNum) // gives 5
})
}
I am trying to send the variable idOfClicked from the Fetch to my app.put so I can do a SQL query which will use that variable.
I assume you are able to do it, the "data" key in the fetch is something I tried from seeing some examples but I wasn't able to send it through
It's a body key instead of data.
I fixed it, the problem was I didn't have "headers: new Headers({ "Content-Type": "application/json" })" in my app.put, I placed it after my "body"