How to make a hidden form with a file field - javascript

I have a dynamically generated table which is editable. On clicking any cell in the table I can change its text.
In one column there is an image displayed. When the user clicks on it I change the html for that column to <input type='file'> and trigger a click hence making the user choose a file to upload as the an icon.
In the last column of the table I have a commit button. If the user makes some changes and presses commit I have to pick up the whole row ( some text fields and one file field ) and add all the contents to a form including the file the user chose and send it to a python script to upload it to an s3 server.
My question is: How do I send this form?
I'm currently using script this but it is not working as it is only sending text as request.Files turns out empty at the python(django) script side.
function update(a) {
try {
var button = $(a);
var row = $(button.parent());
var rowcount = button.parent().parent().parent().children().index(button.parent().parent());
var filerow = '';
var formrow = new Array();
var rowkey = new Array('Topic', 'TopicDescription');
var cnt = 0;
var form = $('#dyno_form');
row.siblings().each(function () {
if ($(this).find($('input:file')).length > 0) {
$(this).find($('input:file')).appendTo($(form));
} else if ($(this).find($('img')).length == 0) {
formrow[cnt++] = '<input type="text" value="' + $(this).html() + '" name="' + rowkey[cnt - 1] + '"/>';
}
});
$(form).append(formrow[0]);
$(form).append(formrow[1]);
$(form).submit();
} catch (a) {
alert(a);
}
}
and here is the HTML:
<form id='dyno_form' action='' method="post" style="visibility:hidden">{% csrf_token %}</form>
How do I go about doing this?

When you want to upload a file the form element needs to have the correct enctype attribute and the method must be post.
<form enctype="multipart/form-data" method="post" ...
Otherwise only the values of your inputs will be uploaded.

Related

Why is my form.action different than what gets submitted by the form?

I am trying to set up a form to transfer data to my php file via forms filled out by the user. I want to create my own GET request so simplify it, but when i submit my form it is a different URL than the one i created.
I console logged my form.action and got (both fabricated data):
.../index.php?search1=987654321&search2=987654321
but the URL i got was (i inputted 987654321):
/index.php?search1=987654321
File: index.html
<form id="searchForm" action="/index.php" method="GET">
<input type="submit" value="Search" onclick="createActionGetRequest()">
<br><br>
<text id="search1Text">Social Security Number</text><input id="searchField1" type="text" name="search1"><br>
<text id="search2Text"></text>
</form>
File: helper-functions.js
function createActionGetRequest()
{
var form = document.getElementById("searchForm");
var elements = form.elements;
var values = [];
for (var i = 0; i < elements.length; i++)
{
values.push(encodeURIComponent(elements[i].name) + '=' + encodeURIComponent(elements[i].value));
}
var userForm = document.getElementById("userType");
values.push(encodeURIComponent("userType") + '=' + encodeURIComponent(userForm.value));
var searchForm = document.getElementById("searchType");
values.push(encodeURIComponent("searchType") + '=' + encodeURIComponent(searchForm.value));
// dummy test for GET request
form.action += '?' + "search1=987654321" + '&' + "search2=987654321";
console.log(form.action);
alert('pause');
form.submit();
}
When you click on a Submit button within a form, its always call form.submit() by browser. Which mean 2 calls were made, /index.php?search1=987654321 made by browser and /index.php?search1=987654321&search2=987654321 by your js code
You can add event.preventDefault() to createActionGetRequest() to prevent the browser call.
function createActionGetRequest(event)
{
event.preventDefault()
...
}
The GET method also replace the request queries with the form input values. You can add another input instead of changing form.action.
var input = document.createElement("input");
input.type = "text";
input.name = "search2";
form.appendChild(input);
And some suggestion for your code :
1.Change submit element to button type to prevent fire submit().
<input type="button" value="Search" onclick="createActionGetRequest()">
2.The values joined from input element should exclude the elements we don't need.
for (var i = 0; i < elements.length; i++)
{
if( elements[i].name.startsWith('search')) {
values.push(encodeURIComponent(elements[i].name) + '=' + encodeURIComponent(elements[i].value));
}
}

Symfony - dynamically add file form field

I'm trying to dynamically add file field to form in symfony 2 using js and PRE_SUBMIT event listener. That's what I've got:
JS:
function addFileField() {
var container = document.getElementById("files");
var new_file_field = document.createElement("input");
new_file_field.type = "file";
new_file_field.onclick = function() { addFileField(); };
new_file_field.id = "order_file" + getFileFieldsCount().toString();
new_file_field.name = "order[file" + getFileFieldsCount().toString() + "]";
container.appendChild(new_file_field);
}
Where getFileFieldsCount() simply returns how many file fields there's been created so far.
And in my listener for PRE_SUBMIT I simply have:
for ($i = 0; $i < $data['files_count']; $i++ ) {
$form->add("file$i", 'file');
}
Where files_count is a hidden field which value contains what getFileFieldsCount() returns when clicking submit button. The only problem is that form data contains only filename of the file that is supposed to be uploaded, not the file itself. I am trying to make it work for couple hours now, can someone help?

Get SPARQL query showing after submitting in Javascript

I am trying to display the result of a query after user presses submit with the value they have inputted, the query aims to grab this input and generate a result specific to the input. The query does grab the input as I have put the query code in an alert box and it displays the input from the user in the query, this alert box pops up after pressing submit of course. My code are below:
Html
<table id="results">
</table>
<form>
First name:<br>
<input id="messageInput" type="text" name="firstname"><br>
<input id="submit99" type="submit" value="Submit">
</form>
The query result should display in the table after pressing submit. Therefore table was inserted.
Script
<script type="text/javascript">
var table = $("#results");
table.on("click", "td", myFunction);
var url = "http://dbpedia.org/sparql";
$('#submit99').on('click', function (e) {
var userInput = $('#messageInput').val();
var query = [
"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>",
"PREFIX type: <http://dbpedia.org/class/yago/>",
"PREFIX prop: <http://dbpedia.org/property/>",
"SELECT ?spouse",
"WHERE {",
"?dave dbo:spouse dbr:" + userInput + ".",
"?dave rdfs:label ?spouse.",
"}",
"Limit 1"
].join(" ");
alert("this query: [" + query + "]");
var queryUrl = url + "?query=" + encodeURIComponent(query) + "&format=json";
console.log(queryUrl);
$.ajax({
dataType: "jsonp",
url: queryUrl,
success: function (data) {
console.log(data);
// get the table element
var table = $("#results");
// get the sparql variables from the 'head' of the data.
var headerVars = data.head.vars;
// using the vars, make some table headers and add them to the table;
var trHeaders = getTableHeaders(headerVars);
table.append(trHeaders);
// grab the actual results from the data.
var bindings = data.results.bindings;
// for each result, make a table row and add it to the table.
for (rowIdx in bindings) {
table.append(getTableRow(headerVars, bindings[rowIdx]));
}
}
});
function getTableRow(headerVars, rowData) {
var tr = $("<tr></tr>");
for (var i in headerVars) {
tr.append(getTableCell(headerVars[i], rowData));
}
return tr;
}
function getTableCell(fieldName, rowData) {
var td = $("<td></td>");
var fieldData = rowData[fieldName];
//alert("fieldName = ["+fieldName +"] rowData[fieldName][value] = ["+rowData[fieldName]["value"] + "]");
td.html(fieldData["value"]);
return td;
}
function getTableHeaders(headerVars) {
var trHeaders = $("<tr></tr>");
for (var i in headerVars) {
trHeaders.append($("<th>" + headerVars[i] + "</th>"));
}
return trHeaders;
}
});
</script>
As you noticed the query result should be displayed in a table after user has pressed submit that's why I put almost all the code in the submit99 button. You guys should be able to run the code by copying and pasting it to your own IDE to gain a more familiar understanding. So question is right now after submission nothing shows up besides the alertbox displaying user input.
Thanks for your time :)
So I managed to fix the issue and get the result... all I had to do was insert the form elements in the table like:
<table id="results">
<First name:
<br>
<input id="messageInput" type="text" name="firstname">
<br>
<input id="submit99" type="submit" value="Submit">
</table>
However it is very strange because when I try to input the form tags it doesn't work:S atleast it does what I want it to do now:)

append() in jquery does'nt append file second time

I have defined an input of type file and a hidden form below it,
<input type="file" name="attachment0" id="attachment0" custom-on-change="uploadfile" ng-show="attachFile" multiple/>
<form class="hidden" id="myForm" method="post" enctype="multipart/form-data" action="SupportRequest">
</form>
"custom-on-change" is an angular directive that calls the function uploadfile() after choosing files. My javascript looks as shown below
var form = $('#myForm');
var n=0;
$scope.attachFile = true;
$scope.uploadfile = function() {
if(n == 0){
var filein = $('#attachment0');
form.append(filein);
$('#attachment0').test();
}
else
{
if(n==1){
var temp = "attachment0" + '_' + n;
var file_in = $('#'+temp);
form.append(file_in);
$('#'+temp).test();}
}
};
$.fn.test = function() {
return this.each(function(){
n++;
$(this).attr('id', this.id + '_' + n);
$(this).attr('name', this.name + '_' + n);
});
};
Am trying to append files twice to the form myForm. When i choose files second time, even after appending, i see that the previously appended input with id="attachment0" is not present in myForm and the input of id="attachment0_1" is present in the form.
Here am trying to upload multiple files multiple times, that is why am dynamically changing the id of the input in test().
I want both input with id attachment0 and attachment0_1 in myForm.
Does anyone know how this can be fixed? And explain this behavior too.
Change your code from form.append(filein) to form.append($('#attachment0').clone()).
It work then. You should use .clone() method to copy elements .
.append() just moves the element from one place to another but for copying first create the copy of the element using .clone() and then append it to your form
looks like in test function you are replacing id,
$(this).attr('id', this.id + '_' + n);
Would is not be better to use ng-repeat? Something like this:
Controller:
$scope.files = [...] // list of files
$scope.uploadfile = function() {
// So stuff to get the file
$scope.files.push(filein);
};
Html:
<!-- Inside the form -->
<div ng-repeat="file in files">{{file}}</div>

It is only uploading first row's file input

I have a application which you can access here. If you open the application please click on the "Add" button a couple of times. This will add a new row into a table below. In each table row there is an AJAX file uploader.
Now the problem is that if I click on the "Upload" button in any row except the first row, then the uploading only happens in the first row so it is only uploading the first file input only.
Why is it doing this and how can I get it so that when then the user clicks the "Upload" button, the file input within that row of the "Upload" button is uploaded and not the first row being uploaded?
Below is the full code where it appends the file AJAX file uploaded in each table row:
function insertQuestion(form) {
var $tbody = $('#qandatbl > tbody');
var $tr = $("<tr class='optionAndAnswer' align='center'></tr>");
var $image = $("<td class='image'></td>");
var $fileImage = $("<form action='upload.php' method='post' enctype='multipart/form-data' target='upload_target' onsubmit='startUpload();' >" +
"<p id='f1_upload_process' align='center'>Loading...<br/><img src='Images/loader.gif' /><br/></p><p id='f1_upload_form' align='center'><br/><label>" +
"File: <input name='fileImage' type='file' class='fileImage' /></label><br/><label><input type='submit' name='submitBtn' class='sbtn' value='Upload' /></label>" +
"</p> <iframe id='upload_target' name='upload_target' src='#' style='width:0;height:0;border:0px solid #fff;'></iframe></form>");
$image.append($fileImage);
$tr.append($image);
$tbody.append($tr);
}
function startUpload(){
document.getElementById('f1_upload_process').style.visibility = 'visible';
document.getElementById('f1_upload_form').style.visibility = 'hidden';
return true;
}
function stopUpload(success){
var result = '';
if (success == 1){
result = '<span class="msg">The file was uploaded successfully!<\/span><br/><br/>';
}
else {
result = '<span class="emsg">There was an error during file upload!<\/span><br/><br/>';
}
document.getElementById('f1_upload_process').style.visibility = 'hidden';
document.getElementById('f1_upload_form').innerHTML = result + '<label>File: <input name="fileImage" type="file"/><\/label><label><input type="submit" name="submitBtn" class="sbtn" value="Upload" /><\/label>';
document.getElementById('f1_upload_form').style.visibility = 'visible';
return true;
}
UPDATE:
Current Code:
var $fileImage = $("<form action='upload.php' method='post' enctype='multipart/form-data' target='upload_target' onsubmit='startUpload(this);' >" +
"<p class='f1_upload_process' align='center'>Loading...<br/><img src='Images/loader.gif' /><br/></p><p class='f1_upload_form' align='center'><br/><label>" +
"File: <input name='fileImage' type='file' class='fileImage' /></label><br/><label><input type='submit' name='submitBtn' class='sbtn' value='Upload' /></label>" +
"</p> <iframe class='upload_target' name='upload_target' src='#' style='wclassth:0;height:0;border:0px solclass #fff;'></iframe></form>");
function stopUpload(success, source_form){
var result = '';
if (success == 1){
result = '<span class="msg">The file was uploaded successfully!<\/span><br/><br/>';
}
else {
result = '<span class="emsg">There was an error during file upload!<\/span><br/><br/>';
}
$(source_form).find('.f1_upload_process').style.visibility = 'hidden';
$(source_form).find('.f1_upload_form').innerHTML = result + '<label>File: <input name="fileImage" type="file"/><\/label><label><input type="submit" name="submitBtn" class="sbtn" value="Upload" /><\/label>';
$(source_form).find('.f1_upload_form').style.visibility = 'visible';
return true;
}
Why am I getting an error on this line below:
$(source_form).find('.f1_upload_form').style.visibility = 'visible';
Without seeing the full cose, your problem seems to be that you are working with ID's, which must be unique within one document. If several elements are using the same ID, in the best case a browser will use the first one (which it does here), in the worst case nothing will work.
When adding a new upload form, you have to give the elements in it unique ID's. You could do that simply by attaching a counting variable to window, e.g.
$(document).ready( function(){ window.formCount=0; } );
You could then add that number to the ID of the newly added form.
Apart from this, by using the this variable, you can carry a reference to the correct form through, e.g. like onsubmit='startUpload(this);' as well as function startUpload(f){...
You should then be able to access things within the form using $(f).find(...).
There are many ways to make this work and solve the issue of multiple ID's. What I would do: var $fileImage = $("<form action... In this form where it says id I would instead use class. Then as above, change the onsubmit (in the same line) by adding "this" to its brackets. Then change the function startUpload as here:
function startUpload(source_form){
$(source_form).find('.f1_upload_process').css('visibility','visible');
$(source_form).find('.f1_upload_form').css('visibility','hidden');
return true;
}
You have to do the same thing for other functions where you want to access something inside the form that is sending a file. Pass a reference to the form to the function using this in the function call's brackets, then access things inside the form as I showed above.

Categories

Resources