Symfony - dynamically add file form field - javascript

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?

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));
}
}

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>

Set ID for input elements when creating them dynamically

How can I set an input field ID when creating them dynamically when the user clicks a button.
I have a text field and a combo box pair which will be created on click. So every time the user clicks and creates one pair, I need to assign them unique IDs so that these value pairs can be saved to an array for later retrieval.
function createattr() {
var input = document.createElement("input");
input.type = "text";
input.placeholder="Attribute name";
input.className = "attr-textfield-style";
inputval.appendChild(input);
//Display the drop down menu
var newDiv=document.createElement('div');
var html = '<select>', attrtypes = typeGenerate(), i;
for(i = 0; i < attrtypes.length; i++) {
html += "<option value='"+attrtypes[i]+"'>"+attrtypes[i]+"</option>";
}
html += '</select>';
newDiv.className="attr-combobox-style";
newDiv.innerHTML= html;
inputval.appendChild(newDiv);
}
Solved it. It was this one simple line.Just wanted to share this for future references.
input.id="attr"+attrID;
with attrID being declared as a global variable that is incremented before the function ends so that each input field is assigned a unique ID
I just added the 'attr' string to an ID so that the combobox selected along with this text field will have the same numeral (i.e. One pair-> text field id- attr3, combobox- type3. The next pair will have -> text field id- attr4, combobox- type4)
if the elements never get deleted, you could count existing elements and give ID accordingly, like:
var newId = document.getElementsByClassName('attr-combobox-style').length;
input.id = 'attr' + newId;
Or you could use timestamp, it will be absolutely unique:
input.id = 'attr' + new Date().getTime();

How to make a hidden form with a file field

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.

Getting the ID in of an ASP drop down list from client side

What I'm trying to do is get one of my drop down list to change its contents whenever the selected item in another one cahnges. I have this code in my aspx file:
function ModifyDDLItems(id1, id2)
{
var ddlcontrolShown = document.getElementById(id1);
var ddlcontrolHidden = document.getElementById(id2);
if (ddlcontrolShown.options[ddlcontrolShown.selectedIndex].value == "DD1")
{
//Get number of items of hidden ddl
var length = ddlcontrolHidden.options.length;
//Clear items of shown ddl
ddlcontrolShown.options.length = 0;
//Add itmems of hidden ddl to shown ddl
for (i = 0; i < length; i++)
{
ddlcontrolShown.options.add
var newoption = document.createElement("option")
newoption.text = ddlcontrolHidden.options[i].text;
newoption.value = ddlcontrolHidden.options[i].text.value;
}
}
}
Now, i give it the front end ID's thru this:
protected void SetDD1ConfItems(GridViewRow gvRow, DataSet BaseConfItems)
{
DataView dvConfType = new DataView(BaseConfItems.Tables[0]);
DataSet dsTemp = BaseConfItems.Clone();
DropDownList ddlConfType2 = (DropDownList)form1.FindControl("ddlConfType2");
DropDownList ddlBA = (DropDownList)gvRow.FindControl("ddlBA");
DropDownList ddlConfType = (DropDownList)gvRow.FindControl("ddlConfType");
dvConfType.RowFilter = "ref_code = 'FAX' or ref_code = 'EEX' or ref_code = 'EPD'";
dsTemp.Tables.Clear();
dsTemp.Tables.Add(dvConfType.ToTable());
ddlConfType2.DataSource = dsTemp;
ddlConfType2.DataBind();
//ddlBA.Attributes["onchange"] = "function GetDDLD(" + ddlConfType.ClientID + ", " + ddlConfType2.ClientID + ") {ModifyDDLItems(id1, id2);}";
ddlBA.Attributes.Add("onchange", "ModifyDDLItems('" + ddlConfType.ClientID + "', '" + ddlConfType2.ClientID + "')");
}
When I run it, VS keeps on telling me that id1 and id2 are both null, it seems the id's aren't passed to the client properly.
I think you have code wrongly, the first mistake i found at a glance is,
You cannot find the controls inside gridview by using
gvRow.FindControl("ddlBA");
There may be multiple rows in GridView, so you have to find your controls in each Row as all of them will have different ClientIDs. First to try to replace the below code
gvRow.Rows[RowIndex].FindControl("ControlID");
ALso, it should be written in the some kind of loop in order to find the RowIndex value of the Grid.
Describe your exact requirement in brief. So, that i can help you in writing the proper code.

Categories

Resources