I always use the hard coded way for submitting temp table in MVC
Ex: I have to submit the following temp table after Jquery manipulating
#using (Html.BeginForm("GridSumbit", "ControllerName", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<table class="Vista" id="table1">
<thead>
<tr>
<th>
col 1
</th>
<th>
col 2
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<input type="submit" value="Submit" />
}
Jquery
function AddRow(val1,val2) {
var col1 = '<input name="col1" type="hidden" value="' + val1 + '" />';
var col2 = '<input name="col2" type="hidden" value="' + val2 + '" />';
$('#table1 tbody:last').append('<tr><td>' + col1 + '</td><td>' + val2 + '</td></tr>');
}
Controller
public ActionResult GridSumbit(List<GridRows> grid)
{
.....
Model
public class GridRows {
public string col1 {set;get;}
public string col2 {set;get;}
}
Is there an alternative way to do this ? more organized way...
For model binder to correctly map the form data to your action method parameter, which is a list of GridRow class, your form element's name attribute value should be like
[{index}].col1
where {index} is the zero based index.
So if you are adding 2 rows, your inputs should be like this
<input name="[0].col1" type="hidden" value="a" />
<input name="[0].col2" type="hidden" value="b" />
<input name="[1].col1" type="hidden" value="c" />
<input name="[1].col2" type="hidden" value="d" />
You can do this by fixing your AddRow method. Here is a simple solution where i am reading the table row length and using that to derive the index. Based upon your HTML markup/client side code, make adjustments to this. All you need is the correct name attribute value in the above format.
function AddRow(val1, val2) {
var index = $('#table1 tr').length-1;
var col1 = '<input name="[' + index+'].col1" type="text" value="' + val1 + '" />';
var col2 = '<input name="[' + index +'].col2" type="text" value="' + val2 + '" />';
$('#table1 tbody:last').append('<tr><td>' + col1 + '</td><td>' + col2 + '</td></tr>');
}
Related
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();
}
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');
});
i am increment i in this code which i am not able to parse. what is wrong with i in the code below?
#{
int i=0;
}
#foreach (var item in Model.PortServiceTariffIncluded)
{
<tr id="#("sp" + item.ServiceId)">
<td>#item.ServiceName <input type="hidden" name="QuotationDetailList[i].ServiceId" value="#item.ServiceId" /></td>
<td>#item.ServiceCriteria</td>
<td>#item.ItemBasis</td>
<td>#Html.DropDownListFor(model => model.Currency, ViewBag.CurrencyDd as SelectList) <input type ="text" id="Amount#i" name="QuotationDetailList[i].Amount" /></td>
<td><input type="hidden" value="#item.ServiceId" class="serviceslist" name="serviceslist" /><input type ="button" id="#item.ServiceId" name="btnremove" value="Remove" class="clsremove" /></td>
</tr>
i = i + 1;
}
Use the following, instead:
#foreach (var item in Model.PortServiceTariffIncluded.Select((value, i) => new { i, value })
{
<tr id="#("sp" + item.value.ServiceId)">
<td>#item.ServiceName <input type="hidden" name="QuotationDetailList[item.i].ServiceId" value="#item.value.ServiceId" /></td>
<td>#item.value.ServiceCriteria</td>
<td>#item.value.ItemBasis</td>
<td>#Html.DropDownListFor(model => model.Currency, ViewBag.CurrencyDd as SelectList) <input type ="text" id="Amount#item.i" name="QuotationDetailList[item.i].Amount" /></td>
<td><input type="hidden" value="#item.value.ServiceId" class="serviceslist" name="serviceslist" /><input type ="button" id="#item.value.ServiceId" name="btnremove" value="Remove" class="clsremove" /></td>
</tr>
}
Basically, this causes your item variable to be an object consisting of an iterator (item.i) and the actual item (item.value).
First, I would set a variable to contain your QuotationDetailList :
#{ var QuotationDetailList = Model.QuotationDetailList;}
Then, use a for here instead of a foreach :
#for (var ListIndex = 0; ListIndex < Model.PortServiceTariffIncluded.Count(); ListIndex++)
Now you can reference items using your variable and the index :
<td>#QuotationDetailList[ListIndex].ServiceName <input type="hidden" name="#QuotationDetailList[ListIndex].ServiceId" value="#QuotationDetailList[ListIndex].ServiceId" /></td>
I am currently working on some Knockout js templating stuff. My requirement is I need to set the name of a field (input) with a combination of string and the index value of the row.
For example "xxx3".
I tried two options.
'xxx' + ko.utils.arrayIndexOf(viewModel.mycollection, $data)
and
'xxx' + $index
The first option always gives '-1' for my index value and the second option doesnt work
becasue seems like I can only use the $index value without any string concatenation.
Could someone let me know if I can concatenate a string value to $index value in knockout so that I can set that to the name property of an input field.
The final result I want should be like this.
<input class="text-box single-line" data-val="true"
data-val-required="The XXX field is required." id="XXX" type="text" name="XXX3">
Here is how my template looks like.
<table id ="editorRows" class="table">
<tbody data-bind='template: {name: "rowTemplate", foreach: Rules }'></tbody>
</table>
<script id="rowTemplate" type="text/html">
<tr data-bind="attr: { id: RuleKey }">
<td>
<div class="editor-field">
<input class="text-box single-line" data-val="true" data-val-required="The Name field is required." id="Name" type="text" data-bind="value: Name, attr: {name : 'Rules[' + $index + '].Name'}" />
<span class="field-validation-valid" data-bind="attr : { 'data-valmsg-for': 'Rules[' + $index + '].Name'}" data-valmsg-replace="true"></span>
</div>
</td>
</tr>
</script>
$index is an observable, so you would need to call it to retrieve the value. So assuming you are trying to set the values of the attributes to literally Rule[0].Name, you'd do this:
<input class="text-box single-line" data-val="true" data-val-required="The Name field is required." id="Name" type="text"
data-bind="value: Name, attr: {name : 'Rules[' + $index() + '].Name'}" />
<span class="field-validation-valid" data-valmsg-replace="true"
data-bind="attr : { 'data-valmsg-for': 'Rules[' + $index() + '].Name'}"></span>
I have the following in my form
<td><input id="Notifications_0__IssueCreate" name="Notifications[0].IssueCreate" type="checkbox" value="true" /><input name="Notifications[0].IssueCreate" type="hidden" value="false" /></td>
<td><input id="Notifications_0__AllChanges" name="Notifications[0].AllChanges" type="checkbox" value="true" /><input name="Notifications[0].AllChanges" type="hidden" value="false" /></td>
In the partial view it`s wrriten as :
<%int count = 0; %>
<%foreach (var item in Model.List)
{%>
<tr>
<td><%=Html.CheckBox("Notifications[" + (count) + "].IssueCreate", item.IssueCreate)%></td>
<td><%=Html.CheckBox("Notifications[" + (count++) + "].AllChanges", item.AllChanges)%></td>
</tr>
<%}
%>
I want to submit to the controller upon each and every click on any of the checkbox. i.e, if user checks the checkbox, it sends the name of the checkbox and if selected or not to the controller, using ajax post.
How can I do that?
Here's an example function which registers a click event handler for all checkboxes and posts the name and the value of the clicked element to a controller action through AJAX:
$(function() {
$('input:checkbox').click(function() {
var $this = $(this);
$.post(
'/home/action',
{
name: $this.attr('name'),
value: $this.val()
},
function(data) {
alert('success');
}
);
});
});