Updating a table structured items - c#

I am trying to make it possible for a user to accept/reject an item stating a reason in any of the items presented in a table with a PaginatedList:
#model PaginatedList<ItemViewModel>
<table>
<thead>
...
</thead>
for (int i = 0; i < Model.Count(); i++){
var item = Model.ElementAt(i);
...
<tr>
<td><input asp-for="#item.AdditionalText" type="text" /></td>
<td>
<form asp-action="AddAdditionalText" method="post" asp-route-trackID="#item.itemID" asp-route-notes="#item.AdditionalText">
<input value="Accept Item" type="submit" class="btn btn-success btn-lg">
</form>
</td>
<td>
<form asp-action="AddAdditionalText" method="post" asp-route-trackID="#item.itemID" asp-route-notes="#item.AdditionalText">
<input value="Reject Item" type="submit" class="btn btn-success btn-lg">
</form>
</td>
<tr>
...
Data is submitted to the controller and in the action, I see only the itemID being submitted and not the notes. It is null because it is out of form. I tried but it doesn't work. Could you please suggest a solution?

You should include the notes in the form which is being submitted. Keep the input element for the AdditionalText in the same form where you submit buttons are. Also keep a name attribute on your submit buttons so that you know which button is clicked, inside your http post action method
<form asp-action="AddAdditionalText" method="post" asp-route-trackID="#item.itemID">
<input asp-for="#item.AdditionalText" type="text" />
<input value="Accept Item" name="reason" type="submit" class="btn">
<input value="Reject Item" name="reason" type="submit" class="btn">
</form>
and in the action method.
public ActionResult AddAdditionalText(int trackId,string AdditionalText, string reason)
{
if (reason == "Accept Item")
{
}
else
{
}
// to do : return something
}

Related

Hidden value for each item in List (MVC)

I'm trying to make some kind of a shopping cart, so I show a list of items in a view.
I added a submit button with the value "+ Add" and a number input with the value amount for each of the items displayed.
This is my code:
VIEW:
#model MyProject.ViewModel.AddProductsViewModel
#{
Layout = null;
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<table class="table" align="left" style="padding-left:15px">
<tr>
<th>
Product
</th>
</tr>
#foreach (var item in Model.ProductsList)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Descripcion)
</td>
<td>
<input type="hidden" name="ProductId" value="#item.ProductId" />
<input type="number" id="Amount" name="Amount"
min="1" max="30" value="1">
<input type="submit" value="+ Add" class="btn btn-primary" />
</td>
</tr>
}
</table>
}
MODEL:
public class AddProductsViewModel
{
...stuff here...
public List<Products> ProductsList { get; set; }
}
I need my controller to get the productId from the item I clicked submit to, but this way I'm only getting the Id of the first item of the list.
How can I make that happen?
EDITED MY CODE FOR CONTEXT
EDIT
Thanks to everyone that responded. Your answers didn't solve the issue but I think I might have made the wrong question. I'll give a little bit of context: I'm trying to show a list of Products in a ViewModel where each has an Add to cart button and an input style number on it's side (By using a for each, as I made a List of Products, as shown in my code), and when I click the add to cart button it gives the info of that specific item to the controller.
I don't know if I was doing it wrong. Is this possible? If so, how?
The issue with my code is that no matter which add to cart button I clicked, it always gives the info of the first item on the list only.
Instead of using:
<input type="hidden" name="ProductId" value="#item.ProductId" />
Use:
#Html.HiddenFor(modelItem => item.ProductId)
Following code may help you:
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Descripcion)
</td>
<td>
#Html.HiddenFor(modelItem => item.ProductId)
<input type="number" id="Amount" name="Amount"
min="1" max="30" value="1">
<input type="submit" value="+ Add" class="btn btn-primary" />
</td>
</tr>
}
If you are trying to send all data at once you can also use the following example:
#for( int i = 0; i < Model.Count(); ++i)
{
<tr>
<td>
#Html.DisplayFor(modelItem => Model[i].Descripcion)
</td>
<td>
#Html.HiddenFor(modelItem => Model[i].ProductId)
<input type="number" id="Amount" name="Amount"
min="1" max="30" value="1">
<input type="submit" value="+ Add" class="btn btn-primary" />
</td>
</tr>
}
Where as you controller action method may look like:
[HttpPost]public ViewResult(ModelClass model)
{
...
}

asp.net core mvc form viewmodel empty on post

When I click the button to submit my form, the viewModel is not being bound. I'm not sure whether this is to do with the model property being an array.
Controller
[HttpPost]
public async Task<IActionResult> CommodityAdditionalCodes(CommodityAdditionalCodesViewModel viewModel)
{
//todo code in here which calls webservice
return View(viewModel);
}
ViewModel
public class CommodityAdditionalCodesViewModel
{
public CommodityAdditionalCodeType[] Types { get; set; }
}
View
#model Asm.Helios.ToolboxMvc.ViewModels.CommodityAdditionalCodesViewModel
#{
ViewData["Title"] = "CommodityAdditionalCodes";
}
<Section>
<button type="button" id="btnCommit">Commit Changes</button><span id="isDirtyMessage" class="warning" style="display:none">There are unsaved changes, press the commit changes button to save them</span>
</Section>
<form id="frmAdditionalCodes" name="frmAdditionalCodes" method="post" >
<table class="table header-fixed">
<thead>
<tr >
<th>Origin</th>
<th>Description</th>
<th>Valid From</th>
<th>Valid To</th>
<th>Type</th>
<th>Customs Identifier</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Types)
{
<tr>
<td>
<span>#item.Origin</span>
<input type="text" value="#item.Origin" style="display:none"/>
</td>
<td>
<span>#item.Description</span>
<input type="text" value="#item.Description" style="display:none" />
</td>
<td>
<span>#item.ValidFrom</span>
<input type="text" value="#item.ValidFrom" style="display:none" />
</td>
<td>
<span>#item.ValidTo</span>
<input type="text" value="#item.ValidTo" style="display:none" />
</td>
<td>
<span>#item.Type</span>
<input type="text" value="#item.Type" style="display:none" />
</td>
<td>
<span>#item.CustomsIdentifier</span>
<!--<input type="text" value="#item.CustomsIdentifier" style="display:none" />-->
#Html.TextBoxFor(m=>item.CustomsIdentifier, new {#style="display:none"})</td>
<td>
<button type="button" id="deleteItem">Delete</button>
<button type="button" id="editItem">Edit</button>
<button type="button" id="updateItem" style="display:none">Update</button>
<button type="button" id="cancelItem" style="display:none">Cancel</button>
</td>
</tr>
}
</tbody>
</table>
</form>
Don't use a foreach loop, instead use a classic for and index the model, for example Model.Types[index].
Also you should consider using tag helpers, it makes your Razor code much easier to read as it more closely resembles real HTML.
#for (var index = 0; index < Model.Types.Count; index++)
{
<input type="text" asp-for="Model.Types[index].Origin" />
<!-- etc... -->
}

Passing the data-id from anchor tag to html.beginform

I have table and <tbody> of this table is getting filled from the list in the model.
The list has id for each item which is getting assigned to data-id in anchor tag
<tbody>
#foreach (var item in Model.eList.ToList())
{
<tr>
<td>#item.FullName</td>
<td>#item.Title</td>
<td><a data-id="#item.Id" data-open="Event">Event</a></td>
</tr>
}
</tbody>
I have div with Id Event like this
<div id="Event" class="reveal" data-reveal>
#using (Html.BeginForm("Cancel", "Profile", new { id = data-id}, FormMethod.Post))
{
<label>confirm</label>
<input type="submit" value="Save" class="button" id="Edits" />
}
</div>
When user clicks on anchor tag it will open the div with id="Event". But how do I pass data-id for that particular record to div with id="Event", from there it will be posted to controller with action cancel.
Thank you
You can keep a hidden input element inside that form.
<div id="Event" class="reveal" data-reveal>
#using (Html.BeginForm("Cancel", "Profile"))
{
<input id="dataId" name="id" value="" type="hidden" />
<label>confirm</label>
<input type="submit" value="Save" class="button" id="Edits" />
}
</div>
and when user clicks the anchor tag, read the value from the data-id attribute of the clicked element and set it as the value of the hidden element.
$(function(){
$("[data-id]").click(function(e){
e.preventDefault();
var id=$(this).data("id");
$("#dataId").val(id);
// your existing code to open the div with form
/ /$("#Event").show();
});
});
When the user submits the form, the id value we set to the hidden input will also be submitted.
Here is a js bin sample.
You can post Id in either -
Query String as new {id = item }, or
Hidden Field as <input type="hidden" name="id" value="#item">
For example,
<tbody>
#foreach (var item in Model.eList.ToList())
{
<tr>
<td>#item.FullName</td>
<td>#item.Title</td>
<td>
#using (Html.BeginForm("Cancel", "Profile", new {id = item },
FormMethod.Post))
{
<a data-id="#item.Id" data-open="Event">Event</a>
<input type="hidden" name="id" value="#item">
<div id="Event" class="reveal" data-reveal>
<label>confirm</label>
<input type="submit" value="Save" class="button" id="Edits" />
</div>
}
</td>
</tr>
}
</tbody>

Ajax to reload entire partial MVC

I have an main overview.cshtml page that has the following code to run a partial:
<div>
Html.RenderAction("UserProjMetric", "Users", new {id = Model.Id});
</div>
Inside of that partial it looks like so:
#model RecruiterMetricsViewModel
<div>
<div>
<input type="text" id="dates start" />
<input type="text" id="dates end" />
<input type="submit" onclick="runAjax()" />
<table>
#foreach(var data in Model.Metrics)
{
<tr> <td>#data</td> </tr>
}
</table>
</div>
I want to make the onclick run some ajax that will reload the entire partial. The user has the ability to specify a date range. When they do that then click submit I want the entire partial to be reloaded.
How do I do that and is that possible?
This should do what you want. A bit more verbose than Jonesy's comment, perhaps they would accomplish the same thing. You could try replacing Html.BeginForm with Ajax.BeginForm I suppose.
// overview.cshtml
<div id="UserProjWrapper">
Html.RenderAction("UserProjMetric", "Users", new {id = Model.Id});
</div>
// UserProjMetric.cshtml
#model RecruiterMetricsViewModel
#using(Html.BeginForm("UserProjMetric","Users",null,FormMethod.Post, new {id = "UserProjForm" }))
{
<input type="text" name="startDate" class="dates start" />
<input type="text" name="endDate" class="dates end" />
<input type="submit" value="Submit"/>
<table>
#foreach(var data in Model.Metrics)
{
<tr> <td>#data</td> </tr>
}
</table>
}
<script>
$(function() {
$('#UserProjForm').submit(function(e) {
e.preventDefault();
$.post($(this).attr("action"),$(this).serialize(),function(response) {
$('#UserProjWrapper').html(response);
});
});
});
</script>

Why form not submitting with models in asp.net mvc 5 .(Another Model binding error)

In my mvc application i have a script with following code
<script type="text/javascript">
$(document).ready(function () {
var element = $('input[data-op-mode="Edit"]');
$(".form-control").attr("disabled", "disabled");
element.click(function() {
var elementValue = element.val();
if (elementValue == "Edit") {
element.val("Update");
$(".form-control").removeAttr("disabled");
return false; //blocking from submitting form
} else {
$(".form-control").attr("disabled", "disabled");
element.val("Edit");
return true;
}
});
});
</script>
The purpose this code is to toggle Edit->Update, Update->Edit. This functionality is working fine . but when submitting the form the the post method not submitting the form values to my controller (model binding not working). the html code is given below
#model AutoPosContextA.DomainModels.Customer
#{
var options = new AjaxOptions()
{
Url = Url.Action("Update", "Customer"),
LoadingElementId = "saving",
LoadingElementDuration = 1000,
OnFailure = "OnAjaxCallsFailed",
OnSuccess = "OnCustomerInsertSuccess"
};
}
#using (Ajax.BeginForm(options))
{
<ol class="breadcrumb">
<li><i class="fa fa-floppy-o"></i><input type="submit" value="Edit" class="btn-link" data-op-mode="Edit"/></li>
<li> <a data-ajax="true" data-ajax-mode="replace" data-ajax-update="#mainDiv" href="/Customer/ListCustomer"><i class="fa fa-undo"></i> Cancel</a></li>
<li> <a data-ajax="true" data-ajax-mode="replace" data-ajax-update="#mainDiv" href="/Customer/CreateCustomer"><i class="fa fa-eraser"></i> Clear</a></li>
</ol>
<div class="col-md-7">
<table class="table table-bordered table-striped" style="clear: both">
<tr>
<td><label for="CustomerName" >Customer name</label></td>
<td><input type="text" class="form-control" id="CustomerName" placeholder="Customer name" name="CustomerName" value="#Model.CustomerName"></td>
</tr>
<tr>
<td><label for="AddressLine1" >AddressLine-1</label></td>
<td><input type="text" class="form-control" id="AddressLine1" placeholder="AddressLine-1" name="AddressLine1" value="#Model.AddressLine1"></td>
</tr>
<tr>
<td><label for="AddressLine1" >AddressLine-2</label></td>
<td><input type="text" class="form-control" id="AddressLine2" placeholder="AddressLine-2" name="AddressLine2" value="#Model.AddressLine2"></td>
</tr>
<tr>
<td><label for="Mobile" >Mobile</label></td>
<td><input type="text" class="form-control" id="Mobile" placeholder="Mobile" name="Mobile" value="#Model.Mobile"></td>
</tr>
<tr>
<td><label for="CustomerKey" >Search Key(s)</label></td>
<td><input type="text" class="form-control" id="CustomerKey" placeholder="" name="CustomerKey" value="#Model.CustomerKey"></td>
</tr>
<tr>
<td><label for="Notes" >Notes</label></td>
<td><input type="text" class="form-control" id="Notes" placeholder="Notes" name="Notes" value="#Model.Notes"></td>
</tr>
</table>
<input type="hidden" value="#Model.Id" name="Id" id="Id"/>
</div>
}
The key point in my problems are
1.) If i remove the script it will work fine
2.) Here i am using strongly typed partial view
Whats wrong with my javascript?
Disabled form fields are not sent back to the server by the browser in a POST request (according to HTTP standards), so the MVC framework will not have the values to do the model binding before entering your controller.
Potential solutions
Avoid using disabled and mix some css and javascript to obtain the feeling of disabled for fields.
On form submit event make sure to enable all the fields back
Put some hidden fields in the form with the names from the controls, and update them every time a value changes.

Categories

Resources