Hi Everyone, I try to used the modal to avoid having multiple pages. but I got a problem, first, I click the view button and it will display to modal the right information; but when I click other view button instead the next data, it display the previous data.
second, after I select the view button and try to select the new shoes button (expectation must be display the new module in modal) it display the data of the previous item I select in view button:
Controller:
public ActionResult Index() //main page
{
var result = _Context.Shoeses.Include(x => x.Supply).ToList();
return View(result);
}
public ActionResult New() //create new product
{
var SupplierCategory = _Context.Suppliers.ToList();
var listOfSupplier = new ShoesViewModel
{
Supply = SupplierCategory
};
return PartialView(listOfSupplier);
}
public ActionResult Details(int id) //view selected data
{
Shoes productItem = new Shoes();
productItem = _Context.Shoeses.Find(id);
return PartialView("_Details", productItem);
}
View: Index
#model IEnumerable<ShoeInformation.Models.Shoes>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<br />
<br />
<h2>Tindahan sa Bahay ni Tatang Benjamin</h2>
<br />
<br />
//my modal
<div class="modal fade" id="myModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3 class="modal-title">Details</h3>
</div>
<div class="modal-body" id="modalBody">
Testing Only
</div>
</div>
</div>
</div>
//my modal
<p>#Html.ActionLink("New Shoes", "New", "Shoes", new { id="btn_Modal"}, new { #class = "btn btn-primary btn-lg",#data_toggle="modal" ,#data_target="#myModal"})</p>
<table class="table table-striped table-hover ">
<tr>
<th>Product ID
</th>
<th>Product Code
</th>
<th>Product Name
</th>
<th>Item Size
</th>
<th>Supplier
</th>
<th>Available Quantity
</th>
<th>Unit Price (Php)
</th>
<th>Action
</th>
</tr>
#foreach (var shoes in Model)
{
<tr class="success">
<td>
#shoes.Id
</td>
<td>
#shoes.ProductCode
</td>
<td>
#Html.ActionLink(#shoes.ProductName, "Edit", "Shoes", new { id=shoes.Id})
</td>
<td>
#shoes.ItemSize
</td>
<td>
<input type="hidden" value="#shoes.Id" id="hiddenval" />
#Html.HiddenFor(x => shoes.Id)
#Html.DisplayFor(x => shoes.Supply.SupplierName)
</td>
<td>
#shoes.ItemQty
</td>
<td>
#shoes.ItemUnitPrice
</td>
<td>
#Html.ActionLink("View", "Details", "Shoes", new { id=shoes.Id}, new { #class = "view-Modal",#data_toggle="modal" ,#data_target="#myModal"})
</td>
</tr>
}
</table>
#*Open Modal Testing*#
#section scripts
{
<script src="~/Scripts/jquery.min.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
$('#myModal').hide();
$("#btn_Modal").click(function () {
$('#myModal').modal('show');
});
$(".view-Modal").click(function () {
var productId =
$(this).closest('tr').find('#hiddenval').val();
$.ajax({
type: 'POST',
url: '/Shoes/Details',
data: { id: productId },
success: function (response)
{
$('#modalBody').html(response);
$('#myModal').modal('show');
}
});
})
$(".close").click(function ()
{
console.log("Clear All");
});
});
</script>
}
partial view: _details
#model ShoeInformation.Models.Shoes
<div>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">Details</h4>
</div>
<div class="modal-body">
<table class="tablemodel">
<tr>
<tr>
#Html.DisplayFor(x=>x.Id)
</tr>
<tr>
#Html.DisplayFor(x=>x.ProductName)
</tr>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
I try to breakpoint to see the problem but everything is working properly, however in the modal it display the same value
can someone please help me regarding to this matter
thanks in advance
Related
On loading the application, table with list of items is displayed.
On clicking the save button, i want to write the list of items to excel.
When i click the save button, in the new request send to the controller,the list is empty.I do not prefer to write the list of table items to database.
Could anyone advice me on how to do handle this?
public IActionResult SaveReport(SalesParentViewModel salesParentViewModel)
{
if(salesParentViewModel.SalesDataModelItems != null)
{
var buffer = new StringBuilder();
buffer.AppendLine("#UserCode,SalesmanName,Date,ItemCode,ItemDescription,BrandCode,BrandName,ClientCode,Client,ClientBranchCode,Description, BranchSubChannel,TransactionAmount,Quantity");
salesParentViewModel.SalesDataModelItems.ToList().ForEach(item => buffer.AppendLine
(String.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13}", item.UserCode, item.SALESMANNAME, item.DATE, item.ItemCode, item.ITEMDESCRIPTION, item.BRANDCODE, item.BRANDNAME, item.ClientCode, item.Client, item.ClientBranchCode, item.Description, item.BRANCHSUBCHANNEL, item.TrxAmount, item.QTY
)));
System.IO.File.WriteAllText("c:\\temp\\file.csv", buffer.ToString());
}
return View();
}
View is as below:
#model MyStoreReports.ViewModels.SalesParentViewModel
#{
ViewBag.Title = "Sales Report";
}
#section scripts{
<script src="~/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.js"></script>
<link rel="stylesheet"
href="http://cdn.datatables.net/1.10.2/css/jquery.dataTables.min.css">
<script type="text/javascript"
src="http://cdn.datatables.net/1.10.2/js/jquery.dataTables.min.js"></script>
<script type="text/javascript"
src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
}
<div class="container-fluid">
<div class="row">
<div class="col-sm-9">
<h1>Sales Report</h1>
</div>
</div>
<div>
<asp:Button id="btnFilter" class="btn btn-sm btn-info" runat="server" Text="Click Me!">
<i class="fa fa-filter"></i>Filter
</asp:Button>
#using (Html.BeginForm("SaveReport", "App", FormMethod.Post))
{
#Html.HiddenFor(model => model.SalesDataModelItems);
<asp:Button id="btnSave" class="btn btn-sm btn-info" onclick="location.href='#Url.Action("SaveReport","App")'" runat="server" Text="Click Me!">
<i class="fa fa-save"></i>Save
</asp:Button>
}
#*<a href="#" class="btn btn-sm btn-info">
<i class="fa fa-save"></i>Save
</a>*#
<a href="#" class="btn btn-sm btn-info">
<i class="fa fa-print"></i>Print
</a>
</div>
<div class="row">
<form method="post">
<asp:Panel id="pnlFilter" runat="server" GroupingText="This is a sample group text" HorizontalAlign="Center">
<div class="col-sm-10" style="background-color:lavenderblush;">
<div class="row">
<div class="col-sm-2">
<label asp-for="SalesViewModelInstance.StartDate">StartDate</label>
<div class="form-group">
<input asp-for="SalesViewModelInstance.StartDate" type="date" class="form-control" />
<span asp-validation-for="SalesViewModelInstance.StartDate" class="text-muted"></span>
</div>
</div>
<div class="col-sm-2">
<label asp-for="SalesViewModelInstance.EndDate">EndDate</label>
<div class="form-group">
<input asp-for="SalesViewModelInstance.EndDate" type="date" class="form-control" />
<span asp-validation-for="SalesViewModelInstance.EndDate" class="text-muted"></span>
</div>
</div>
<div class="row">
<div class="col-sm-1">
<input type="submit" value="Submit" class="btn btn-success" />
</div>
<div class="col-sm-1">
<a asp-controller="App" asp-action="Index" class="btn btn-default">Cancel</a>
</div>
</div>
</div>
</asp:Panel>
</form>
</div>
<div class="form-group">
#if (Model.SalesDataModelItems != null)
{
<div class="container" style="background-color:lavender;" >
<div class="row">
<div class="panel panel-primary">
<div class="panel-heading">
<h2>Report</h2>
</div>
<div class="VScrollTable">
<table id="myTable" class="table table-fixed table-responsive" align="left" cellspacing="0">
<thead>
<tr>
<th>UserCode</th>
<th>SalesmanName</th>
<th>Date</th>
<th>ItemCode</th>
<th>ItemDescription</th>
<th>BrandCode</th>
<th>BrandName</th>
<th>ClientCode</th>
<th>Client</th>
<th>ClientBranchCode</th>
<th>Description</th>
<th>BranchSubChannel</th>
<th>TransactionAmount</th>
<th>Quantity</th>
</tr>
</thead>
#foreach (var item in Model.SalesDataModelItems)
{
<tbody>
<tr>
<td>#item.UserCode</td>
<td>#item.SALESMANNAME</td>
<td>#item.DATE</td>
<td>#item.ItemCode</td>
<td>#item.ITEMDESCRIPTION</td>
<td>#item.BRANDCODE</td>
<td>#item.BRANDNAME</td>
<td>#item.ClientCode</td>
<td>#item.Client</td>
<td>#item.ClientBranchCode</td>
<td>#item.Description</td>
<td>#item.BRANCHSUBCHANNEL</td>
<td>#item.TrxAmount</td>
<td>#item.QTY</td>
</tr>
</tbody>
}
</table>
</div>
</div>
</div>
</div>
}
</div>
</div>
If no change is done in the model, why would you want to pass the entire model from the view to the controller?
Just pass an identifier of some sort like id, and get the data again in the controller and save it in Excel.
If you must pass the model back to the controller it can be done, but the data needs to be hidden inputs or editable input controls (text box, check box)
Your view should look similar to the following :
#model MyStoreReports.ViewModels.SalesParentViewModel
#{
ViewBag.Title = "Sales Report";
}
#section scripts{
<script src="~/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.js"></script>
<link rel="stylesheet"
href="http://cdn.datatables.net/1.10.2/css/jquery.dataTables.min.css">
<script type="text/javascript"
src="http://cdn.datatables.net/1.10.2/js/jquery.dataTables.min.js"></script>
<script type="text/javascript"
src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
}
<div class="container-fluid">
<div class="row">
<div class="col-sm-9">
<h1>Sales Report</h1>
</div>
</div>
<div>
#using (Html.BeginForm("SaveReport", "App", FormMethod.Post))
{
<input id="brnSave" type="submit" class="btn btn-sm btn-info" value="Save" />
<div class="form-group">
#if (Model.SalesDataModelItems != null)
{
<div class="container" style="background-color:lavender;">
<div class="row">
<div class="panel panel-primary">
<div class="panel-heading">
<h2>Report</h2>
</div>
<div class="VScrollTable">
<table id="myTable" class="table table-fixed table-responsive" align="left" cellspacing="0">
<thead>
<tr>
<th>UserCode</th>
<th>SalesmanName</th>
<th>Date</th>
<th>ItemCode</th>
<th>ItemDescription</th>
<th>BrandCode</th>
<th>BrandName</th>
<th>ClientCode</th>
<th>Client</th>
<th>ClientBranchCode</th>
<th>Description</th>
<th>BranchSubChannel</th>
<th>TransactionAmount</th>
<th>Quantity</th>
</tr>
</thead>
#for (int i = 0; i < Model.SalesDataModelItems.Count; i++)
{
<tbody>
<tr>
<td>#Model.SalesDataModelItems[i].UserCode</td>
<td>#Model.SalesDataModelItems[i].SalesManName</td>
<td>#Model.SalesDataModelItems[i].SaleDate</td>
<td>#Model.SalesDataModelItems[i].ItemCode</td>
<td>#Model.SalesDataModelItems[i].ItemDescription</td>
<td>#Model.SalesDataModelItems[i].BrandCode</td>
<td>#Model.SalesDataModelItems[i].BrandName</td>
<td>#Model.SalesDataModelItems[i].ClientCode</td>
<td>#Model.SalesDataModelItems[i].ClientName</td>
<td>#Model.SalesDataModelItems[i].ClientBranchCode</td>
<td>#Model.SalesDataModelItems[i].Description</td>
<td>#Model.SalesDataModelItems[i].BranchSubChannel</td>
<td>#Model.SalesDataModelItems[i].TrxAmount</td>
<td>#Model.SalesDataModelItems[i].Quantity</td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].UserCode) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].SalesManName) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].SaleDate) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].ItemCode) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].ItemDescription) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].BrandCode) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].BrandName) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].ClientCode) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].ClientName) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].ClientBranchCode) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].Description) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].BranchSubChannel) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].TrxAmount) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].Quantity) </td>
</tr>
</tbody>
}
</table>
</div>
</div>
</div>
</div>
}
</div>
}
</div>
</div>
And like Tetsuya Yamamoto pointed out, avoid mixing asp web forms controls in asp.net MVC application
EDIT (After Maria comments) :
You can add an ajax call to save the data in excel on button press :
Controller Savereport method :
public ActionResult SaveReport()
{
try
{
// Get data from DB and save it in excel
return Json("Success save report");
}
catch (Exception ex)
{
return Json("Save report failure!" + ex.Message);
}
}
View :
#model MVCWebApplication.Controllers.SalesParentViewModel
#{
ViewBag.Title = "Sales Report";
}
#section scripts{
<link rel="stylesheet"
href="http://cdn.datatables.net/1.10.2/css/jquery.dataTables.min.css">
<script type="text/javascript"
src="http://cdn.datatables.net/1.10.2/js/jquery.dataTables.min.js"></script>
<script type="text/javascript"
src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
}
<div class="container-fluid">
<div class="row">
<div class="col-sm-9">
<h1>Sales Report</h1>
</div>
</div>
<div>
<input id="btnSave" type="button" class="btn btn-sm btn-info" data-url="#Url.Action("SaveReport","App")" value="Save" />
<div class="form-group">
#if (Model.SalesDataModelItems != null)
{
<div class="container" style="background-color:lavender;">
<div class="row">
<div class="panel panel-primary">
<div class="panel-heading">
<h2>Report</h2>
</div>
<div class="VScrollTable">
<table id="myTable" class="table table-fixed table-responsive" align="left" cellspacing="0">
<thead>
<tr>
<th>UserCode</th>
<th>SalesmanName</th>
<th>Date</th>
<th>ItemCode</th>
<th>ItemDescription</th>
<th>BrandCode</th>
<th>BrandName</th>
<th>ClientCode</th>
<th>Client</th>
<th>ClientBranchCode</th>
<th>Description</th>
<th>BranchSubChannel</th>
<th>TransactionAmount</th>
<th>Quantity</th>
</tr>
</thead>
#foreach (var item in Model.SalesDataModelItems)
{
<tbody>
<tr>
<td>#item.UserCode</td>
<td>#item.SalesManName</td>
<td>#item.SaleDate</td>
<td>#item.ItemCode</td>
<td>#item.ItemDescription</td>
<td>#item.BrandCode</td>
<td>#item.BrandName</td>
<td>#item.ClientCode</td>
<td>#item.ClientName</td>
<td>#item.ClientBranchCode</td>
<td>#item.Description</td>
<td>#item.BranchSubChannel</td>
<td>#item.TrxAmount</td>
<td>#item.Quantity</td>
</tr>
</tbody>
}
</table>
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
<script>
$(function () {
$('#btnSave').on('click', function () {
$.ajax({
url: $(this).data('url'),
type: 'post',
datatype: 'json',
contentType: 'application/json; charset=utf-8',
success: function (data) {
console.log(data);
},
error: function (xhr) {
console.log(JSON.parse(xhr.responseText));
}
});
});
});
</script>
I have two controllers, both are having view.
control#1->view#1
control#2->view#2
on controller#1->view#1 I have data displayed in tabular format. in that data table, one column is hyperlink, when i click on that I want to pop up Bootstrap modal dialog. My retirement is Modal dialog should call action method of control#2 and display view#2 in modal dialog.
view#1:
#model xxx
<table id="myTable" class="table table-bordered">
<thead>
....
</thead>
<tbody>
#foreach (xx item in Model.xxx)
{
....
<td>#Html.ActionLink(item.Value.ToString(), "Display", "Controller#2", new { para1 = item.val1, para2 = item.val2}, null)</td>
}
#Html.ActionLink() is working fine it invokes Display() method of Controller#2 and eventually displays view#2. But now the requirement is view#2 should be popup modal dialog box.
FYI: both the views are using common _Layout.cshtml file.
Please help me doing this.
I've created a complete solution for you using #Ajax.ActionLink().To use Ajax.ActionLink it's very important that you add a reference to jquery.unobtrusive-ajax.min.js.In total you should have the following references in this order:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.3/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.ajax.unobtrusive/3.2.4/jquery.unobtrusive-ajax.min.js"></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var p1 = new Product { ID = 1, Description = "Product 1" };
var p2 = new Product { ID = 2, Description = "Product 2" };
return View(new List<Product> { p1, p2 });
}
public PartialViewResult GetDetails(string description)
{
return PartialView("_GetDetails", description);
}
}
_GetDetails.cshtml partial view:
<div id="myModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Modal Header</h4>
</div>
<div class="modal-body">
<h3>#Model</h3>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
Main view:
#model IEnumerable<MVC_Master_Pages.Models.Product>
#{
ViewBag.Title = "Home";
Layout = null;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.3/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.ajax.unobtrusive/3.2.4/jquery.unobtrusive-ajax.min.js"></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
<script type="text/javascript">
function Done() {
$('#myModal').modal('show');
}
</script>
<table border="1">
<thead>
<tr>
<th>ID</th>
<th>Description</th>
<th>Details</th>
</tr>
</thead>
<tbody>
#foreach (var product in Model)
{
<tr>
<td>#product.ID</td>
<td>#product.Description</td>
<td>
#Ajax.ActionLink("Details",
"GetDetails",
new { description = product.Description },
new AjaxOptions
{
UpdateTargetId = "details",
InsertionMode = InsertionMode.Replace,
OnSuccess = "Done()"
})
</td>
</tr>
}
</tbody>
</table>
<div id="details">
</div>
Output:
The second view can't be a complete view with layout. It should be a partial view and called by ajax. Check this answer to learn how to implement it.
I have a cshtml page that will be sending a list of items over to my controller. However when i click on the submit button, nothing is being passed over to my controller.
The codes below is my cshtml codes which will pass the model over to my controller.
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-group">
#if (Model.Count() != 0)
{
<input type='button' value='Save and Update' class="btn btn-primary" data-toggle="modal" data-target="#myModal" />
}
</div>
<table class="table cell-border" id="TempTable5">
<tbody>
#if (Model.Count() != 0)
{
int j = 0;
foreach (var item in Model)
{
#Html.HiddenFor(model => item.ExerciseInstruction.ExerciseInstructionID)
<tr>
<td align="center">
<div class="form-group">
#Html.DisplayFor(model => item.ExerciseInstruction.ExerciseInstructionID)
</div>
</td>
<td>
<div class="form-group">
#Html.DisplayFor(model => item.Exercise.Name)
</div>
</td>
<td>
<div class="form-group">
<iframe width="300" height="175" src=#item.ExerciseVideo.VideoURL frameborder="0" allowfullscreen></iframe>
</div>
</td>
<td align="center">
#Html.DisplayFor(model => item.Therapist.Name)
</td>
<td>
#Html.DisplayFor(model => item.ExerciseInstruction.Prescribed_Date)
</td>
<td>
No. of Reps: #item.ExerciseInstruction.Number_Of_Reps<br />
No. of Secs to hold: #item.ExerciseInstruction.Number_Of_Secs_PositionHold<br />
No. of Sets: #item.ExerciseInstruction.Number_Of_Sets_Per_Day<br />
No. of Times: #item.ExerciseInstruction.Frequency_Per_Week<br />
Remarks: #if (item.ExerciseInstruction.Remark == null || item.ExerciseInstruction.Remark.Trim() == "")
{
#:NIL
}
else
{
#item.ExerciseInstruction.Remark
}
</td>
<td align="center">
#Html.EditorFor(model => item.ExerciseInstruction.ToPerform, new { htmlAttributes = new { style = "width:23px; height:23px;" } })
</td>
<td>
#Html.ActionLink("View", "Details", new { id = Model[j].ExerciseInstruction.ExerciseInstructionID, pageFrom = "performExercises" }, new { target = "_blank" })
</td>
</tr>
j++;
}
}
</tbody>
</table>
#if (Model.Count() != 0)
{
<input type='submit' value='Save and Update' class="btn btn-primary" data-toggle="modal" data-target="#myModal" />
}
}
The controller that is working on this is as below.
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Therapist")]
public ActionResult ToPerformExercises(int? pid, List<AssignmentViewModel> avmLIst)
{
if (ModelState.IsValid)
{
foreach (var item in avmLIst)
{
ExerciseInstruction eI = db.ExerciseInstructions.SingleOrDefault(a => a.ExerciseInstructionID == item.ExerciseInstruction.ExerciseInstructionID);
eI.ToPerform = item.ExerciseInstruction.ToPerform;
db.Entry(eI).State = EntityState.Modified;
db.SaveChanges();
}
}
return RedirectToAction("ViewToPerform", "AssignExercisesViewModel", new { pid = pid });
}
This is the submit pop up box
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!— Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Confirmation</h4>
</div>
<div class="modal-body">
<p>Are you sure you want to add/remove the Ongoing Exercise(s) for the patient?</p>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-primary" value="Confirm" onclick="DisableButton(this)" />
<button type="button" class="btn btn-default" data-dismiss="modal" id="cancel">Cancel</button>
</div>
</div>
</div>
</div>
My problem is very similar to this link Jquery tool DataTable unable to post/submit in an MVC3 Html.BeginForm
However i am unsure of how he actually solve it as the explanation on his answer was really brief.
Can anyone assist?
There's a lot going on here, but I'll take a shot at it based on a common pitfall in model binding... You should change the foreach to a for loop, then alter your HtmlEditorFor calls to use the index.
So to greatly simplify what you have above...
for(int i = 0; i < model.Count; i++)
{
// other things
#Html.EditorFor(model => model[i]. //rest of stuff
// more other things
MVC serializes a name into the element for you, then attempts to re-map this server-side when posting the form. If you use a foreach loop in this way, it will lose the index and fail to bind.
You can see this effect happening if you watch your requests in Fiddler (or Chrome or whatever).
Check out this answer. They experienced a similar problem when using foreach instead of for. The model binding does not work in the former case.
Model.List is null on POST using Razor
I have the following View
#model QuotationManagement.Models.ProductViewModel
#{
ViewBag.Title = "Products";
}
<h2>Products</h2>
<button id='newProduct' data-toggle="modal" data-target="#newProductModal" class="btn btn-primary">Add New Product</button>
<br />
#using (Html.BeginForm("Products", "Main", FormMethod.Post, new { encType = "multipart/form-data", name = "myform" }))
{
<table class="table table-bordered table-condensed table-striped">
<tr>
<th>
Name
</th>
<th>
Price
</th>
<th>
Gender
</th>
<td>
Action
</td>
</tr>
#Html.EditorFor(model => model.Products)
</table>
}
<div id="newProductModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
#using (Html.BeginForm("NewProduct", "Main", FormMethod.Post, new { encType = "multipart/form-data", name = "newProdutForm", #class = "form-group" }))
{
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">New Product</h4>
</div>
<div class="modal-body">
#Html.HiddenFor(model => model.NewProduct.Id)
Name:
#Html.TextBoxFor(model => model.NewProduct.Name, new { #class = "form-control" })
Price:
#Html.TextBoxFor(model => model.NewProduct.Price, new { #class = "form-control" })
Gender:
#Html.DropDownListFor(model => model.NewProduct.ForGender, new List<SelectListItem>() { new SelectListItem() { Text = "Male", Value = "1" }, new SelectListItem() { Text = "Female", Value = "2" } }, new { #class = "form-control" })
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save changes</button>
</div>
}
</div>
</div>
</div>
And then the Template
#model QuotationManagement.Bussiness_Logic_Layer.Product
<tr>
<td>
#Html.HiddenFor(model => model.Id)
#Html.DisplayFor(model => model.Name)
</td>
<td>
#Html.DisplayFor(model => model.Price)
</td>
<td>
#Html.DisplayFor(model => model.Gender)
</td>
<td>
#Html.ActionLink("Edit", "EditProduct","Main", Model ,new { #class = "btn btn-primary"})
</td>
</tr>
Adding a new Product works, but now I want to change the edit Button to Bind the row item to the Boostrap Popup and then opens it for editing.
The current method I am trying is with the ActionLink which then takes the selected Product and binds it to ProductViewModel.NewProduct, which works but now my problem is I will need to reload the whole page and repopulate the table and then somehow open the Boostrap Modal.
So my question is
How can I Bind the Selected Product to the Modal and then show the Modal withoud having to do a postback or without having to reload the current page
I would recommend using AJAX and a single 'Edit' modal which would be cleared and repopulated when the user clicks 'edit' for each row.
Essentially, you will have a partial view which will be called via AJAX and injected onto the page, the method will have a parameter of productId.
Template
Please note the important part here is the onclick attribute of the edit button.
#model QuotationManagement.Bussiness_Logic_Layer.Product
<tr>
<td>
#Html.HiddenFor(model => model.Id)
#Html.DisplayFor(model => model.Name)
</td>
<td>
#Html.DisplayFor(model => model.Price)
</td>
<td>
#Html.DisplayFor(model => model.Gender)
</td>
<td>
Edit
</td>
</tr>
Javascript
$(function() {
$('.editModal').modal();
});
function editProduct(productId) {
$.ajax({
url: '/Product/GetProductDetailsModal/' + productId, // The method name + paramater
success: function(data) {
$('#modalWrapper').html(data); // This should be an empty div where you can inject your new html (the partial view)
}
});
}
Add the following to your top-level view
<div id="modalWrapper">
#* Inject form here *#
</div>
Partial View
Your partial view will look something like this
#model ProductModel
<div class="modal fade" id="editModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">Edit</h4>
</div>
<div class="modal-body">
<form>
<input type="text" id="ProductName" value="#Model.Name"/>
<input type="submit" />
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
C#, MVC4
I have a PartialView created for a popup data entry on a form. This is a snippet from the main form.
<input type="button" id="btnAddGroup" value="Add Group" />
<p>
<input type="submit" value="Save" />
</p>
</div>
</fieldset> }
I discovered quickly that I needed to have the line:
#Html.Partial("_Groups")
Outside the primary view so the form submit button in the partial view would accept and process.
My controller processes and sends back the data using:
return PartialView(NewModel);
I can run the debugger and see that the data is getting passed back to the PartialView but since the view sits outside the original form, it's not displaying.
My PartialView is as follows:
#model OMD.ViewModels.SearchedUser
#if (Model.AddGroups != null)
{
<h2>Groups to be Added</h2>
<table id="AddGroupList">
<thead>
<tr>
<th>
Name
</th>
<th>
Until
</th>
<th>
Action
</th>
</tr>
</thead>
<tbody>
#foreach (var Group in Model.AddGroups)
{
<tr>
<td>
#Html.DisplayFor(model=> Group.GroupName)
</td>
<td>
#Html.DisplayFor(model=> Group.dtAddedTo)
</td>
<td>
#Html.DisplayFor(model=> Group.bAddOrRemove)
</td>
<td>
#if (AuthCheck.CheckUser(new HttpContextWrapper(HttpContext.Current), oRoles.StaffChangeRequest) ||
AuthCheck.CheckUser(new HttpContextWrapper(HttpContext.Current), oRoles.StudentChangeRequest))
{
<span>#Html.ActionLink("Remove", "RemoveGroup", new { id = Group.ID })</span>
}
</td>
</tr>
}
</tbody>
</table>
}
<div id="dlgAddGroup" title="Add Group" style="display: none">
#using (Ajax.BeginForm("_Groups",new AjaxOptions { UpdateTargetId ="ID",OnSuccess="onSuccess"}))
{
#Html.DropDownListFor(model => model.AllGroups,new SelectList(Model.AllGroups, "ID","GroupName"), "Select Group to Add")
#Html.ValidationMessageFor(model => model.AllGroups)
<div class="editor-label">
#Html.CheckBox("cbxMakeGroupPermanent", true) Permanent
</div>
<div class="editor-label" id ="dlgUntil1">
Group Add Until:
</div>
<div class="editor-field" id="dlgUntil2">
#Html.TextBox("tbAddUntil",null,new { maxlength = 30, style = "width: 100px" })
<span style='padding:5px'><img id='calImageGroup' alt="img" src='~/Images/calendar.gif'></span>
</div>
<button class="btn btn-inverse" type="submit">add</button>
}
I can see the table at the top display the information posted back to it but it doesn't show on the screen...
How can I get this data/table to display?