I need to switch two different models in one view.
For that, I created a class that contains my two "subclasses" of my models.
So far so good, my problem is in converting these classes to .ToList(), I have an error that tells me that I can not convert a List<Events> into Events (which I understand perfectly).
Except that if in my main class (EventViewModel) I change and I say that my subclasses are lists, then when I go in my view I do not parivens more to access the elements of my subclasses.
Indeed, I have for example a #Html.LabelFor(model => model._Events.) Except that there is no way to find the desired element of my object, since it represents a list.
I still specify that results is of type IEnumerable and also that I need to recover several events by request.
To do this, I used this page (Two models in one view in ASP MVC 3), especially the second answer.
Controller
[Authorize]
[HttpGet]
public async Task<ActionResult> Index()
{
ViewBag.sessionv = HttpContext.Session.GetInt32("idMember");
FileMakerRestClient client = new FileMakerRestClient(serverName, fileName, userName, password);
var toFind = new Models.EventsLines { Zkf_CTC = 1053 };
var results = await client.FindAsync(toFind);
Models.EventViewModel oEventViewModel = new Models.EventViewModel
{
_EventsLines = (from o in results select o).ToList()
};
ViewBag.JsonList = oEventViewModel;
return View(oEventViewModel);
}
[Authorize]
[HttpGet]
public async Task<ActionResult> GetEventsDetails(int Id_Event, int Id_CTC)
{
ViewBag.sessionv = HttpContext.Session.GetInt32("idMember");
FileMakerRestClient client = new FileMakerRestClient(serverName, fileName, userName, password);
var toFind = new Models.SubEventsLines { Zkp_WEB_SEL = ViewBag.sessionv, Zkf_CTC = Id_CTC, Zkf_EVL = Id_Event };
var results = await client.FindAsync(toFind);
Models.EventViewModel oEventViewModel = new Models.EventViewModel
{
_SubEventsLines = (from o in results select o).ToList()
};
Console.WriteLine(oEventViewModel);
return Json(oEventViewModel);
}
public class EventViewModel
{
public Events _Events { get; set; }
public SubEvents _SubEvents { get; set; }
}
**View**
#model jak.formulaire.Models.EventViewModel
<div class="container">
<div class="col-5" style="margin-top:2%">
<h3>Registration History</h3>
</div>
#* Table of Events member *#
<div>
<table id="example" class="table table-hover" style="width:100%; margin-top:2%">
<thead>
<tr>
<th scope="col">Event Name</th>
<th scope="col">Start Date</th>
<th scope="col">End Date</th>
<th scope="col">Status</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model._EventsLines)
{
<tr>
<td>#item.Event_Name</td>
<td>#item.Event_DateStart</td>
<td>#item.Event_DateEnd</td>
<td>#item.Event_Status</td>
<td>View Details</td>
</tr>
}
</tbody>
</table>
</div>
</div>
#* Modal Details *#
<div class="modal" role="dialog" id="myModal">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalTitle">Details : </h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div id="myModalContent">
<div class="container" style="width:auto; margin-top:1%">
<div class="row col-12">
#foreach (var item in Model._EventsLines)
{
<div class="form-horizontal col-6" style="margin-left:-5%">
#Html.HiddenFor(model => model._EventsLines.FirstOrDefault().Zkp, new { data_val = "false" })
#Html.HiddenFor(model => model._EventsLines.FirstOrDefault().Zkf_CTC, new { data_val = "false" })
<div class="form-check-inline col-12" style="margin-top:1%">
<label class="control-label col-md-5" style="font-size:13px">Start Date</label>
<input name="Event_StartDate" id="Event_StartDate" value="#item.Event_Name" class="form-control col-md-7" readonly="" />
#*#Html.EditorFor(model => model._Events.FirstOrDefault().Event_Name, new { htmlAttributes = new { #class = "form-control col-md-7", #style = "font-size:13px, height:10px", #readonly = "", #placeholder = "Date Start", #id = "Event_StartDate" } })*#
</div>
<div class="form-check-inline col-12" style="margin-top:1%">
<label class="control-label col-md-5" style="font-size:13px">End Date</label>
#Html.EditorFor(model => model._EventsLines.FirstOrDefault().Event_DateEnd, new { htmlAttributes = new { #class = "form-control col-md-7", #style = "font-size:13px, height:10px", #readonly = "", #placeholder = "Date End", #id = "Event_EndDate" } })
</div>
<div class="form-check-inline col-12" style="margin-top:1%">
<label class="control-label col-md-5" style="font-size:13px">City</label>
#Html.EditorFor(model => model._EventsLines.FirstOrDefault().Event_City, new { htmlAttributes = new { #class = "form-control col-md-7", #style = "font-size:13px, height:10px", #readonly = "", #placeholder = "City", #id = "Event_City" } })
</div>
<div class="form-check-inline col-12" style="margin-top:1%">
<label class="control-label col-md-5" style="font-size:13px">Country</label>
#Html.EditorFor(model => model._EventsLines.FirstOrDefault().Event_Country, new { htmlAttributes = new { #class = "form-control col-md-7", #style = "font-size:13px, height:10px", #readonly = "", #placeholder = "Country", #id = "Event_Country" } })
</div>
</div>
<div class="form-horizontal col-6">
<div class="form-check-inline col-12" style="margin-top:1%">
<label class="control-label col-md-5" style="font-size:13px">Type</label>
#Html.EditorFor(model => model._EventsLines.FirstOrDefault().Event_Type, new { htmlAttributes = new { #class = "form-control col-md-7", #style = "font-size:13px, height:10px", #readonly = "", #placeholder = "Type", #id = "Event_Type" } })
</div>
<div class="form-check-inline col-12" style="margin-top:1%">
<label class="control-label col-md-5" style="font-size:13px">Status</label>
#Html.EditorFor(model => model._EventsLines.FirstOrDefault().Event_Status, new { htmlAttributes = new { #class = "form-control col-md-7", #style = "font-size:13px, height:10px", #readonly = "", #placeholder = "Status", #id = "Event_Status" } })
</div>
<div class="form-check-inline col-12" style="margin-top:1%">
<label class="control-label col-md-5" style="font-size:13px">Total Due</label>
#Html.EditorFor(model => model._EventsLines.FirstOrDefault().Event_TotalDue, new { htmlAttributes = new { #class = "form-control col-md-7", #style = "font-size:13px, height:10px", #readonly = "", #placeholder = "Total Due", #id = "Event_TotalDue" } })
</div>
</div>
}
<div class="col-12">
<div class="card border-primary" style="margin-top:5%; margin-left:-4%; width:113%">
<div class="card-header"> <h6>Sub-Events</h6></div>
<div class="card-body">
<table id="SubEventsDatatables" class="display col-12">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Start Date</th>
<th scope="col">Status</th>
<th scope="col">Fees</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
#section Scripts{
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.css">
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.js"></script>
<script type="text/javascript">
// Get the modal
var modal = document.getElementById('myModal');
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks the button, open the modal
//btn.onclick = function () {
// modal.style.display = "block";
//}
// When the user clicks on <span> (x), close the modal
span.onclick = function () {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function (event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
////triggered when modal is about to be shown
//$('#myModal').on('show.bs.modal', function (e) {
// GetEventsDetails();
// //get data-id attribute of the clicked element
// var id = $(this).data('id');
// //populate the textbox
// $(e.currentTarget).find('input[name="Event_StartDate"]').val('id');
//});
//once the modal has been shown
$('#myModal').on('shown.bs.modal', function () {
//Get the datatable which has previously been initialized
var dataTable = GetEventsDetails();
//recalculate the dimensions
dataTable.columns.adjust().responsive.recalc();
//get data-id attribute of the clicked element
var id = $(this).data('id');
//populate the textbox
$(e.currentTarget).find('input[name="Event_StartDate"]').val('id');
});
$(document).ready(function () {
});
//$(function () {
// $(".myModal").click(function () {
// var my_id = $(this).data('id');
// $(".modal-body #hiddenValue").val(my_id);
// })
//});
function GetEventsDetails() {
return $('#SubEventsDatatables').DataTable({
"paging": false,
"ordering": false,
"searching": false,
"info": false,
processing: true,
ajax: {
"url": '#Url.Action("GetEventsDetails", "Events")' + "/" + 1053 + "/" + 1454,
"type": "GET",
"datatype": "json",
succes: function (data) {
$("#Name").val(data['Name_cU']);
$("#Name").val(data['Date']);
$("#Name").val(data['Status']);
$("#Name").val(data['Fee_cU']);
},
},
columns: [
{ "data": "Name_cU" },
{ "data": "Date" },
{ "data": "Status" },
{ "data": "Fee_cU" },
]
});
}
</script>
}
Based on your last comment, you would just need to change your EventViewModel to something like this (although it sounds like you've already done this):
public class EventViewModel
{
public List<Events> _Events { get; set; }
public List<SubEvents> _SubEvents { get; set; }
}
Then, in your view, you can just do something like this (but obviously using the properties of an _Events type):
<table>
<thead>
<tr>
<td>Name</td>
<td>Start Date</td>
</tr>
</thead>
<tbody>
#foreach(var item in Model._Events)
{
<tr>
<td>#item.Name</td>
<td>#item.StartDate</td>
</tr>
}
</tbody>
</table>
EDIT
I would suggest something like this then. Build the table like I showed before (updated to match your model as best I can). Use a button with the "data-" attribute that contains some identifier for that Event. Use javascript to handle the click of the button and call a method on your controller that will get the subevents for the selected event (even return a partial view). In the success function, populate the html of the modal with the subevents and display the modal. When you say "datatables", are you referring to datatables.net?
<table id="example" class="table table-hover" style="width:100%; margin-top:2%">
<thead>
<tr>
<th></th>
<th scope="col">Event Name</th>
<th scope="col">Start Date</th>
<th scope="col">End Date</th>
<th scope="col">City</th>
<th scope="col">Country</th>
<th scope="col">Type</th>
<th scope="col">Status</th>
<th scope="col">Total Due</th>
</tr>
</thead>
<tbody>
#foreach(var item in Model._Events)
{
<tr>
<td><button data-id="#item.Id">View Details</button></td>
<td>#item.Event_Name</td>
<td>#item.Event_DateStart</td>
<td>#item.Event_DateEnd</td>
<td>#item.Event_City</td>
<td>#item.Event_Country</td>
<td>#item.Event_Type</td>
<td>#item.Event_Status</td>
<td>#item.Event_TotalDue</td>
</tr>
}
</tbody>
</table>
You're probably better off posting a new question(s) to accomplish the rest of your goals. Hopefully, this will get you going in the right direction.
Related
I have a search screen which gives the results in a paged list. On changing the page I need to get the values of the Model to the GET method in the controller. While I was able to pass the model properties which are strings, I am having an issue passing the string list.
View Code :
<div class="divSearch">
<div class="divCriteria">
<div class="row">
<div class="col-md-6">
#Html.LabelFor(m => m.Name)
#Html.TextBoxFor(m => m.Name, new { #class = "form-control" })
</div>
<div class="col-md-6">
#Html.LabelFor(m => m.Owner)
#Html.TextBoxFor(m => m.Owner, new { #class = "form-control" })
</div>
</div>
<br />
<div class="row">
<div class="col-md-6">
#Html.LabelFor(m => m.County)
#Html.ListBoxFor(model => model.County, Model.CountiesList, new { #class = "form-control", multiple = "multiple" })
</div>
</div>
<br />
<div class="row">
<div class="right">
<button type="submit" class="btn btn-primary"><i class="fa fa-share-square-o"></i>Search</button>
</div>
</div>
</div>
<div class="divResults">
<div class="table-responsive">
<table class="table table-hover table-advance dataTable">
<thead>
<tr>
<th style="display:none">ID</th>
<th>Name</th>
<th>Type</th>
<th>County</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.SearchList)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
#Html.HiddenFor(modelItem => item.ID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Type)
</td>
<td>
#Html.DisplayFor(modelItem => item.County)
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
#if (Model.SearchList != null)
{
var county = new List<string>();
foreach (var item in Model.County)
{
county.Add(item);
}
#Html.PagedListPager(Model.SearchList, Page => Url.Action("Index", "FacilityFinder", new RouteValueDictionary() { { "Page", Page }, { "name", Model.Name }, { "owner", Model.Owner }, { "county", county} }),PagedListRenderOptions.PageNumbersOnly)
}
Controller code :
public ActionResult Index(int? page=null,string name = null, List<string> county=null,string owner = null)
{
}
The value for name and owner are fine in the controller, but the list of county gives me System.Collections.Generic.List`1[System.String]
Am I missing something?
You can't pass complex types such as lists. You might need to construct your RouteValueDictionary dynamically:
var query = new RouteValueDictionary
{
{ "name", Model.Name },
{ "owner", Model.Owner }
};
for (var i = 0; i < Model.County.Count; i++)
{
query["county[" + i + "]"] = Model.County[i];
}
#Html.PagedListPager(
Model.SearchList,
Page => Url.Action("Index", "FacilityFinder", new RouteValueDictionary(query) { { "Page", Page } }),
PagedListRenderOptions.PageNumbersOnly
)
so that the resulting url looks like this:
/FacilityFinder/Index?Page=5&name=Foo&owner=Bar&county[0]=foo1&county[1]=foo2...
which will make the default model binder in ASP.NET MVC happy and properly bind this to a List<string>.
My Html
#using (Html.BeginForm("userrights", "Users", FormMethod.Post, new { #class = "form-horizontal", role = "form", #id = "userrights_frm", #name = "userrights_frm" }))
{
<div class="form-group">
<div class="col-md-7" style="padding-right:10px">
#Html.TextBoxFor(m => m.firstname, new { #class = "form-control", #id = "firstname", #name = "firstname", #placeholder = "Serach By User Name" })
#Html.HiddenFor(m => m.id, new { #class = "form-control", #id = "id", #name = "id" })
</div>
<div class="col-sm-2">
<button type="submit" id="btn_search" value="Search" name="btn_search" class="btn btn-default">Search</button>
</div>
<div class="clearfix"></div>
</div>
<div class="form-group">
<div class="col-md-1" style="padding-top:7px"> Select Top Link </div>
<div class="col-sm-6">
#Html.DropDownList("selectedMenu", Model._menu.Select(menu => new SelectListItem { Text = menu.menuname, Value = menu.menuid.ToString() }), "Select Menu", new { #class = "form-control" })
</div>
<div class="clear"></div>
</div>
#Html.Partial("_userRightPartial", Model._UserRightPartialView)
<div class="clear"></div>
}
AjaxMethod on Select Menu Changed
$("#selectedMenu").change(function () {
mnid = $(this).val();
userId = $("#userid").val();
$.ajax({
type: 'POST',
url: "/Users/getsubmenus",
data: "{userid:'" + userId + "',menuid:'" + mnid + "'}",
contentType: "application/json; charset=utf-8",
dataType: 'json',
success: function (data) {
if (data.result == "Error") {
alert(data.message);
}
}
});
});
Action Result called in Ajax "getsubmenus"
public ActionResult getsubmenus(string userid, string menuid)
{
userright _userright = new userright();
user _user = _ftwCommonMethods.GetuserDataById(Convert.ToInt32(userid));
UserRightPartialView _UserRightPartialView = new UserRightPartialView();
if (_user!=null)
{
IEnumerable<SubMenuListModel> _SubMenuListModel = _ftwCommonMethods.GetSubMenuItemsByMenu(_user.id.ToString(), menuid);
_UserRightPartialView.firstname = _user.firstname;
_UserRightPartialView.userid = _user.id;
_UserRightPartialView._SubMenuListModel = _SubMenuListModel;
}
return PartialView("_userRightPartial", _UserRightPartialView);
}
ActionResult When i click on Search Button
[HttpPost]
[AuthorizeUser]
public ActionResult userrights(FormCollection form_collection)
{
IEnumerable<MenuListModel> _MenuListModel = _ftwCommonMethods.GetMenuItems();
int userid = 0;
if (!string.IsNullOrEmpty(form_collection["id"].ToString()) && form_collection["id"].ToString() != "0")
{
userid = Convert.ToInt32(form_collection["id"].ToString());
}
user _user = _ftwCommonMethods.GetuserDataById(userid);
UserRightViewSearch _UserRightViewSearch = new UserRightViewSearch();
_UserRightViewSearch._menu = _MenuListModel;
if (_user != null)
{
IEnumerable<SubMenuListModel> _SubMenuListModel = _ftwCommonMethods.GetSubMenuItems(_user.id.ToString());
UserRightPartialView _UserRightPartialView = new UserRightPartialView();
_UserRightPartialView.firstname = _user.firstname;
_UserRightPartialView.userid = _user.id;
_UserRightViewSearch.id = _user.id;
_UserRightPartialView._SubMenuListModel = _SubMenuListModel;
_UserRightViewSearch._UserRightPartialView = _UserRightPartialView;
}
else
{
ViewData["message"] = "User Not Found.";
}
return View(_UserRightViewSearch);
}
Partial View
#model FTW_Admin.Models.UserRightPartialView
#if (Model.firstname != null)
{
<div class="dhe-example-section" id="ex-1-2">
<div id="example-1-2">
<div class="col-md-6" style="padding:0px 10px 10px 0px">
<div class="drag_to">#Model.firstname
#Html.Hidden("userid", Model.userid, new { #id = "userid" })
</div>
<div class="middle_section">
<div class="inner_section_page_sec">
<div id="container" class="main_page_area">
<div class="column left first">
<div>
<ul class="sortable-list-allow">
#foreach (var row in Model._SubMenuListModel)
{
if (row.allowd)
{
<li class="sortable-item loop_content">
<table id="dragable_grid">
<tr>
<th style="color:#000">
#row.submenuname
#Html.Hidden("submenuid", #row.submenuid, new { #id = "submenuid" })
#Html.Hidden("menuid", #row.submenuid, new { #id = "menuid" })
</th>
<th class="heading_style_a" style="text-align:right"><span class="allowedSpan"> Allowed</span></th>
</tr>
</table>
</li>
}
}
</ul>
<div class="clear"></div>
</div>
</div>
<div class="clear"></div>
</div>
</div>
</div>
</div>
<div class="col-md-6" style="padding:0px 10px 10px 0px">
<div class="drag_to">Drag and Drop section to home screen section</div>
<div class="inner_section_page_sec">
<div class="main_page_area">
<div id="container">
<div class="column left">
<ul class="sortable-list-disallow">
#foreach (var row in Model._SubMenuListModel)
{
if (!row.allowd)
{
<li class="sortable-item loop_content">
<table id="dragable_grid">
<tr>
<th style="color:#000">
#row.submenuname
#Html.Hidden("submenuid", #row.submenuid, new { #id = "submenuid" })
#Html.Hidden("menuid", #row.submenuid, new { #id = "menuid" })
</th>
<th class="heading_style_a" style="text-align:right"><span class="allowedSpan">Denied</span></th>
</tr>
</table>
</li>
}
}
</ul>
</div>
</div>
<div class="clear"></div>
</div>
</div>
</div>
<div class="clear"></div>
</div>
</div>
}
The thing is when i search records i get all sub menu items in partial view initially. Then i want to do is when i select particular menu link in dropdown partial view should be updated only with submenus of selected menu
Your ajax function specifies a return type of json but your calling a controller method that returns a view. Then in the success callback, you refer to the result property which does not exist. Instead you need to update the DOM with the partial view your returning. In addition, there is no need to stringify the data you pass to the controller. You script should be
$("#selectedMenu").change(function () {
mnid = $(this).val();
userId = $("#userid").val();
$.ajax({
type: 'POST',
url: '#Url.Action("getsubmenus", "Users")', // don't hard code url's
data: { userid: userId, menuid: mnid }, // no quotes
dataType: 'html', // change this
success: function (data) {
$(someElement).html(data); // modify selector to suit
}
});
});
Side note: Your partial is rendering controls with duplicate id attributes (invalid html) and duplicate name attributes without indexers so will not be able to bind to a model when you submit the form, although its unclear what the point of all those hidden inputs is since there is nothing that can be edited so you just posting back exactly the same data unchanged (degrading your app and opening yourself to over-posting attacks)
I am working in MVC 4 and want to bind two models in view for which i used Tuple, and now i want to get values from both models in two different Divs but i am getting the following error:
here is my Controller code:
public ActionResult Edit()
{
CygnusInternalResponseViewModel result = new CygnusInternalResponseViewModel();
result = new Logic(CApplicationId, CurrentCompanyId).GetProducts();
if (result.Success)
return View(result.Model);
ProductOrderViewModel objparent = new ProductOrderViewModel();
List<ProductOrderViewModel> viewmodel = new List<ProductOrderViewModel>();
viewmodel.Add(objparent);
return View(viewmodel.AsEnumerable());
// return View();
}
here is my model code:
public class ProductOrderViewModel
{
public List<ProductViewModel> Products { get; set; }
public List<OrderViewModel> Orders { get; set; }
}
Please guide me to tackle this issue..Following is my Code
#model Cygnus.Global.ViewModels.ProductOrderViewModel
#using Cygnus.Global.ViewHelpers;
#using Cygnus.Global.ViewModels;
#{
ViewBag.Title = "Edit";
}
#using (Html.BeginForm())
{
<div id="productarea">
<div id="tabs-1">
#foreach (var pd in Model.Products)
{
<div>
<div style=" border: 1px solid black; margin-top:5px; padding-left: 10px; padding-bottom: 10px;" class="media p-t20px m-tn
">
<div class="left m-r10px">
<i class="fa fa-envelope-o comments-icon cmtIcon"></i>
</div>
<div class="media-body">
<p>
<span class="cmtText"> | #pd.Name | #pd.UnitPrice </span>
</p>
</div>
</div>
</div>
}
</div>
</div>
Your Order
<img src="~/Content/themes/base/images/locationicon.png" />
#for(int i = 0; i < Model.Orders.Count; i++) { #Html.EnumDropDownListFor(m => m.Orders[i].Area, new { #name = "area", #style = "width:295px; height:25px;margin-left:5px;" })
#Html.ValidationMessageFor(m => m.Orders[i].Area)}
<br /><br /><br />
<img style="margin-left:20px;" src="~/Content/themes/base/images/timeicon.png" title="Delivery Time" /> 1 hr <img style="margin-left:60px;" src="~/Content/themes/base/images/deliveryicon.png" title="Delivery Free" /> Free<img style="margin-left:60px;" src="~/Content/themes/base/images/walleticon.png" title="Minimum Order" /> Rs.1000
<br /><br />
<div style="height:150px;background-color:#fff;margin-left:-11px;margin-right:1px;">
<br /><br /><br />
<label style="float:right;color:red;margin-right:10px;">Start by Adding Items to Order!</label>
</div>
#for (int i = 0; i < Model.Orders.Count; i++) {
#Html.LabelFor(m =>m.Orders[i].SubTotal)
#Html.TextBoxFor(m => m.Orders[i].SubTotal, new {#readonly = "readonly" ,#style = "width:100px; float:right;margin-top:-21px;" })
<br />
#Html.LabelFor(m => m.Orders[i].Discount)
#Html.TextBoxFor(m => m.Orders[i].Discount, new { #readonly = "readonly", #style = "width:100px; float:right;margin-top:-21px;" })
<br />
#Html.LabelFor(m => m.Orders[i].DeliveryFee)
#Html.TextBoxFor(m => m.Orders[i].DeliveryFee, new { #readonly = "readonly", #style = "width:100px; float:right;margin-top:-21px;" })
<br />
#Html.LabelFor(m => m.Orders[i].TotalAmount)
#Html.TextBoxFor(m => m.Orders[i].TotalAmount, new { #readonly = "readonly", #style = "width:100px; float:right;margin-top:-21px;" })
}<br /><br />
<input id="btnproceed" type="button" value="Proceed to Order" />
</div>
<div id="customerdetails">
<label>Your Information</label><br />
#for (int i = 0; i < Model.Orders.Count; i++) {
#Html.TextBoxFor(m => m.Orders[i].Customer, new { #placeholder = "Enter Your Full Name" })
#Html.ValidationMessageFor(m => m.Orders[i].Customer)
#Html.TextBoxFor(m => m.Orders[i].Phone, new { #placeholder = "Enter Your Cell Number" })
#Html.ValidationMessageFor(m => m.Orders[i].Phone)
#Html.TextAreaFor(m => m.Orders[i].Address, new {#rows = 3, #cols = 2, #style = "width:300px;" , #placeholder = "Enter Your Complete Delivery Address" })
#Html.ValidationMessageFor(m => m.Orders[i].Address)
}
<input id="btnback" type="button" value="Back" /> <input id="submit" type="submit" value="Save" />
</div>
}
Create a class that contains the two models and populated them from your controller:
public class FooViewModel
{
public List<ProductViewModel> Products {get;set;}
public OrderViewModel Order {get; set;}
}
Then in your view:
#model FooViewModel
// code ommited
#foreach (var pd in Model.Products)
{
// rest of code
Also note that if the rest of the fields are related to the order it would be within the Order property i.e:
#Html.LabelFor(m =>m.Order.SubTotal)
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>
I need pass data displayed on Razor View page by ViewModel, to Controller. Values entered by user in #Html.EditorFor are passing successfully, but data from #Html.DisplayFor for are not. What I missing?
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<table>
<tr>
<td style="text-align: center; vertical-align: middle;">
<div class="main-container">
<h3 class="main-title" id="bold-title">
#Html.DisplayFor(model => model.EmailReceiver)
</h3>
<h3 class="main-title" id="thin-title">
#Html.DisplayFor(model => model.PurchaseDesc)
</h3>
#Html.EditorFor(model => model.EmailSender, new { htmlAttributes = new { #placeholder = "Your e-mail", #id = "e-mail" } })
#Html.EditorFor(model => model.CardNumber, new { htmlAttributes = new { #placeholder = "Your card number", #id = "card" } })
#Html.EditorFor(model => model.CardValidDate, new { htmlAttributes = new { #placeholder = "MM / YYYY", #id = "date" } })
#Html.EditorFor(model => model.CVV, new { htmlAttributes = new { #placeholder = "CVV", #id = "cvv" } })
<button class="button" id="pay-button" type="submit">
<div id="price">Pay #Html.DisplayFor(model => model.TotalAmount)$</div>
<br>
<div id="ok">Complete!</div>
</button>
</div>
</td>
</tr>
</table>
}
You'll need to add a hidden field to get those read-only values passed back. Use #Html.HiddenFor to generate an equivalent hidden field.