Posting very complex data structures through ASP.NET MVC - c#

The file fmOrderIn.cshtml is a view that contains a complex form:
#model MVF2.Models.FarmOrderModel
…
<form method="post">
<table>
<tr>
<td><label>Nº Encomenda</label></td>
<td><input asp-for="encID" readonly="readonly" style="background-color:lightgray;" /></td>
</tr>
<tr>
<td><label>Farmácia</label></td>
<td><input asp-for="farmDetails.cliNome" readonly="readonly" /></td>
</tr>
<tr>
<td><label>Contactos</label></td>
<td><input asp-for="farmDetails.cliTelefone[0]" readonly="readonly" /><input asp-for="farmDetails.cliTelefone[1]" readonly="readonly" /></td>
</tr>
<tr>
<td><label>Rua</label></td>
<td><input asp-for="farmDetails.locRua" readonly="readonly" /></td>
</tr>
<tr>
<td><label>Localidade</label></td>
<td><input asp-for="farmDetails.locLocalidade" readonly="readonly" /></td>
</tr>
<tr>
<td><label>Código Postal</label></td>
<td><input asp-for="farmDetails.locCodPostal" readonly="readonly" /></td>
</tr>
<tr>
<td>#Html.LabelFor(m => m.aSelVM.SelectedArm)</td>
<td>#Html.DropDownListFor(m => m.aSelVM.SelectedArm, Model.aSelVM.ArmList, "Seleccionar...")</td>
#Html.ValidationMessageFor(m => m.aSelVM.SelectedArm)
</tr>
<tr>
<td>#Html.LabelFor(m => m.aSelVM.SelectedArmLoc)</td>
<td>#Html.DropDownListFor(m => m.aSelVM.SelectedArmLoc, Model.aSelVM.ArmLocList)</td>
</tr>
#Html.Partial("_ProdPartialView", Model.pVM)
The file _ProdPartialView.cshtml is that partial view that contains:
#model MVF2.Models.ViewModels.prodTableViewModel
#foreach (var p in Model.pTable.AsEnumerable())
{
<tr>
<td>#p.Codigo</td>
<td>#p.ProdNome</td>
<td><input asp-for="#p.Data.Date" type="date" /></td>
<td><input asp-for="#p.QtdVendida" /></td>
<td><input asp-for="#p.QtdBonus" /></td>
<td>#p.QtdTotal</td>
<td><input asp-for="#p.PercDesconto" /></td>
<td><select asp-for="#p.TipoDesconto" asp-items="Html.GetEnumSelectList<DiscountEnumType>()">
</select></td>
</tr>
}
Now, I want to post all this information to the controller through a button.
I tried some <input type="submit" … /> and also a #Html.ActionLink helpers, but I didn't manage to transfer all this information.
Could you help me?
Thank you very much.

I simplified your model but you can use the same format for the rest of the properties
fmOrderIn.cshtml:
#model FarmOrderModel
<form method="post" action="#Url.Action("Method", "Home")">
<table>
<tr>
<td><label>Nº Encomenda</label></td>
<td><input asp-for="encID" readonly="readonly" style="background-color:lightgray;" /></td>
</tr>
#Html.Partial("_ProdPartialView", Model)
</table>
<input type="submit" value="Click Me" />
</form>
And the Url.Action("Method", "Home") will go to the url /Home/Method so you will need to change that to the correct action method you want to hit
_ProdPartialView.cshtml:
#model FarmOrderModel
#for (int i = 0; i < Model.pTable.Count; i++)
{
<tr>
<td>
<input asp-for="#Model.pTable[i].Codigo" />
</td>
</tr>
}

Related

Table data not posting to controller

I have the following table:
<form method="post" asp-action="Index" asp-controller="Record">
<table class="table table-hover">
<thead>
<tr>
<th scope="col"><input type="checkbox" id="chkAll"></th>
<th scope="col">Created</th>
<th scope="col">User Reference</th>
<th scope="col">Type</th>
<th scope="col">Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
#foreach (var rec in Model.Data)
{
<tr>
<td style="display: none">
#Html.TextBoxFor(m => rec.Id)
</td>
<td>
#Html.CheckBoxFor(m => rec.IsChecked)
</td>
<td>#rec.Created</td>
<td>#rec.UserReference</td>
<td>#rec.Type</td>
<td>#rec.Status</td>
<td>
<input name="submit" type="submit" id="process" value="submit" />
</td>
</tr>
}
</tbody>
</table>
</form>
The issue I have is when I press submit I'm expecting to pass the content of the table into my controller, however when I submit the form the model on my controller is null:
[HttpPost]
public async Task<IActionResult> Index(List<UserData> data)
When I submit the form I expect to have a list of id's and checkbox values either true / false, can someone shed some light into why I'm not able to see this within the post method of the controller?
Found the solution of the following thread, seems switching foreach to for resolved the issue.

How to save data from more than 3 html <input> </>

Hello I have a form with several html/input tags. Like so:
<form class="form-group">
<div class="body table-responsive">
<table class="table m-b-0">
<thead>
<tr>
<th>Name</th>
<th>age</th>
<th>phone number</th>
<th>ID</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#item.name</td>
<td>
<input type="text" name="" id="" value=""
class="bordered">
</td>
<td>
<input type="text" name="" id="" value=""
class="bordered">
</td>
<td>
<input type="text" name="" id="" value=""
class="bordered">
</td>
</tr>
}
</tbody>
</table>
</div>
</form>
I havent named or id them yet , since I know there is a way to fill all inputs and save them all at the same time when a submit or button is pressed, I just dont know how.
Do I need to add something a tag or attribute on the in order to be able to save all inputs at the same time when the is pressed?
You have to assign names to each input and add place a submit button. When you click submit, user input will be sent to the server with the given method.
<form method="post" class="form-group">
<div class="body table-responsive">
<table class="table m-b-0">
<thead>
<tr>
<th>Name</th>
<th>age</th>
<th>phone number</th>
<th>ID</th>
</tr>
</thead>
<tbody>
#{
var i = 0;
foreach (var item in Model) {
<tr>
<td>#item.name</td>
<td>
<input type="text" name="input1_#i" id="" value=""
class="bordered">
</td>
<td>
<input type="text" name="input2_#i" id="" value=""
class="bordered">
</td>
<td>
<input type="text" name="input3_#i" id="" value=""
class="bordered">
</td>
</tr>
}
}
</tbody>
</table>
</div>
<button type="submit">Submit</button>
</form>
Or you can listen to the submit event and handle it yourself.
$('form').submit(function(e) {
e.preventDefault();
// you can get the input data from 'this' (form element)
// here comes your validation and server call
});

Move a button to another tr programatically

I have a login form designed using a <table> in an ASP.NET application.
A client is asking to modify the layout by moving around a few UI controls. They want to move the Forgot Password link below the Login button so they are on separate lines.
However, for all other clients, everything needs to remain the same, so if any CSS or style changes need to be done, I would need to do it programatically. Are there any easy ways to do this?
I am trying to avoid creating duplicate user controls to fit the layout they want, and then hide/show controls, depending on the client.
<table style="TABLE-LAYOUT: fixed; WIDTH: 370px;">
<COLGROUP>
<COL width="120px">
<COL width="250px">
</COLGROUP>
<tr>
<td>Username:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td> </td>
<td>
<table>
<tr>
<td style="text-align:right;">
Forgot Password
</td>
<td>
<button type="submit">Login</button>
</td>
</tr>
</table>
</td>
</tr>
</table>
JSfiddle Demo
EDIT: jQuery NOT allowed. JavaScript OK.
Jquery can do this for you. the code might look something like this:
$("#toggle").click(toggleButtonPosition);
function toggleButtonPosition() {
var buttonRow = $("button[type=submit]").closest("tr"), buttonCell, newTR, tr;
if (buttonRow.find("td").length === 2) {
// the table is in its initial configuration. Need to extract the button cell and add it to a new row
buttonCell = buttonRow.find("button").closest("td");
buttonCell.remove();
newTR = $("<tr />").append(buttonCell);
newTR.insertBefore(buttonRow);
} else {
// Reverse the process
buttonCell = buttonRow.find("td");
tr = buttonRow.siblings().first();
tr.append(buttonCell);
buttonRow.remove();
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table style="TABLE-LAYOUT: fixed; WIDTH: 370px;">
<COLGROUP>
<COL width="120px">
<COL width="250px">
</COLGROUP>
<tr>
<td>Username:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td> </td>
<td>
<table>
<tr>
<td style="text-align:right;">
Forgot Password
</td>
<td>
<button type="submit">Login</button>
</td>
</tr>
</table>
</td>
</tr>
</table>
Toggle Button Position
You don't need to duplicate the layout. You can do it by adding/ removing the css class depending upon the client using jquery or javascript.
$(document).ready(function(){
var client1 = true; // variable to store client
if(client1){
$('button').removeClass('client2').addClass('client1');
}
else {
$('button').removeClass('client1').addClass('client2');
}});
Css classes to be added/removed from the button depending upon the client. I have put 'client1' css class on the button.
button.client1{display:block;margin:0 auto}
button.client2{float:right;margin-left:4px}
Html code as follows:
<table style="TABLE-LAYOUT: fixed; WIDTH: 370px;">
<COLGROUP>
<COL width="120px">
<COL width="250px">
</COLGROUP>
<tr>
<td>Username:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td> </td>
<td>
<table>
<tr>
<td>
<button type="submit" class='client1'>Login</button>
Forgot Password
</td>
</tr>
</table>
</td>
</tr>
You could use jQuery to archive that.
Here is an example of moving the button one step back
$(document).ready(function() {
var loginLayOut = $(".login"); // login Table
var btnTd = loginLayOut.find("button").parent(); // button container, in this case its td
var tbody = btnTd.parent().parent(); // we get the tbody by moving two step back
var tr = $("<tr></tr>"); // create a new tr
tr.append(btnTd); // append the td to the new created tr
tbody.prepend(tr); // insert the tr to the tbody at position 0
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class='login' style="TABLE-LAYOUT: fixed; WIDTH: 370px;">
<COLGROUP>
<COL width="120px">
<COL width="250px">
</COLGROUP>
<tr>
<td>Username:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td> </td>
<td>
<table>
<tr>
<td style="text-align:right;">
Forgot Password
</td>
<td>
<button type="submit">Login</button>
</td>
</tr>
</table>
</td>
</tr>
</table>

How to swap two asp.net controls in client side depend on situations?

In my project I have a page as named EduStandardCoursManager that depend on type of query string which has sent to page show different reaction.
In EduStandardCoursManager we have two controls (courseSelector,standardSelector) that If query string sent StandardID I want to StandardSelector place 1st and CourseSelector place 2nd.
Like this:
<table>
<tr>
<td>
<input type="type" name="standardSelector" placeholder="StandardSelector" value="" />
</td>
</tr>
<tr>
<td>
<input type="type" name="courseSelector" placeholder="CourseSelector" value="" />
</td>
</tr>
</table>
And if query string sent CourseID I want to CourseSelector place 1st and StandardSelector place 2nd.
Like this:
<table>
<tr>
<td>
<input type="type" name="courseSelector" placeholder="CourseSelector" value="" />
</td>
</tr>
<tr>
<td>
<input type="type" name="standardSelector" placeholder="StandardSelector" value="" />
</td>
</tr>
</table>
Is there any way to change these controls depend on query string type?
(I won't place 4 control instead)
Here you go, change your HTML to add Id to your rows
<table>
<tr id="courseSelectorRow">
<td>
Course<input type="text" name="courseSelector" placeholder="CourseSelector" value="" />
</td>
</tr>
<tr id="standardSelectorRow">
<td>
Standard<input type="text" name="standardSelector" placeholder="StandardSelector" value="" />
</td>
</tr>
</table>
And add this JavaScript snippet, you must have jQuery referenced in your page
<script>
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
var standardID = getParameterByName('StandardID');
if(standardID && standardID != '' )
{
$("#standardSelectorRow").insertBefore("#courseSelectorRow");
}
</script>
One way is to put them in a panel and show the one you want according to the QueryString value OnLoad.
<asp:Panel ID="StandardID" runat="server" Visible="false">
<table>
<tr>
<td>
<input type="type" name="standardSelector" placeholder="StandardSelector" value="" />
</td>
</tr>
<tr>
<td>
<input type="type" name="courseSelector" placeholder="CourseSelector" value="" />
</td>
</tr>
</table>
</asp:Panel>
<asp:Panel ID="CourseID" runat="server" Visible="false">
<table>
<tr>
<td>
<input type="type" name="courseSelector" placeholder="CourseSelector" value="" />
</td>
</tr>
<tr>
<td>
<input type="type" name="standardSelector" placeholder="StandardSelector" value="" />
</td>
</tr>
</table>
</asp:Panel>
And here is the code behind:
public string foobar;
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["foo"] != null)
{
foobar = Request.QueryString["foo"];
if (foobar == "CourseID")
{
StandardID.Visible = false;
CourseID.Visible = true;
}
else
{
StandardID.Visible = true;
CourseID.Visible = false;
}
}
}
Here are the results when you change the QueryString:

Remove tag from HtmlTextWriter

I am receiving text to a function public void LoadMarkup(HtmlTextWriter writer){} and I need to remove last <tr> tag from it.
The text I am getting is:
<table class="form">
<tr>
<td class="createLabel">Name:<span class="field">*</span></td><td><input type="text" maxlength="200" id="productTitle" name="productTitle" class="required" style="width: 250px;" /></td>
</tr><tr>
<td class="createLabel">Account:<span class="field">*</span></td><td><select id="recognizedAccount" name="recognizedAccount" class="required">
<option value="8a1dd4c7-8ddd-4632-aa81-6be29dc86d13">
Donation
</option><option value="5617660d-4794-4cad-aab8-a04323faf68a">
Dues Account
</option>
</select></td>
</tr><tr style="display: none;">
<td class="createLabel">Deferral Method:</td><td><select id="deferralMethod" name="deferralMethod" class="required">
<option value="e816071c-282d-46af-8c5d-ebecb8472b94">
None
</option>
</select></td>
</tr><tr>
<td class="createLabel">Description:<span class="required-field">*</span></td><td><textarea id="productDescription" name="productDescription" class="required" rows="3" style="width: 250px;"></textarea></td>
</tr><tr>
<td class="createLabel">Active:</td><td><input type="checkbox" id="productActive" name="productActive" /></td>
</tr><tr>
<td class="createLabel">Expiration Date:<span class="required-field">*</span></td><td><span class="datePicker"><input type="text" autocomplete="off" id="productExpirationDate" name="productExpirationDate" class="required" style="width: 135px;" /></span></td>
</tr><tr class="typeRates">
<td class="createLabel">Rate:<span class="required-field">*</span></td><td><input id="5a2da3f6-c3e5-4cd0-a194-7a704c8f07e0_rate" name="5a2da3f6-c3e5-4cd0-a194-7a704c8f07e0_rate" class="required" type="text" /></td>
</tr>
I need to remove this text from Upper text:
<tr class="typeRates">
<td class="createLabel">Rate:<span class="required-field">*</span></td><td><input id="5a2da3f6-c3e5-4cd0-a194-7a704c8f07e0_rate" name="5a2da3f6-c3e5-4cd0-a194-7a704c8f07e0_rate" class="required" type="text" /></td>
</tr>
I can not modify text before I am receiving it in function as this is coming from framework. Any one can help with it please suggest.
Thanks.
Not tested, nor the most robust, but perhaps give it a try:
public string RemoveLastTableRow(HtmlTextWriter writer)
{
// Create an array which contains each table row split
string[] html = writer.ToString().Split(new string[] { "<tr>" }, StringSplitOptions.None);
// Return all the array indexes joined, except for the final index
return string.Join("", html.Take(html.Count() - 1));
}

Categories

Resources