Removing rows from simple table - tablesorter

I'm trying to figure out how to remove rows from a table. More specifically, rows that user might have ADDED.
Essentially my table gets data from a DB. I have a link "Add Row" that seems to work okay. It'll add a row, and add along the 'save' and 'delete' button on the row. See:
As you can see, the idea is to be able to 'cancel' this newly added row. However, I cannot find simple examples on how to do it, nor can I even seem to trigger the click() of the delete button!
My code:
$(function() {
/* <table id="tableX"> tag to specify different tables to be threated by the Tablesorter */
var $table = $('#table1');
var enabledlbl = localejs.gettext("Enabled");
var disabledlbl = localejs.gettext("Disabled");
var fieldRequiredlbl = localejs.gettext("This field is required!");
var dayslbl = localejs.gettext("days");
var monthslbl = localejs.gettext("months");
var savelbl = localejs.gettext("Save");
var deletelbl = localejs.gettext("Delete");
var accStatuslbl = localejs.gettext("Account Status");
/***************************
* main tablesorter config
***************************/
$table.tablesorter( {
theme : "bootstrap",
widthFixed: true,
/* click on column header a 3rd time to disable sorting, else need to ctrl+click */
sortReset: false,
// widget code contained in the jquery.tablesorter.widgets.js file
// use the zebra stripe widget if you plan on hiding any rows (filter widget)
// the uitheme widget is NOT REQUIRED!
// PROY: eventually also look at the Output Widget
widgets : [ "columns", "zebra"],
widgetOptions : {
// using the default zebra striping class name, so it actually isn't included in the theme variable above
// this is ONLY needed for bootstrap theming if you are using the filter widget, because rows are hidden
zebra : ["even", "odd"],
// class names added to columns (need 'columns' widget) when sorted
columns: [ "primary", "secondary", "tertiary" ]
}
});
/***************************
* Add row function
***************************/
$('.addrow').click(function() {
var row = '' +
'<tr class="newrow">' +
'<td><input type="hidden" name="id" value="0"></td>' +
'<td>'+
'<select name="isActive" id="isActive" class="form-control pl-2" aria-label="' + accStatuslbl + '" aria-describedby="isActiveReq">' +
' <option value="1" selected>' + enabledlbl + '</option>' +
' <option value="0">' + disabledlbl + '</option>' +
'</select>' +
'<div id="isActiveReq" class="pl-1 invalid-feedback">' + fieldRequiredlbl + '</div>' +
'</td>' +
'<td>' +
'<input type="text" name="days" id="days" class="form-control"' +
' placeholder="'+ dayslbl +'"' +
' aria-label="' + dayslbl + '"' +
' aria-describedby="daysReq"' +
' value=""' +
' required/>' +
'<div id="daysReq" class="pl-1 invalid-feedback">' + fieldRequiredlbl + '</div>' +
'</td>' +
'<td>' +
'<input type="text" name="months" id="months" class="form-control"' +
' placeholder="'+ monthslbl +'"' +
' aria-label="' + monthslbl + '"' +
' aria-describedby="monthsReq"' +
' value=""' +
' required/>' +
'<div id="monthsReq" class="pl-1 invalid-feedback">' + fieldRequiredlbl + '</div>' +
'</td>' +
'<td class="text-right text-nowrap">' +
' <input type="submit" name="btnSave" value="' + savelbl + '" style="font-weight: normal; font-size: 1.1em; color: red;">' +
' <input type="button" name="btnDelete" value="' + deletelbl + '" class="delrow" style="font-weight: normal; font-size: 1.1em;">' +
'</td>' +
'</tr>';
$row = $(row),
// resort table using the current sort; set to false to prevent resort, otherwise
// any other value in resort will automatically trigger the table resort.
resort = true;
$table
.find('tbody').append($row)
.trigger('addRows', [$row, resort]);
return false;
});
/***************************
* Delete row function
***************************/
$('.delrow').click(function() {
alert("delete row..");
});
});
<!doctype html>
<html lang="en">
<head>
<!-- jQuery tablesorter related -->
<link href="/css/jquery-tablesorter/theme.bootstrap_4.prestadesk.css" rel="stylesheet" type="text/css">
<script src="/js/jquery-tablesorter/jquery.tablesorter.combined.min.js"></script>
<script src="/js/prestadesk.tablesorter.onem_conditions.js"></script>
</head>
<body>
<table class="table table-striped table-md table-responsive-lg w-auto" id="table1">
<thead class="pt-2">
<th scope="col" data-priority="critical" data-label="ID" data-filter="false" class="colID">ID</th>
<th scope="col" data-priority="critical" data-sorter="false" data-filter="false" class="colStatus" data-label="STATUS" data-placeholder="" class="">STATUS</th>
<th scope="col" data-priority="critical" data-sorter="false" data-filter="false" data-label="DAYS">DAYS</th>
<th scope="col" data-priority="critical" data-sorter="false" data-filter="false" data-label="MONTHS">MONTHS</th>
<th data-priority="critical" data-sorter="false" data-filter="false" data-columnSelector="disable" data-label="SPACER" data-name="SPACER"> </th>
</thead>
<tfoot>
<tr>
<th>ID</th>
<th>STATUS</th>
<th>DAYS</th>
<th>MONTHS</th>
<th> </th>
</tr>
<tr>
<td colspan="5" class="pl-3 pt-2 pb-2" style="border-bottom-style: hidden;">
<div class="row ">
<div class="col-auto pr-2">
[ Add Row ]
</div>
<div class="col-auto pl-0 ml-0">
* save the added row before inserting new ones!
</div>
</div>
</td>
</tr>
</tfoot>
<tbody>
<tr>
<!-- ID -->
<td class="pl-3 data-rowheader">
<input type="hidden" name="id" value="1">
1
</td>
<!-- STATUS -->
<td class="text-nowrap">
<select name="isActive" id="isActive" class="form-control pl-2">
<option value="1" selected>Enabled</option>
<option value="0" >Disabled</option>
</select>
</td>
<!-- DAYS -->
<td>
<input type="text" name="days" id="days" class="form-control"
placeholder="days"
value="156"
required/>
</td>
<!-- MONTHS -->
<td>
<input type="text" name="months" id="months" class="form-control"
placeholder="months"
value="18"
required/>
</td>
<!-- FORM BUTTONS -->
<td class="text-right text-nowrap">
<input type="submit" name="btnSave" value="Save" style="font-weight: normal; font-size: 1.1em;">
<input type="button" name="btnDelete" class="delrow" value="Delete" style="font-weight: normal; font-size: 1.1em;">
</td>
</tr>
</tbody>
</table>
</body>
</html>
It seems that the $('.delrow').click(function()... gets properly called if I add the class="delrow" to the main, existing 'delete' buttons, but upon adding a row, even if the new added row button has the 'delrow' class, it doesn't go through the $('.delrow').click even at all.
That is my first problem. Second, as mentioned initially, I can't seem to find a simple example. I am not using any particular widgets here or anything. It's a simple table... Should I ?
I did came across Pager plugin - examples of how to add and remove rows. from https://mottie.github.io/tablesorter/docs/example-pager.html, however, frankly, I do now understand it. Why would I need the pager just to remove a row? And frankly it seems way overkill, no ?
If anyone can shed a light on this... Many thanks! pat

Use delegated binding on the delete button:
$table.on('click', '.delrow', function() {
$(this).closest('tr').remove();
$table.trigger('update');
});

Related

Canvas in ASP.NET Core MVC controller

How can I retrieve my image drawn in my canvas tag on my Index.cshtml page in my Home Controller?
I can currently get the from them but not the value of to insert it into a PDF later
My index.cshtml:
<form asp-action="Index">
<table>
<tr>
<th>Date</th>
<th>Société</th>
<th>Nom / Prénom</th>
<th>Signature (matin)</th>
<th>Signature (après-midi)</th>
</tr>
<tr>
<td><input asp-for="dateFormation" type="date" /></td>
<td><input asp-for="societeForme" type="text" /></td>
<td><input asp-for="nomPrenomForme" type="text" /></td>
<td><canvas id="signatureCanvas" width="200" height="100"></canvas></td>
<td><canvas id="signatureCanvas2" width="200" height="100"></canvas></td>
</tr>
</table>
#*BOUTON ENVOYER*#
<br />
<div class="myforma">
<button type="submit">Envoyer formulaire</button>
</div>
<br />
</form>
My HomeController.cs:
public async Task<IActionResult> Index([Bind("dateFormation, societeForme, nomPrenomForme")] FormulaireModel formulaireModel)
{
var renderer = new HtmlToPdf();
var pdfCreate = renderer.RenderHtmlAsPdf(formulaireModel.typeFormation + " " + formulaireModel.dureeFormation + " " + formulaireModel.animateurFormation + " " + formulaireModel.dateFormation.ToShortDateString() + " " + formulaireModel.societeForme + " " + formulaireModel.nomPrenomForme);
pdfCreate.SaveAs("liste-presence.pdf");
return View();
}

Jquery addRow and autocomplete

I have a table I would like to use autocomplete on a column.
(medSearch is the class set for this column)
I use the Jquery's autocomplete code
autocomp_opt={
source: function(request,response){
var myTable = [];
var searchStr = $(".medSearch").val();
if (searchStr.length>2)
{
alert(searchStr);
var soapEnv = "... searchStr.....";
$.ajax(
{
.............
Then I use Cloud Gen's addRow javascript.
$(document).ready(function(){
$(".addRow").btnAddRow(function(row){row.find(".medSearch").autocomplete(autocomp_opt)});
$(".delRow").btnDelRow();
$(".medSearch").autocomplete(autocomp_opt); //end autocomplete
}); //end document. ready
However, the autocomplete does not work properly with newly added row's column.
The user's input in this new row's column is not taken for the autocomplete query.
It always takes the first row's column content as the input.
I think it's because the jQuery always takes the first item which has class '.medSearch'. Then it does not take the current row's user input.
I don't know how to fix it.
Thank you for your help in advance!
My further question:
Actually, this my further question (it is too long for a comment)
I have two more columns with class identifier medCode and medDin, they need to be populated by the autocomplete result:
success: function(xml){
//alert($(xml).text());
//traverse the xml
var xmlItem = $(xml).find("*").eq(0);
//alert($(xmlItem)[0].nodeName);
var xmlMedItemArr = $(xmlItem).children().children().children();
//alert("Phyiscian Items: "+$(xmlPhyItemArr).length);
// go through each of them
$(xmlMedItemArr).each(function()
{
//do what? get each text
var childList = $(this).children();
myTable.push({
label: $(childList[0]).text() + " - " + $(childList[2]).text(),
value: $(childList[0]).text(),
din: $(childList[2]).text(),
code: $(childList[1]).text()
});
});
select: function(event,ui) {
$(".medCode").val(ui.item.code);
$(".medDin").val(ui.item.din);
},
But as the previous problem, after I select an item from the list of autocomplete result, then the two columns of all rows will be set to the same value.
How can this be done correctly?
Thank you very much for your help!
Here is the html for the table part. (we use ebase xi as the platform. It is a drag and drop web development tool. It will generate the html and some of the script automatically. You will see in the html code)
<!----><div class="CTID-1182-_ eb-1182-panel ">
<!---->Current Medications</div>
<!----><table class="CTID-1156-_ eb-1156-tableControl " summary="">
<tr>
<td>
<table class="eb-1156-tableNavRow " style="margin-top:5px;margin-bottom:5px;" summary="" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="99%">
<span class="eb-1156-tableNavRowInfo " style="padding-left:10px;">Displaying 1...1 of 1 records</span></td>
<td width="1%" align="right">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table class="eb-1156-tableContent " summary="" title="">
<colgroup>
<col style="width:20%;"><col style="width:4%;"><col style="width:4%;"><col style="width:7%;"><col style="width:7%;"><col style="width:7%;"><col style="width:7%;"><col style="width:11%;"><col style="width:11%;"></colgroup>
<tr>
<th id="CTID-1156-_-C-1164" class="eb-1156-tableColumnHeader eb-1164-tableColumnHeader ">
Medicine Name</th>
<th id="CTID-1156-_-C-1168" class="eb-1156-tableColumnHeader eb-1168-tableColumnHeader ">
Med code</th>
<th id="CTID-1156-_-C-1170" class="eb-1156-tableColumnHeader eb-1170-tableColumnHeader ">
Med drug identification number</th>
<th id="CTID-1156-_-C-1175" class="eb-1156-tableColumnHeader eb-1175-tableColumnHeader ">
Dosage</th>
<th id="CTID-1156-_-C-1177" class="eb-1156-tableColumnHeader eb-1177-tableColumnHeader ">
Unit</th>
<th id="CTID-1156-_-C-1179" class="eb-1156-tableColumnHeader eb-1179-tableColumnHeader ">
Frequency</th>
<th id="CTID-1156-_-C-1181" class="eb-1156-tableColumnHeader eb-1181-tableColumnHeader ">
Unit</th>
<th id="CTID-1156-_-C-1200" class="eb-1156-tableColumnHeader eb-1200-tableColumnHeader ">
</th>
<th id="CTID-1156-_-C-1196" class="eb-1156-tableColumnHeader eb-1196-tableColumnHeader ">
</th>
</tr>
<tr class="CTID-1156-_-R-0 eb-1156-tableRow eb-1156-tableRow ">
<td class="eb-1156-tableContentCell eb-1164-tableColumn " headers="CTID-1156-_-C-1164"><div class="eb-1164-Editor " style="display:inline-block;zoom:1;*display:inline;">
<input id="CTID-1164-_-C-0" class="CTID-1164-_-C-0 eb-1156-tableContentData eb-1164-EditorInput medSearch" type="text" name="CTRL:1164:_:C:0" size="50" maxlength="128" title="Medicine Name"></div>
</td>
<td class="eb-1156-tableContentCell eb-1168-tableColumn " headers="CTID-1156-_-C-1168"><div class="eb-1168-Editor " style="display:inline-block;zoom:1;*display:inline;">
<input id="CTID-1168-_-C-0" class="CTID-1168-_-C-0 eb-1156-tableContentData eb-1168-EditorInput medCode" type="text" name="CTRL:1168:_:C:0" size="5" maxlength="32" title="Med code"></div>
</td>
<td class="eb-1156-tableContentCell eb-1170-tableColumn " headers="CTID-1156-_-C-1170"><div class="eb-1170-Editor " style="display:inline-block;zoom:1;*display:inline;">
<input id="CTID-1170-_-C-0" class="CTID-1170-_-C-0 eb-1156-tableContentData eb-1170-EditorInput medDin" type="text" name="CTRL:1170:_:C:0" size="5" maxlength="64" title="Med drug identification number"></div>
</td>
<td class="eb-1156-tableContentCell eb-1175-tableColumn " headers="CTID-1156-_-C-1175"><div class="eb-1175-Editor " style="display:inline-block;zoom:1;*display:inline;">
<input id="CTID-1175-_-C-0" class="CTID-1175-_-C-0 eb-1156-tableContentData eb-1175-EditorInput " type="text" name="CTRL:1175:_:C:0" size="5" maxlength="10" title="Dosage"></div>
</td>
<td class="eb-1156-tableContentCell eb-1177-tableColumn " headers="CTID-1156-_-C-1177"><div class="eb-1177-Editor " style="display:inline-block;zoom:1;*display:inline;">
<select id="CTID-1177-_-C-0" class="CTID-1177-_-C-0 eb-1156-tableContentData eb-1177-EditorInput " name="CTRL:1177:_:C:0" title="Unit"><option selected="selected" value="">Please select</option><option value="109">mg</option><option value="110">ml</option></select></div>
</td>
<td class="eb-1156-tableContentCell eb-1179-tableColumn " headers="CTID-1156-_-C-1179"><div class="eb-1179-Editor " style="display:inline-block;zoom:1;*display:inline;">
<input id="CTID-1179-_-C-0" class="CTID-1179-_-C-0 eb-1156-tableContentData eb-1179-EditorInput " type="text" name="CTRL:1179:_:C:0" size="5" maxlength="64" title="Frequency"></div>
</td>
<td class="eb-1156-tableContentCell eb-1181-tableColumn " headers="CTID-1156-_-C-1181"><div class="eb-1181-Editor " style="display:inline-block;zoom:1;*display:inline;">
<select id="CTID-1181-_-C-0" class="CTID-1181-_-C-0 eb-1156-tableContentData eb-1181-EditorInput " name="CTRL:1181:_:C:0" title="Unit"><option selected="selected" value="">Please select</option><option value="112">per day</option><option value="113">per 4 hours</option></select></div>
</td>
<td class="eb-1156-tableContentCell eb-1200-tableColumn " headers="CTID-1156-_-C-1200"><input class="CTID-1200-_-C-0 eb-1200-Button addRow" type="submit" name="CTRL:1200:_:D:0" value="Add" title=""></td>
<td class="eb-1156-tableContentCell eb-1196-tableColumn " headers="CTID-1156-_-C-1196"><img class="eb-1196-Image delRow" src="shared/uohi/images/delete_icon.gif" alt="" title="">
</td>
</tr>
</table>
</td>
</tr>
</table>
Use:
var searchStr = request.term;
instead of what you currently have.
The existing code:
var searchStr = $(".medSearch").val();
Reads the value of the first element that meets the selector .medSearch
Thank you for all your help.
I have the correct value now by using the following code:
$(this).closest('tr').find(".medCode").val(ui.item.code);
$(this).closest('tr').find(".medDin").val(ui.item.din);
Thanks,
Xiaoli

MVC Html helper to make a label editable

I have a html table generated in my view, does anyone know of any helpers available that I could use so that one of the fields could be edited in-line.
View:
<table>
<caption>Configuration values for current management group</caption>
<thead>
<tr>
<th scope="col">Device Type</th>
<th scope="col">Section</th>
<th scope="col">Name</th>
<th scope="col">Value</th>
<th scope="col">Operation</th>
</tr>
</thead>
<tbody>
#foreach (var param in Model.ParamData)
{
<tr>
<td>#param.DeviceType</td>
<td>#param.Group</td>
<td>#param.Name</td>
<td>#param.Value</td>
<td>#(param.IsMerge ? "Merge" : "Delete")</td>
</tr>
}
</tbody>
</table>
As you can see there is nothing special here, I would like an edit column that would work in a similar way to a web forms gridview. The only field to be edited would be value, and it would always be a textbox.
Im sure people must have done this before but the only example Ive seen on line was for mvc 1.
I could knock something up using jquery but am sure there must be loads of examples already and dont want to re-invent the wheel.
Ive done it myself, if anyones interested:
#foreach (var param in Model.ParamData)
{
<tr>
<td>#param.DeviceType</td>
<td>#param.Group</td>
<td>#param.Name</td>
<td>
<div class="#("ViewValueDiv_" + param.ParamaterValueId)">
#param.Value
</div>
<div class="#("EditValueDiv_" + param.ParamaterValueId)" style="display:none;">
<input type="text" name="#("EditValue_" + param.ParamaterValueId)" value="#param.Value" class="#("Input_" + param.ParamaterValueId)" />
</div>
</td>
<td>#(param.IsMerge ? "Merge" : "Delete")</td>
<td>
<div class="#("EditButtonDiv_" + param.ParamaterValueId)">
<input type="button" value="Edit" class="EditButton" Id="#param.ParamaterValueId" />
</div>
<div class="#("UpdateCancelButtonDiv_" + param.ParamaterValueId)" style="display:none;">
<input type="button" value="Update" class="UpdateButton" id="#("U" + param.ParamaterValueId)" />
<input type="button" value="Cancel" class="CancelButton" id="#("C" + param.ParamaterValueId)" />
</div>
</td>
</tr>
}
$(document).ready(function () {
$(".EditButton").click(function () {
var id = $(this).attr('id');
$(".ViewValueDiv_" + id).hide();
$(".EditValueDiv_" + id).show();
$(".EditButtonDiv_" + id).hide();
$(".UpdateCancelButtonDiv_" + id).show();
oldvalue = $(".Input_" + id).val();
});
$(".CancelButton").click(function () {
var id = $(this).attr('id').substr($(this).attr('id').indexOf("C") + 1);
$(".ViewValueDiv_" + id).show();
$(".EditValueDiv_" + id).hide();
$(".EditButtonDiv_" + id).show();
$(".UpdateCancelButtonDiv_" + id).hide();
$(".Input_" + id).val(oldvalue);
});
$(".UpdateButton").click(function () {
var id = $(this).attr('id').substr($(this).attr('id').indexOf("U") + 1);
NewValue = $(".Input_" + id).val();
if (NewValue) {
$.ajax({
url: "/Terminals_configuration/UpdateConfigValue",
data: { valueId: id, newValue: NewValue },
dataType: "json",
type: "POST",
error: function () {
alert("An error occurred.");
},
success: function (data) {
$(".ViewValueDiv_" + id).show();
$(".EditValueDiv_" + id).hide();
$(".EditButtonDiv_" + id).show();
$(".UpdateCancelButtonDiv_" + id).hide();
$(".ViewValueDiv_" + id).html(NewValue);
}
});
} else {
alert("You didn't supply a new value");
}
});
});

create div dynamically on click of a hyperlink in asp.net mvc

1.I want to dynamically generate div containing textbox with unique id on click of button
<input id="<%:rid %>" type="button" value="reply"/>
2.I also want to use jquery ajax mathod to carry the textbox data to ashx file .
Can anyone help me
code
var lineItemCount = 0;
$(document).ready(function () {
$(".commentbox input[type='button']").click(function () {
var id = $(this).attr("id");
alert(id);
var cid = id.substring(5);
var containerid = "container" + cid;
alert(containerid);
//Increase the lineitemcount
lineItemCount++;
//Add a new lineitem to the container, pass the lineItemCount to makesure
getLineItem()
// can generate a unique lineItem with unique Textbox ids
$(containerid).append(getLineItem(lineItemCount));
});
});
//Create a new DIV with Textboxes
function getLineItem(number) {
var div = document.createElement('div');
//Give the div a unique id
div.setAttribute('id', 'lineitem_' + number);
//pass unique values to the getTextbox() function
var t1 = getTextbox('txt_' + number + '_1');
div.appendChild(t1);
return div;
}
//Create a textbox, make sure the id passed to this function is unique...
function getTextbox(id) {
var textbox = document.createElement('input');
textbox.setAttribute('id', id);
textbox.setAttribute('name', id);
return textbox;
}
iteration through model in aspx page
<%var i=1;%>
<%foreach (var commentitem in item.commentsModelList)
{
<table border="0" class="commentbox">
<tr>
<%var rid = "reply" + i;%>
<div id="<%:containerid %>">
<td> <input id="<%:rid %>" type="button" value="reply"/>
</div>
</td>
</tr>
</table>
<% i++;}%>
I changed your markup little bit to get the corresponding id of items on my click events
HTML
<table border="0" class="commentbox">
<tr>
<td>Some Item text
</td>
</tr>
<tr>
<td>
<div id="container-1" ></div>
<input type="button" class='btnReply' id="reply-1" value="Reply" />
</td>
</tr>
</table>
And the Script
$(function(){
$(".commentbox .btnReply").click(function(){
$(this).hide();
var id=$(this).attr("id").split("-")[1]
var strDiv="<input type='text' class='txtCmnt' id='txtReply-"+id+"' /> <input type='button' class='btnSave' value='Save' id='btnSave-"+id+"' /> ";
$("#container-"+id).html(strDiv);
});
$(".commentbox").on("click",".btnSave",function(){
var itemId=$(this).attr("id").split("-")[1]
var txt=$(this).parent().find(".txtCmnt").val();
$.post("/echo/json/", {reply: txt, id: itemId},function(data){
alert(data);
//do whatever with the response
})
});
});
Here is the jsfiddle example : http://jsfiddle.net/UGMkq/30/
You need to change the post target url to your relevant page which handles the ajax response.
EDIT : As per the comment about handing Multiple Divs
As long as you have the container div ids unique, it will work, I just changed the markup to include more than one item.
<table border="0" class="commentbox">
<tr>
<td>Some Item text<br/>
<div id="container-1" ></div>
<input type="button" class='btnReply' id="reply-1" value="Reply" />
</td>
</tr>
<tr>
<td>Some Another Content here <br/>
<div id="container-2" ></div>
<input type="button" class='btnReply' id="reply-2" value="Reply" />
</td>
</tr>
</table>
Here is the sample :http://jsfiddle.net/UGMkq/44/
For the above output to be rendered, you probably want to write your razor syntax like this
<table border="0" class="commentbox">
#foreach (var commentitem in item.commentsModelList)
{
<tr>
<td>Some Another Content here<br/>
<div id="container-#(commentitem.Id)" ></div>
<input type="button" class='btnReply' id="reply-#(commentitem.Id)" value="Reply" />
</td>
</tr>
}
</table>
Instead of creating a new table for each item, I created a new row in existing table.

ASP page not receiving POST parameters

I am writing a small application in Classic ASP. I have a page which has a form, which posts to a second page. Included with the form's POST, are file uploads, hence the need for a POST method.
The second page though is NOT seeing ANY of the fields being sent by the first page. Calling either Request("param") or Request.Form("param") both just return empty string.
If i switch the method on my form from POST to GET (with NO other changes), then the values are properly picked up by the receiving page, of course then I cannot do the file uploads, which are a crucial part of this application.
In GET mode, the parameters are all put on the url as expected. In POST mode, I fired up FireBug, and examined the POST data of my request. The originating form IS sending all the values in the request (they show up in FireBug as expected), so the problem seems to be on the receiving page's end.
The form is being submitted via code, called from the button with the onclick="javascript:saveMinutes();"
My form and the saveMinutes() function are declared as follows:
<form id="frmMinutes" enctype="multipart/form-data" method="post" action="saveminutes.asp">
<table id="tblMinutes" style="width: 100%;">
<tr>
<td>
<select id="selYear" name="year" size="13" onclick="javascript:setDatePickerRange(); checkForMinutes();">
<%For lc = Year(Now) To getMinutesFirstYear() Step - 1%>
<option value="<%=lc%>" <%If lc = Year(Now) Then%>selected="selected"<%End If%>><%=lc%></option>
<%Next%>
</select>
</td>
<td>
<select id="selMonth" name="month" size="13" onclick="javascript:setDatePickerRange(); checkForMinutes();">
<%For lc = 1 To 12%>
<option value="<%=lc%>" <%If lc = Month(Now) Then%>selected="selected"<%End If%>"><%=MonthName(lc)%></option>
<%Next%>
</select>
</td>
<td style="width: 100%; padding-left: 20px;">
<table id="enterMinutes" style="width: 100%">
<tr>
<th>Topic:</th>
<td><input id="topic" name="topic" type="text" maxlength="100" field="topic" /></td>
</tr>
<tr>
<th>Presenter:</th>
<td><input id="presenter" name="presenter" type="text" maxlength="100" field="presenter" /></td>
</tr>
<tr>
<th>Date:</th>
<td><input id="mtgdate" name="mtgdate" type="text" maxlength="10" class="datepick" field="mtgdate" readonly="readonly" /></td>
</tr>
<tr>
<th style="vertical-align: top;">Files:</th>
<td style="text-align: left;">
<input id="file0" name="file0" type="file" size="35" /><span class="redEmphasis" style="margin: 0px 10px 0px 10px;">(.doc or .docx)</span><input type="button" value="+" onclick="javascript:addFileUpload();" />
</td>
</tr>
<tr>
<th style="vertical-align: top;"></th>
<td style="text-align: left; padding: 10px 0px 10px 0px;">
<input type="button" style="width: 100%" value="update minutes" onclick="javascript:saveMinutes();" />
</td>
</tr>
</table>
<span id="warnexist" class="redEmphasis" style="display: none;">The selected month already has associated minutes (). doc files take precedence over docx.</span>
</td>
</tr>
</table>
</form>
saveMinutes():
function saveMinutes() {
if($('form#frmMinutes input[type=text]').filter(function () { return $(this).val() == '' }).length > 0) {
alert('Please enter all fields.');
return;
}
if ($('form#frmMinutes input#file0').filter(function () { return !$(this).val().match(/.*\.docx?$/i) }).length > 0) {
alert('First file must be doc or docx.');
return;
}
$('form#frmMinutes input[type=file]').filter(function () { return $(this).val() == '' }).next().remove();
$('form#frmMinutes input[type=file]').filter(function () { return $(this).val() == '' }).remove();
removeDupeFiles();
// reindex file inputs after removing emptys/dupes
var fs = $('form#frmMinutes input[type=file]:gt(0)');
for (lc = 1; lc <= fs.length; lc++) {
var fid = 'file' + new String(lc);
$(fs[lc-1]).attr('id', fid).attr('name', fid);
}
$('form#frmMinutes')[0].submit();
}
When your from is encoded as multipart, you can't get the POST values as plain old parameters. They are just additional parts of the multipart form.
To retrieve the uploaded files in ASP, you typically have to loop through the parts and check each one to see if it is a file (and then save it if it is). To get field values, you have to add to that loop to check each part to see if it has the name of one of your field values, and then retrieve the value. This is a pain to do in pure ASP code, so many people use some type of file upload component, in which case the retrieval of field values will depend on the component.
But the basic message is: whatever parsing of the form you're doing to retrieve the files, you have to do the same thing to retrieve the field values.

Resources