Introduction
Before reading this article, I would recommend reading my previous tutorial where I have explained how to implement basic In-place editing in asp.net MVC webgrid for better understanding.
Let's start implementing advance In-place editing in asp.net MVC webgrid.
Step - 1: Open Part 1 - Basic In-place editing in asp.net MVC webgrid application in visual studio.
So I am going to open the part 1 application first and if you have not downloaded the source code of the part 1 application till now, you can download from the below link.
Download Part 1 - Basic In-place editing in asp.net MVC webgrid source code.
Step-2: Update Index.cshtml for make Role columns cell editable.
Go to Solution Explorer > Open Index.cshtml view page from View > Home folder. Update the view page adding below yellow make jquery code for making the Role column cells editable.
@model List<InlineEditingWebgrid.ViewModel.SiteUserModel> @{ ViewBag.Title = "Index"; WebGrid grid = new WebGrid(Model, rowsPerPage:10); } <h2>Inplace editing in webgrid</h2> <hr /> <div class="row"> @grid.GetHtml( tableStyle:"table table-responsive table-striped table-bordered", columns: grid.Columns( grid.Column(header:"First Name", format:@<text><div class="edit" data-id="@item.ID" data-propertyname="FirstName">@item.FirstName</div></text>), grid.Column(header: "Last Name", format:@<text><div class="edit" data-id="@item.ID" data-propertyname="LastName">@item.LastName</div></text>), grid.Column(header: "Role", format:@<text><div class="editSelect" data-id="@item.ID" data-propertyname="RoleID">@item.RoleName</div></text>), grid.Column(header: "DOB", format:@<text><div class="editDate" data-id="@item.ID" data-propertyname="DOB">@string.Format("{0:dd-MM-yyyy}", item.DOB )</div></text>) ) ) </div> <style> .table td{width:25%;} .w100 { width:100px;} .margin10{ margin-left:10px; } </style> @section scripts{ <script src="https://www.appelsiini.net/download/jquery.jeditable.js"></script> <script> $(document).ready(function () { var oldValue = ''; $('.edit').editable('/home/saveuser', { cssclass: 'jeditForm', tooltip: 'click to edit me...', width: 'none', height: 'none', onsubmit: function (settings, original) { oldValue = original.revert; }, submitdata: function () { return { id: $(this).data('id'), PropertyName: $(this).data('propertyname') } }, callback: function (value, settings) { var jsonData = $.parseJSON(value); if (jsonData.status) { $(this).text(jsonData.value); } else { $(this).text(oldValue); } } }) $('.editSelect').editable('/home/saveuser', { cssclass: 'jeditForm', tooltip: 'click to edit me...', width: 'none', height: 'none', type: 'select', submit: 'Ok', loadurl: '/home/GetUserRoles', loaddata: function () { return {id: $(this).data('id')} }, onsubmit: function (settings, original) { oldValue = original.revert; }, submitdata: function () { return { id: $(this).data('id'), PropertyName: $(this).data('propertyname') } }, callback: function (value, settings) { var jsonData = $.parseJSON(value); if (jsonData.status) { $(this).text(jsonData.value); } else { $(this).text(oldValue); } } }) $('.editSelect').click(function () { $('select', this).addClass('form-control pull-left w100'); $('button', this).addClass('btn btn-sm btn-success margin10') }) }) </script> }
Line 60:
type: 'select' -
This is for render select/dropdown list control in edit modeLine 61:
submit: 'Ok' -
This is for rendering submit button. Here the edit form will submit only when the submitted button will be clicked. I have added this submit button here as I want the user to click on the submit button for submitting updated data to the server.Line 62:
loadurl: '/home/GetUserRoles' -
The loadurl
allows us to fetch select/dropdown list option from external URL like here we are fetching from '/home/GetUserRoles' URL.Line 63:
loaddata: function () {return {id: $(this).data('id')}} -
The loaddata
allows us to pass extra parameter when using loadurl. Here we are passing selected user id for getting the selected user role and select in the select/dropdown list control.and all remaining parameters we had already used and described in the part 1 tutorial.
Step-3: Add an another MVC action "GetUserRoles" in HomeController.
public ActionResult GetUserRoles(int id) { //Allowed response content format //{'E':'Letter E','F':'Letter F','G':'Letter G', 'selected':'F'} int selectedRoleID = 0; StringBuilder sb = new StringBuilder(); using (MyDatabaseEntities dc = new MyDatabaseEntities()) { var roles = dc.UserRoles.OrderBy(a => a.RoleName).ToList(); foreach (var item in roles) { sb.Append(string.Format("'{0}':'{1}',", item.ID, item.RoleName)); } selectedRoleID = dc.SiteUsers.Where(a => a.ID == id).First().RoleID; } sb.Append(string.Format("'selected': '{0}'", selectedRoleID)); return Content("{" + sb.ToString() + "}"); }
Step-4: Update "saveuser " existing MVC action of HomeController.
Updated
saveuser
MVC action[HttpPost] public ActionResult saveuser(int id, string propertyName, string value) { var status = false; var message = ""; //Update data to database using (MyDatabaseEntities dc = new MyDatabaseEntities()) { var user = dc.SiteUsers.Find(id); object updateValue = value; bool isValid = true; if (propertyName == "RoleID") { int newRoleID = 0; if (int.TryParse(value,out newRoleID)) { updateValue = newRoleID; //Update value field value = dc.UserRoles.Where(a => a.ID == newRoleID).First().RoleName; } else { isValid = false; } } else if (propertyName == "DOB") { DateTime dob; if (DateTime.TryParseExact(value,"dd-MM-yyyy",new CultureInfo("en-US"), DateTimeStyles.None, out dob)) { updateValue = dob; } else { isValid = false; } } if (user != null && isValid) { dc.Entry(user).Property(propertyName).CurrentValue = updateValue; dc.SaveChanges(); status = true; } else { message = "Error!"; } } var response = new { value = value, status = status, message = message }; JObject o = JObject.FromObject(response); return Content(o.ToString()); }
Step-5: Update Index.cshtml for make DOB column cells editable.
But as you can see the DOB is DateTime field So we should have a datepicker plugin and the plugin should work with our jeditable plugin. Right?
We don't have to worry about this as there is jquery.jeditable.datepicker.js plugin available for the same.
Download jquery.jeditable.datepicker.js plugin and add the jquery.jeditable.datepicker.js javascript file in the application. I have added the javascript file in the Scripts folder of my application.
Go to Solution Explorer > Open Index.cshtml view page from View > Home folder. Update the view page adding below yellow make jquery code for making the Role column cells editable.
@model List<InlineEditingWebgrid.ViewModel.SiteUserModel> @{ ViewBag.Title = "Index"; WebGrid grid = new WebGrid(Model, rowsPerPage:10); } <h2>Inplace editing in webgrid</h2> <hr /> <div class="row"> @grid.GetHtml( tableStyle:"table table-responsive table-striped table-bordered", columns: grid.Columns( grid.Column(header:"First Name", format:@<text><div class="edit" data-id="@item.ID" data-propertyname="FirstName">@item.FirstName</div></text>), grid.Column(header: "Last Name", format:@<text><div class="edit" data-id="@item.ID" data-propertyname="LastName">@item.LastName</div></text>), grid.Column(header: "Role", format:@<text><div class="editSelect" data-id="@item.ID" data-propertyname="RoleID">@item.RoleName</div></text>), grid.Column(header: "DOB", format:@<text><div class="editDate" data-id="@item.ID" data-propertyname="DOB">@string.Format("{0:dd-MM-yyyy}", item.DOB )</div></text>) ) ) </div> <style> .table td{width:25%;} .w100 { width:100px;} .margin10{ margin-left:10px; } </style> <link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" rel="stylesheet" /> @section scripts{ <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> <script src="https://www.appelsiini.net/download/jquery.jeditable.js"></script> <script src="~/Scripts/jquery.jeditable.datepicker.js"></script> <script> $(document).ready(function () { var oldValue = ''; $('.edit').editable('/home/saveuser', { cssclass: 'jeditForm', tooltip: 'click to edit me...', width: 'none', height: 'none', onsubmit: function (settings, original) { oldValue = original.revert; }, submitdata: function () { return { id: $(this).data('id'), PropertyName: $(this).data('propertyname') } }, callback: function (value, settings) { var jsonData = $.parseJSON(value); if (jsonData.status) { $(this).text(jsonData.value); } else { $(this).text(oldValue); } } }) $('.editSelect').editable('/home/saveuser', { cssclass: 'jeditForm', tooltip: 'click to edit me...', width: 'none', height: 'none', type: 'select', submit: 'Ok', loadurl: '/home/GetUserRoles', loaddata: function () { return {id: $(this).data('id')} }, onsubmit: function (settings, original) { oldValue = original.revert; }, submitdata: function () { return { id: $(this).data('id'), PropertyName: $(this).data('propertyname') } }, callback: function (value, settings) { var jsonData = $.parseJSON(value); if (jsonData.status) { $(this).text(jsonData.value); } else { $(this).text(oldValue); } } }) $('.editSelect').click(function () { $('select', this).addClass('form-control pull-left w100'); $('button', this).addClass('btn btn-sm btn-success margin10') }) $('.editDate').editable('/home/saveuser', { cssclass: 'jeditForm', tooltip: 'click to edit me...', type: 'datepicker', datepicker: { dateFormat: 'dd-mm-yy', changeMonth: true, changeYear: true, yearRange: '1900:' +(new Date().getFullYear() - 18) }, onsubmit: function (settings, original) { oldValue = original.revert; }, submitdata: function () { return { id: $(this).data('id'), PropertyName: $(this).data('propertyname') } }, callback: function (value, settings) { var jsonData = $.parseJSON(value); if (jsonData.status) { $(this).text(jsonData.value); } else { $(this).text(oldValue); } } }) }) </script> }
type: 'datepicker' -
This is for render datepicker control in edit modeLine 100:
datepicker: '...' -
In the datepicker, we can define datepicker options. and all remaining parameters we had already used and described in the part 1 tutorial.