I have an HTML form that I was using to send information to the nodejs backend. I then tried to implement file uploads using the same form. To do that, I had to change the enctype of the form from the default value (application/x-www-form-urlencoded) to be enctype='multipart/form-data', and I had to use multer on the backend. I also had this button:
<input type="button" value="Submit" onclick="submitRequest(this);">
which I had to change to:
<input type="submit" value="Submit" onclick="submitRequest(this);">
This worked great in the sense that I now had files uploading to the server. However, this implementation depends on the field's names in the form. The problem is that most of the fields that I have don't have names.
I was wondering if there is a way to get both files and data to send without having to give names to each field in the form? I am wondering if it would be possible to inject my own data into the result that is generated after clicking Submit and before that result is sent to the backend? If not, is there any other way?
You can use FormData to set key and value multipart/form-data, fetch() or XMLHttpRequest() to POST data to server.
<form id="form">
<select>
<option value="1">1</option>
<option value="2">2</option>
</select>
<input type="file" />
<input type="submit" value="Submit" />
</form>
function submitRequest(event) {
event.preventDefault();
var i = 0;
var inputs = form.querySelector("input[type=file], select");
var fd = new FormData();
for (let el of inputs) {
if (el.tagName === "SELECT") {
fd.append("select", el.value)
}
if (el.type === "file") {
if (el.files.length) {
for (let file of el.files) {
fd.append("file" + (i++), file);
}
}
}
}
fetch("/path/to/server", {method:"POST", body:fd})
.then(function(response) {
return response.text()
})
.then(function(res) {
console.log(res)
})
.catch(function(err) {
console.log(err)
})
}
const form = document.getElementById("form");
form.onsubmit = submitRequest;
Related
I am trying to re-populate the saved form inputs after a submit/page reload. The problem I'm running into is the input field populates the saved value (or just any string) but then resets almost immediately. What am I missing? Thanks
Flask (Server):
#app.route("/code", methods=["GET", "POST"])
def code():
value = request.form["field1"]
return render_template(
"code.html",
saved_inputs = value
)
Html:
<form action="{{ url_for('code') }}" method="post" id="form">
<label for="field1">Test Input 1 </label>
<input type"text" name="field1" id="field1">
<button type="submit" class="btn btn-primary" id="btnSubmit">Submit</button>
</form>
JS:
<script>
$("#form").on('submit', function(event){
event.preventDefault();
// convert form to JSON
var formData = new FormData(document.getElementById('form'));
var formJSON = {};
for (var entry of formData.entries())
{
formJSON[entry[0]] = entry[1];
}
result = JSON.stringify(formJSON)
console.log("results is: "+result);
// set JSON to local Storage
sessionStorage.setItem('formObject', result);
// submit form
document.getElementById("form").submit();
// decode sessionstorage object
var decodedObj = JSON.parse(sessionStorage.getItem('formObject'));
console.log("sessionStorage object: "+decodedObj);
// alert("value is: "+decodedObj["field1"]);
// alert("jinja value is: "+"{{ saved_inputs }}");
// retrieve localStorage and populate input
// this is not working as expected
document.getElementById("field1").value = "WHY ISN'T THIS SAVING??";
// document.getElementById("field1").value = '{{ saved_inputs }}';
})
</script>
I think the issue you are facing is that you are not checking when the page loads--only when the form is submitted. To load the form on page load we can use sessionStorage to check if the record exists and then load the object to the form.
$(function() {
const formObj = sessionStorage.getItem('formObject');
// Load object
if (formObj != null) {
console.log("Previous form session exists")
let decodedObj = JSON.parse(formObj);
console.log("sessionStorage object: " + decodedObj);
console.log("value is: " + decodedObj["field1"]);
// retrieve sessionStorage and populate input
console.log("Loading previous session");
document.getElementById("field1").value = decodedObj["field1"];
}
});
Proof of concept fiddle
You can try storing the values in local storage & then retrieve them whenever the page is reloaded. You have used Session Storage. See.
I have a form with a couple of inputs. I want to show the value of the inputs (including the names of the fields) in console in json format when I click the submit button.
How can I do this? I read about new FormData way, but I don't really understand how to use it (so far I've come up with this code, but it doesn't work)
//popup is my form
popup.addEventListener("submit", function (event) {
let formData = new FormData(popup);
console.log(formData);
event.preventDefault();
}, false);
If you want to get all of your data in your form (including names), and you ain't planning to use jQuery, you can try to handle the inputs by yourself based on the form:
const form = document.myForm;
form.addEventListener("submit", function(event) {
event.preventDefault(); // Always preventDefault() first
let formData = new FormData(this);
let object = {};
formData.forEach((value, key) => {
object[key] = value
});
let json = JSON.stringify(object);
console.log(json);
}, false);
<form name="myForm">
<input name="input1">
<input name="input2">
<input name="input3">
<button>Submit</button>
</form>
I wanted to submit a form post based on user input, but the url only works for previous button. How do I take it so the addr.url becomes the current URL instead of the previous click. I want to get the url before I submit the post request.
<form id="launch" ngNoForm action="{{addr?.url}}" target="user.name" method="POST">
<input type="hidden" name="process" value="1"/>
<input type="hidden" name="key" value="user.cookie"/>
<button (click)="onSubmit(userInfo)">
<img src="../../../image/clickme.png">
</button>
</form>
onSubmit(userInfo) {
console.log('post submission' + userInfo);
this.paymentService.launch(userInfo).subscribe(data => {
this.addr = data;
if (this.addr && this.addr !== undefined && this.addr.url && this.addr.url !== undefined) {
console.log ('url: ' + this.addr.url);
$('#launch').submit();
}
});
}
Here is an example of posting data to a server "the Angular way":
The form tag:
<form novalidate
(ngSubmit)="save(signupForm)">
The submit button:
<button type="submit">
Save
</button>
The save method in the component:
save(signupForm: NgForm) {
console.log(signupForm.form.value);
// Call an http service to post the form values.
this.dataService.post(signupForm.form.value).subscribe();
}
The dataService:
post(signupValues): Observable<Product> {
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
return this.http.post(this.url, signupValues, { headers: headers });
}
NOTE: This code was written without assistance from a text editor and may contain syntax errors.
I would do it the way DeborahK suggested and inside the onSubmit() function, I would combine both http requests (the one getting the url and the actual submit) with RxJS. E.g. this.httpServe.getUrl().pipe(flatMap(result=>this.httpService.submitWithUrl(result, formValued).
I have this form:
<form action="#" id="form-add">
<input type="text" name="test[]" value="hello">
<input type="text" name="test[]" value="bye">
<button type="submit"><Submit/button>
</form>
And I want, when the user submits, this information to be sent via AJAX using FormData like this:
$('form-add').submit(function (event)
{
//Prevents from submitting form
event.preventDefault();
var formData = new FormData();
var form_fields = $('#form-add').serializeArray();
$.each(form_fields, function (key, input)
{
formData.append(input.name, input.value);
});
});
The problem is when I try to check the entries inside the variable formData, it only shows the value of the first input:
console.log(formData.get('teste[]'));
//Returns
hello
How can I send this kind of inputs using FormData?
It will send all values. But if you want to check on a client you'll need to use getAll method.
const form = new FormData
form.append('a', 1)
form.append('a', 2)
console.log(form.getAll('a'))
I am checking whether the values in form has been changed before submitting for updation. All other controls inside form, if changed, are identified but
not input type=file control. Below is the sample I was trying and if you try submitting form with or without uploading file, the response is its not changed. Why this behavior with only input type=file? Why the change in input type=file is not identified?
var form_serialize = "";
$(function() {
form_serialize = $("#frmProfile").serialize();
})
$('.submit').on('click', function(e) {
e.preventDefault();
var isChanged = $("#frmProfile").serialize() == form_serialize ? false : true;
if (isChanged)
$('body').append('changed');
else
$('body').append('Not changed');
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="frmProfile">
<input type="file" />
<input type="submit" class="submit" value="Submit" />
</form>
As per the documentation of serialize()
Data from file select elements is not serialized.
Instead you can use jQuery ajaxForm plugin which support.
Or you can use FormData object , Refer these questions : Jquery/Ajax Form Submission (enctype="multipart/form-data" ). Why does 'contentType:False' cause undefined index in PHP? , Sending multipart/formdata with jQuery.ajax