JSON Post request is showing 200 success, but script is not executing - javascript

FrontEnd
this gets the name, age, city puts it in a JSON format and sends it to localhost:5100/getJson which is my backend.
<form>
<div class="form-group">
<label for="text">Name:</label>
<input type="text" class="form-control" id="name" placeholder="Enter name" name="name">
</div>
<div class="form-group">
<label for="text">Age:</label>
<input type="text" class="form-control" id="age" placeholder="Age" name="age">
</div>
<div class="form-group">
<label for="text">City:</label>
<input type="text" class="form-control" id="city" placeholder="Enter city" name="city">
</div>
<button onclick = "MyFunction()" id = "submitButton" type="submit" class="btn btn-default">Submit</button>
<p id = "demo">
</p>
<script>
function MyFunction() {
var name = document.getElementById("name").value
var age = document.getElementById("age").value
var city = document.getElementById("city").value
jsonRequest = {"name":name, "age":age, "city":city}
fetch('http://localhost:5100/acceptJson', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: jsonRequest
}).then(res => res.json())
}
</script>
my backend is a flask server in python.
Backend
app = Flask(__name__)
#app.route('/acceptJson',methods=['GET', 'POST'])
def acceptJson():
jsonData = request.json
name = jsonData['name']
age = jsonData['age']
city = jsonData['city']
postToDatabase(name,age,city)
return "Succesful"
if __name__ == '__main__':
app.run(host = "localhost", port = 5100)
Now when I make the same JSON post request using software like Postman it works, returns 200 and runs the script.
but when I do it through the code, it return 200 and doesn't run the script, so it's clearly something wrong with the POST in the javascript, but I do not understand where it's wrong.

The problem seems to be related to your front-end. In the following answer, I assume your form is submitted by "MyFunction".
In this line of HTML:
<button onclick = "MyFunction()" id = "submitButton" type="submit" class="btn btn-default">Submit</button>
The button is a submit type button. When you click the button, the browser submits the form as usual. With no "action" attribute in the tag, the request is submitted to the webpage you open i.e. no request was sent to the back-end.
The solution can be found in this question: Form not submitting with JS. However, I would suggest another method to do so.
You may add "event.preventDefault();" before you call the function of handling the request or add it to the beginning of the function to stop the form from being submitted automatically in a traditional way.
<button onclick = "event.preventDefault();MyFunction()" id = "submitButton" type="submit" class="btn btn-default">Submit</button>
The reason why to use preventDefault is that it only stop the browser default behavior while other solution (return false) stop the event propagating the DOM.

Related

custom error message shows and disappears on submit

I am using flask, html, css and javascript. So what I did was enter a error message in my login form as a new and set display: none. I validate the input credential by comparing values from a SQLite database i set previously. This validation is done inside the flask. When the form is submitted, it is validated inside the flask, however I created a javascript that changes the styling for the error message to display: block. This would show the error message for incorrect fields and the correct input users will be redirected to a new page and hence they wont see the error.
So I was hoping that the error message shows after the form is submitted for the login and the users that key in the right information will be redirected.
Flask:
#app.route('/', methods=['POST', 'GET'])
def tutor_login():
tutor_login_form = LoginAccount(request.form)
if request.method == 'POST' and tutor_login_form.validate():
session.pop('user', None)
admin_account = Admin.query.all()
tutor_account = Tutor.query.all()
for i in admin_account:
admin_id = i.admin_id_num
for j in tutor_account:
tutor_id = j.tutor_id_num
if admin_id == tutor_login_form.id_num.data:
admin_info = Admin.query.filter_by(admin_id_num=tutor_login_form.id_num.data).first()
admin_pass = admin_info.admin_password
if admin_pass == tutor_login_form.password.data:
session['user'] = tutor_login_form.id_num.data
return redirect(url_for('admin_main'))
elif tutor_id == tutor_login_form.id_num.data:
tutor_info = Tutor.query.filter_by(id_num=tutor_login_form.id_num.data).first()
tutor_pass = tutor_info.tutor_password
if tutor_pass == tutor_login_form.password.data:
session['user'] = tutor_login_form.id_num.data
return redirect(url_for('retrieve_tutor_account'))
return render_template('tutorlogin.html')
HTML:
<form class="" action="" method="POST" onsubmit="validate()">
<!-- Input fields -->
<div class="form-group mt-3">
<label for="id_num">Enter Tutor ID:</label>
<input type="text" class="form-control" id="id_num" placeholder="Enter Tutor ID" name="id_num">
</div>
<div class="form-group my-3">
<label for="password">Enter Password:</label>
<input type="password" class="form-control password" id="password" placeholder="Enter Password" name="password">
</div>
<div class="mb-3 text-center" id="error">
ID or Password entered is invalid! Please try again.
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary btn-customized">Login</button>
</div>
<div>
<p class="text-center my-3">Forgot your password? <br> Click here to reset</p>
</div>
</form>
Javascript:
<script>
var error = document.getElementById('error');
function validate(){
error.style.display = "block";
}
</script>
If you want to validate the credentials without a page reload, you need to use Ajax requests.
Where on clicking Submit, the JavaScript will first check if all fields all valid and filled and then send an Ajax request to the Flask app.
Depending on the response of the query you can either show a error message or redirect user to the page you want.
Here's a YouTube video for reference - https://www.youtube.com/watch?v=UmC26YXExJ4

How to read the user input on the client-side, modify it with JS on the client-side, and then POST it to the sever-side (Node.js)?

Problem: I want to read a user input on the client-side, do some processing on the variable using JavaScript, still on the client-side, then POST the modified variable to the server-side (Node.js).
Research: There are a few similar questions on Stackoverflow, but the answers are not the questions to my requirement. I read about Ajax and Fetch, but they focused on collecting info from the server rather than sending a JS variable from the client-side to the server. I am not sure about using WebSockets for such a simple task.
Code:
The following code is in an EJS template.
I want to POST variable name to Node.js in the following code:
<body>
<div>
<label for="name">Name: </label>
<input id = "name" type="text"> <br><br>
<label for="name">City: </label>
<input id = "city" type="text"> <br><br>
<button id="submit">Submit</button>
<button id="capitalize">Capitalize Everything</button>
<button id="clear">Clear</button>
</div>
<p>
Your name is <span id="outputName">____</span>. The city in which you live is <span id = "outputCity">____.</span>
</p>
<script>
var submit = document.getElementById("submit");
submit.onclick = () => {
var name = document.getElementById("name").value;
var city = document.getElementById("city").value;
name = "+" + name //some processing on varibale name, can be anything else
document.getElementById("outputName").innerText = name;
document.getElementById("outputCity").innerText = city;
}
</script>
<form action="/posty" method="post">
<label for="verse"></label>Search The Bible <br></label>
<input type="hidden" id ="id" name = "name" value = "name">
<button type="submit">Submit</button>
</form>
</body>
The related serverside code:
app.post('/posty', (req,res) => {
console.log(req.body.name)
})
In the following:
<input type="hidden" id ="id" name = "name" value = "name">
what is transferred to the server is the string "name" , not the content of the JS variable name. I tried to put the name between <%= %> as it was an ejs template, but it didn't work.
Problem Summary: How to read the user input on the client-side, modify it with JS on the client-side, and then POST it to the sever-side (Node.js)?
Thank you
You should use Ajax to Post data to your route (/posty).
$(document).on("click", "#submit", function () {
var name=$('#name').val()
var city =$('#city').val()
var outputName=$('#outputName').text('name')
var outputCity=$('#outputCity').text('city')
var id= $('#id').attr('id')
var obj=JSON.stringify({
name:name,
city:city,
id:id,
outputName:outputName,
outputCity:outputCity
})
$.ajax({
type: "POST",
url: "/posty",
data:obj,
contentType: "application/json",
beforeSend:function(){
//can put some spinner,before request
},
success: function (res) {
//respond from Backend
if(res){
...
}
},
});
});
//On server side
app.post("/posty", urlencodedParser, async (req, res) => {
try {
await db.query(...);
res.send(true);
}
} catch (err) {
console.log(err);
}
})
Sorry for Jquery,its easier to write..
You should specify the name attribute correctly of each input, so that you can send a HTTP POST request with the payload you want.
<body>
<form action="/posty" method="post">
<label for="name">Name: </label>
<input id="name" name="name" type="text">
<label for="city">City: </label>
<input id="city" name="city" type="text">
<button type="submit">submit</button>
</form>
</body>
If you want to modify the input value before sending the request, you can define a custom function, modify input value in it, and use the native fetch API to send it.
<body>
<script type="text/javascript">
function customSubmit() {
const name = document.getElementById('name').value + ' mock';
const city = document.getElementById('city').value + ' mock';
fetch('/posty', {
method: 'POST',
body: JSON.stringify({ name, city })
})
}
</script>
<form onsubmit="event.preventDefault(); customSubmit()">
<label for="name">Name: </label>
<input id="name" name="name" type="text">
<label for="city">City: </label>
<input id="city" name="city" type="text">
<button type="submit">submit</button>
</form>
</body>

Adding an event listener to a submit button to run a function

Hey guys I'm writing an app with javascript and I'm trying to add an event listener to the submit button which is the "Send Email" button that someone clicks to send an email.
I know the code works for adding the email since when i run it outside of an event listener, it sends the email. So there's an issue with my event listener for some reason.
Currently - nothing happens when I click the send mail button. I get no error it just returns me to the inbox.
I'm sure the event listener isn't working for some reason.
Anyone see what I'm doing wrong? Thanks
html:
<div id="compose-view">
<h3>New Email</h3>
<form id="compose-form"
method="POST">
{% csrf_token %}
<div class="form-group">
From: <input disabled class="form-control" value="{{ request.user.email }}">
</div>
<div class="form-group">
To: <input id="compose-recipients" class="form-control">
</div>
<div class="form-group">
<input class="form-control" id="compose-subject" placeholder="Subject">
</div>
<textarea class="form-control" id="compose-body" placeholder="Body"></textarea>
<input type="submit" id="sendEmail" class="btn btn-primary"/>
</form>
</div>
js:
const element = document.getElementById('sendEmail');
element.addEventListener('click', function() {
fetch('/emails', {
method: 'POST',
body: JSON.stringify({
recipients: 'card51short#gmail.com',
subject: "buglets",
body: 'Hes a fat one'
})
})
.then(response => response.json())
.then(result => {
// Print result
console.log(result);
});
});
}
Its because your form method is post which is going to make a post request when you click the button and the javascript isn't going to run because it is attempting to make a post request to an endpoint that doesn't exist. So you need to remove the html attribute method from the form.

Getting HTML form values with JavaScript and saving them into JSON key and value pairs

Objective
FrameWork used : ElectronJS
I want to take the user submitted form, and use the NodeJS script to generate a JSON file on client PC. The json file will have key and value pairs.
Please see below for expected output.
HTML
<form id="form" method="POST" action="#">
<div class="form-group col-auto">
<input type="text" class="form-control" id="username" name="username" placeholder="Enter Username" value="">
</div>
<div class="form-group col-auto">
<input type="text" class="form-control" id="account" name="account" placeholder="Enter Account" value="">
</div>
<button type="submit" id="save" class = "btn text-white mb-0"> Save </button>
</form>
JS
document.getElementById("save").addEventListener('click', saveJSON(e))
async function saveJSON(e){
e.preventDefault()
var userData = document.getElementById('username').value
var acctData = document.getElementById('account').value
var formData = userData + acctData;
console.log(formData);
await writer.jsonWriter(formData);
//Error - Uncaught TypeError: Cannot read property 'value' of undefined.
Error
Here is the error I am facing
NodeJS Script
async function jsonWriter(data){
let element = JSON.stringify(data);
fs.writeFileSync(__dirname + '\\data\\auth.json', element)
}
module.exports.jsonWriter = jsonWriter;
Required Output
// auth.json
{"username":"Stack","account":"Overflow"}
I believe there was an issue with how you were passing your event into your function and trying to call preventDefault(). I put your function directly on the event listener method with async keyword.
As previously mentioned, document.querySelector() uses CSS selectors unlike document.getElementById(). In your case I would stick with getting the input elements by their ID.
Like Paul said in his answer, you need a JavaScript object for JSON.stringify() to work properly.
document.getElementById("save").addEventListener('click', async function(e) {
e.preventDefault()
var userData = document.getElementById('username').value
var acctData = document.getElementById('account').value
var formData = {
username: userData,
account: acctData
}; // create JS object
console.log(JSON.stringify(formData));
});
<form id="form" method="POST" action="#">
<input type="text" id="username" name="username" placeholder="Enter Username">
<input type="text" id="account" name="account" placeholder="Enter Account">
<button type="submit" id="save">Save</button>
</form>
Okay I think that I can see your mistake.
In the Javascript you can change this part :
var formData = userData + acctData;
console.log(formData);
await writer.jsonWriter(formData);
To this part :
Try to assign it to a javascript object like that :
var formData = {username: userData, account: acctData};
console.log(formData);
await writer.jsonWriter(formData);
it will stringify your object and write an appropriate output.
I think.

Trying to submit html form data via xmlhttprequest

I am trying to put together a simple login prompt for a bit of in house testing and I have found myself stuck. I have the login prompt made via HTML and am trying to send it off via xmlhttprequest. Here is my JS code:
var xhr = new XMLHttpRequest();
function loginResults() {
var loginUser = document.getElementById("username").value;
var loginPass = document.getElementById("password").value;
//console.log(loginUser + loginPass);
xhr.open("post", "https://test.com/api/login/");
var loginData = "username=" + loginUser + "&password=" + loginPass
xhr.send(loginData);
//console.log(loginData);
xhr.addEventListener("readystatechange", processRequest, false);
}
function processRequest(e) {
if (xhr.readyState == 4 && xhr.status == 200) {
var response = JSON.parse(xhr.responseText);
console.log(response);
}
}
The issue is that the xhr.send completely fails using this method. However if I replace the variables sent with the plain text then everything works fine. Like this:
var loginData = "username=" + "test#test.com" + "&password=" + "test1234"
What is the difference between pulling the info via the form data and having the login hard coded like that? The request payload is exactly the same in both instances.
EDIT
Here is the gist of my HTML form:
<form name="isLogin" id="isLogin" onSubmit="loginResults()" method="post">
<div class="container">
<label for="username"><b>Email</b></label>
<input type="text" id="username" placeholder="Enter Email" name="username" required>
<label for="password"><b>Password</b></label>
<input type="password" id="password" placeholder="Enter Password" name="password" required>
<button id="submitLogin" type="submit">Login</button>
The reason the request gets cancelled is you aren't intercepting the standard form submission. When you click the Login button, Chrome fires off the AJAX request, then also submits the form. Since this leads to a page load, Chrome cancels the AJAX request.
What you need to do is prevent the default event handling. A clean way to do this is to add the submission handling in your script:
document.getElementById("isLogin").onsubmit = function(e) {
e.preventDefault();
// AJAX here
console.log("form submission intercepted");
};
<form name="isLogin" id="isLogin" method="post">
<div class="container">
<label for="username"><b>Email</b></label>
<input type="text" id="username" value="test#test.com" name="username" required>
<label for="password"><b>Password</b></label>
<input type="password" id="password" value="test1234" name="password" required>
<button id="submitLogin" type="submit">Login</button>
</div>
</form>
You need to escape values before concatenating them to the URL querystring:
var loginUser = encodeURIComponent(document.getElementById("username").value);
var loginPass = encodeURIComponent(document.getElementById("password").value);
Secondly, i wouldn't recommend passing password directly through querystring.
The secure way to pass it is preferably salted-and-hashed.

Categories