ASP.NET MVC3: WebGrid + Ajax Filters + Ajax Sorting & Paging - asp.net-mvc-3

Basically, I'm using WebGrid and I need to filter the results. The first problem I have here is it's my first time using WebGrid and I was hoping some of you could give me a hand with it... So far, I've managed to sort grid results and filter them with Ajax, but, when re-sorting the filtered results, the subset is lost and I go back to the beginning with the full set of results. I know why it's happening of course, but I don't figure out how to make it work.
Example:
On my view:
#model IQueryable<Cities>
#section MoreScripts
{
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
}
#using (Ajax.BeginForm(new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "GridData"}))
{
<fieldset>
<legend>Search Filters</legend>
<br />
<div>
Name
</div>
<div>
#Html.TextBox("Name")
</div>
<p>
<input type="submit" value="Search" />
</p>
</fieldset>
}
<div id="GridData">
#Html.Partial("Grid", Model)
</div>
My Partial View:
#model IQueryable<Cities>
#{
var grid = new WebGrid<Cities>(null,rowsPerPage: 5, defaultSort: "Nombre", ajaxUpdateContainerId: "GridData");
grid.Bind(Model, autoSortAndPage: true, rowCount: Model.Count());
#grid.GetHtml(columns:
grid.Columns(
grid.Column("Name", "Name", canSort: true),
grid.Column("CreationDate", "Creation Date", canSort: true),
grid.Column("Active", "Active", canSort: true, format: #<text><input type="checkbox" disabled="disabled" value="#item.ID" #(item.Active == true ? "Checked" : null) /></text>),
grid.Column(format: (item) => Html.ActionLink("Edit", "Edit", new { id = item.Id }, new { #class = "editLink smallCell", #title = "Edit" })),
grid.Column(format: (item) => Html.ActionLink("Delete", "Delete", new { id = item.Id }, new { #class = "deleteLink smallCell", #title = "Delete" }))),
tableStyle: "webgrid",
headerStyle: "webgrid-header",
footerStyle: "webgrid-footer",
alternatingRowStyle: "webgrid-alternating-row",
selectedRowStyle: "webgrid-selected-row",
rowStyle: "webgrid-row-style");
}
And finally what am doing wrong is here, on my controller:
public ActionResult Index()
{
return View(repository.GetAllRecords().OrderByDescending(f => f.CreationDate));
}
[HttpPost]
public ActionResult Index(string name)
{
var data = repository.GetAllRecords();
if(!string.IsNullOrEmpty(name))
data = data.Where(a => a.Name.Contains(name));
data = data.OrderByDescending(f => f.CreationDate);
return PartialView("Grid", data);
}
I'm also using a class WebGrid : WebGrid as seen here:
http://archive.msdn.microsoft.com/mag201107WebGrid/Release/ProjectReleases.aspx?ReleaseId=5667
So, this actually works fine for filtering, but once you get the filtered results and then try to change the sort order of your narrowed search results, you lose the elements and the 'name' parameter's value because the WebGrid goes agains the first controller action. Probably this is not the best approach, but as I said, I've never used WebGrid so I'm willing to learn. Any help would be really appreciated. Thanks.

Try to add FormMethod.Post to your form, so the request will go to the second ActionResult. Otherwise, the request is a GET, and goes to the first ActionResult Index() without the parameters.

Related

WebGrid Ajax.. how to make it work with MVC 4 W/Razor

I started working on WebGrid with MVC 4 and I able to display the paginating/sorting and its work as expected.... if i try to make it with with ajax then its doing the full post.
View: - Partial View: (_hostajax.cshtml)
#model IEnumerable<issoa_ef.host>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
#{
var grid = new WebGrid(
Model, rowsPerPage: 2,
defaultSort: "HostFirstName", ajaxUpdateContainerId: "ajaxgrid");
}
<div id="ajaxgrid">
#grid.GetHtml(
tableStyle: "gridTable",
headerStyle: "gridHead",
footerStyle: "gridFooter",
rowStyle: "gridRow",
alternatingRowStyle: "gridAltRow",
columns: grid.Columns
(
grid.Column("HostFirstName", header: "First Name", format: #<text>#Html.ActionLink((string)item.HostFirstName, "Details", "Host", new { id = item.HostId }, null)</text>),
grid.Column("HostMiddleName", header: "Middle Name"),
grid.Column("HostLastName", header: "Last Name"),
grid.Column("HostEmailAddress", header: "eMail Address")
)
)
</div>
Controller:
public ActionResult Index()
{
var model = db.host.ToList();
if (Request.IsAjaxRequest())
return PartialView("_hostajax", model);
else
return View(model);
}
Index page:
<h2>#ViewBag.Message</h2>
<p>
#Html.ActionLink("Request Deployment", "CreateDeployment")
</p>
#Html.Partial("_hostajax", Model)
I've made a similar application. The grid was not using ajax, but just GET method to switch pages. This happened cos grid's javascript was breaking with "jquery is not defined" error. When I added the jQuery the grid started using ajax.
see MVC 4 WebGrid and Jquery produces two errors. JQuery is undefined and a sort error after ajax model change for the "jquery is not defined" error.

MVC 3 Razor pass webgrid row data to controller using actionlink

I have a webgrid with an actionlink which I want to use to edit the selected row in a new view. I know that I can use an actionlink to supply an arguement to my actionresult method but I don't know how to pass the webgrid's row data to my controller apart from using actionlink.
#{
ViewBag.Title = "Index";
}
<h2>
Index</h2>
<p>
#Html.ActionLink("Create New User", "CreateUser")
</p>
<div class="webgrid-wrapper">
#model IEnumerable<UserManager.Models.vw_UserManager_Model_Add_Users>
#{
ViewBag.Title = "Jobs";
WebGrid grid = new WebGrid(Model, canPage: true, canSort: true, rowsPerPage: 15, selectionFieldName: "selectedRow", fieldNamePrefix: "gridItem");
}
#grid.GetHtml(
fillEmptyRows: true,
tableStyle: "webgrid",
alternatingRowStyle: "webgrid-alternating-row",
headerStyle: "webgrid-header",
footerStyle: "webgrid-footer",
selectedRowStyle: "webgrid-selected-row",
rowStyle: "webgrid-row-style",
mode: WebGridPagerModes.All,
columns: new[] {
//grid.Column("ApplicationId"),
//grid.Column("salutation"),
//grid.Column("PasswordSalt"),
grid.Column("FirstName"),
//grid.Column("LoweredEmail"),
//grid.Column("PasswordQuestion"),
//grid.Column("PasswordAnswer"),
// grid.Column("PasswordFormat"),
grid.Column("LastName"),
grid.Column("Password"),
grid.Column("isactive"),
//grid.Column("IsLockedOut"),
grid.Column("email"),
grid.Column("module_name"),
//grid.Column("LastLoginDate"),
//grid.Column("LastPasswordChangedDate"),
//grid.Column("LastLockoutDate"),
//grid.Column("FailedPasswordAttemptCount"),
//grid.Column("FailedPasswordAttemptWindowStart"),
//grid.Column("FailedPasswordAnswerAttemptCount"),
//grid.Column("FailedPasswordAnswerAttemptWindowStart"),
// Rest of grid columns, seen previously
#*grid.Column(
"",
header: "Actions",
format: #<text>
#Html.ActionLink("Edit", "Edit", new { id = item.email })
</text>
) ,
grid.Column(
"",
header: "Actions",
format: #<text>
#Html.ActionLink("Delete", "Delete", new { id = item.email })
</text>
) *#
#* grid.Column(
header:"",
format:#<text><div id="btnSelectedRow">
"#item.GetSelectLink("Edit")</div></text>
),*#
grid.Column(
header:"",
format:#<text><div id="btnSelectedRow">
"#Html.ActionLink("Edit record",
"EditUser",
"UserManager",
new {selectedRow = grid.SelectedRow },
null
)</div></text>
)
})
#if (grid.HasSelection)
{
var record = grid.SelectedRow;
#*#RenderPage("~/Views/UserManager/EditUser.cshtml", new { record = grid.SelectedRow })*#
}
</div>
<script type="text/javascript">
$(document).ready(function () {
function jQueryUIStyling() {
$('input:button, input:submit').button();
// Style tables.
$('.webgrid-wrapper').addClass('ui-grid ui-widget ui-widget-content ui-corner-all');
$('.webgrid-title').addClass('ui-grid-header ui-widget-header ui-corner-top');
jQueryTableStyling();
}
//
// Style tables using jQuery UI theme. This function is
// split out separately so that it can be part of the AJAX
// callback of the WebGrid WebHelper in ASP.NET MVC.
//
function jQueryTableStyling() {
$('.webgrid').addClass('ui-grid-content ui-widget-content');
$('.webgrid-header').addClass('ui-state-default');
$('.webgrid-footer').addClass('ui-grid-footer ui-widget-header ui-corner-bottom ui-helper-clearfix');
}
});
</script>
My controller
public ActionResult EditUser(System.Web.Helpers.WebGrid record)
{
record.ToString();
return View();
}
Summary
How to pass row data using ActionLink from one view to another via ActionResult method.
You have two options, really: have your action take the user Id and look the user up, or have each row of your grid contain a form which sends all the user details to the action when you click 'edit'. Which of those you choose depends on what your action is supposed to do:
If it redirects to a form where the user can edit the user they selected, use the first approach
If it takes all the user details and saves an updated user, use the second approach
Edit
To pass the id you can use this for the action link:
#Html.ActionLink(
"Edit record",
"EditUser",
"UserManager",
new { id = item.email })
...and this for the action signature:
public ActionResult EditUser(string id)

using ajax loading search data to existing data grid

this is my action method
public ViewResult Index(string firstName)
{
// get the list of employees according to the user name
if (firstName == null)
{
return View((from e in db.Employees
where e.IsActive == true
select e).ToList());
}
else
{
return View((from e in db.Employees
where e.IsActive == true && e.FirstName.Contains(firstName )
select e).ToList());
}
}
This is my view
#{
var grid = new WebGrid(source: Model,
defaultSort: "UserName",
rowsPerPage: 15, ajaxUpdateContainerId: "grid");
}
#using (Html.BeginForm())
{
<div class="btn_align">
#if (Request.IsAuthenticated && HttpContext.Current.User.IsInRole("Administrator"))
{
<h2>#Html.ActionLink("Create New", "Create")</h2>
}
</div>
<div class="btn_align">
<p>
Find by name:<input class="inputStyle_S" id="firstName" name="firstName" type="text" value="" data-autocomplete= "#Url.Action("QuickSearchFirstName", "ApplyLeave")" />
<input type="submit" id="txtSearch" value="Search" class="btn"/>
</p>
</div>
<div id="grid">
#grid.GetHtml(
tableStyle: "grid",
headerStyle: "head",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column("User Name", format: (item) => item.FirstName + ' ' + item.LastName),
grid.Column("EmployeeType.Type", "Employee Type"),
grid.Column(header: "Action", format: (item) =>
Html.ActionLink("Details", "Details", new { id = item.id}))
)
)
</div>
}
</div>
<div class="leaveChart_bottom"></div>
I used web grid for representing data
I want get search results to exixting grid without refreshing page , after submiting search button (Search by name)
this is the ajax method I used ,but its not working.Can anyone helpme?
you should use #Ajax.BeginForm it will update your grid without refreshing the page. create a partial class for Grid so that you will get it's RenderHtmlString at server side.
In PartailClass
//GridPartail.cshtml
#model SomeModel
#{
var grid = new WebGrid(source: SomeModel,
defaultSort: "UserName",
rowsPerPage: 15, ajaxUpdateContainerId: "grid");
}
<div id="grid">
#grid.GetHtml(
tableStyle: "grid",
headerStyle: "head",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column("User Name", format: (item) => item.FirstName + ' ' + item.LastName),
grid.Column("EmployeeType.Type", "Employee Type"),
grid.Column(header: "Action", format: (item) =>
Html.ActionLink("Details", "Details", new { id = item.id}))
)
)
</div>
now modified your View
#using (#Ajax.BeginForm("Index", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "gridResult" }))
{
<div class="btn_align">
#if (Request.IsAuthenticated && HttpContext.Current.User.IsInRole("Administrator"))
{
<h2>#Html.ActionLink("Create New", "Create")</h2>
}
</div>
<div class="btn_align">
<p>
Find by name:<input class="inputStyle_S" id="firstName" name="firstName" type="text" value="" data-autocomplete= "#Url.Action("QuickSearchFirstName", "ApplyLeave")" />
<input type="submit" id="txtSearch" value="Search" class="btn"/>
</p>
</div>
<div id="gridResult">
#html.Partail("GridPartail",Model)
</div>
}
NOTE: instead of using Html.BeginForm use Ajax.BeginForm.in your case you have not bind text box to model so that you will get it's value in formCollection
In Controller
[HttpPost]
public ActionResult Index(formCollection coll)
{
string firstName = coll["firstName"];
// get the list of employees according to the user name
if (firstName == null)
{
var result = from e in db.Employees
where e.IsActive == true
select e).ToList();
return PartailView("GridPartail",result );
}
else
{
//"GridPartail.cshtml" is partial viewName
var result = (from e in db.Employees
where e.IsActive == true && e.FirstName.Contains(firstName )
select e).ToList();
return View("GridPartail",result );
}
}
as in AjaxOption i have mention action method POST and you must be pass UpdateTargetId which specify where your result will appear on the view.

How to hide the webgrid when execute the page in mvc3 razor?

When I remove the webgrid and layout=null in the view, its executing and client side validation message is displaying... but When I execute the page with layout= nlll and Webgrid it displaying the below error "A data source must be bound before this operation can be performed"
Controller :
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Display()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Display(string brandname)
{
ShoppingClass s = new ShoppingClass();
var ob= s.Searching(brandname);
return View(ob);
}
view :
#model List<ShoppingCart.Models.ShoppingClass>
#{
ViewBag.Title = "Display";
Layout = null;
}
#{
var grid = new WebGrid(source: Model, defaultSort: "Drug_Code", rowsPerPage: 20);
}
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
#using (Html.BeginForm(null, null, FormMethod.Post))
{
for (int i = 0; i < 1; i++)
{
#*
<table><tr><td> #Html.Label("BrandName")</td>
<td>#Html.TextBox("BrandName")<div>#Html.ValidationMessage("BrandName")</div></td>
<td><input type="submit" value="Search" name="Search" /></td></tr></table>*#
<table><tr><td> #Html.LabelFor(o => o[i].BrandName)</td>
<td>#Html.TextBoxFor(o => o[i].BrandName)<div>#Html.ValidationMessageFor(o => o[i].BrandName)</div></td>
<td><input type="submit" value="Search" name="Search" /></td></tr></table>
}
}
<div id="grid">
#grid.GetHtml(tableStyle: "listing-border", headerStyle: "gridhead", footerStyle: "paging", rowStyle: "td-dark", alternatingRowStyle: "td-light",
columns: grid.Columns(
grid.Column("GenericName", format: #<text>#item.GenericName</text>),
grid.Column("BrandName", format: #<text>#item.BrandName</text>),
grid.Column("Purchaseqty", format: #<text>#item.Purchaseqty</text>),
grid.Column("Purchaseprice", format: #<text>#item.Purchaseprice</text>),
grid.Column("Drug_Code", format: #<text>#item.Drug_Code</text>),
grid.Column(header: "", format: (item) => Ajax.ActionLink("Add to Cart", "ADDTOCART",
new { brandname = #item.BrandName, purchaseqty = #item.Purchaseqty, drugcode = #item.Drug_Code }, new AjaxOptions { HttpMethod = "Post", OnSuccess = "ADDTOCART" }))
)
)
</div>
If you want to hide the grid if the model is null, then you can put an if statement in that checks if the model is null... ie.
if (model != null)
{
// Make and populate grid here
}

validation is not firing on textbox in RAZOR?

1below I have posted my total coding of view. Here validation is not firing on the textbox. I dont know how to sort out this problem. This view is executing. if I press the search textbox without entering the text in textbox, its not validating.Also tell me wheather I have to use TextBox or TextBoxFor. I am fresher and new to mvc3. Please tell me the solution.
#model IEnumerable< ShoppingCart.Models.ShoppingClass>
#{
ViewBag.Title = "Display";
}
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
#Html.ValidationSummary(true)
#using (Html.BeginForm("Display","Home", FormMethod.Post, new { id = "loginForm" }))
{
//for (int i = 0; i < 1; i++)
//{
<table><tr>o<td> #Html.Label("BrandName")</td>
<td>#Html.TextBox("BrandName") <div> #Html.ValidationMessage("BrandName")</div></td>
<td></td></tr></table>
#* <table><tr><td>
#Html.LabelFor(o=>o[i].BrandName)</td>
<td>#Html.EditorFor(o => o[i].BrandName) <div>#Html.ValidationMessageFor(o => o[i].BrandName)</div></td>
<td></td></tr></table>*#
// }
<input type="submit" value="Search" name="Search" />
}
#{
var grid = new WebGrid(source: Model, defaultSort: "Drug_Code", rowsPerPage: 20);
<div id="grid">
#grid.GetHtml(tableStyle: "listing-border", headerStyle: "gridhead", footerStyle: "paging", rowStyle: "td-dark", alternatingRowStyle: "td-light",
columns: grid.Columns(
grid.Column("GenericName", format: #<text>#item.GenericName</text>),
grid.Column("BrandName", format: #<text>#item.BrandName</text>),
grid.Column("Purchaseqty", format: #<text>#item.Purchaseqty</text>),
grid.Column("Purchaseprice", format: #<text>#item.Purchaseprice</text>),
grid.Column("Drug_Code", format: #<text>#item.Drug_Code</text>),
grid.Column(header: "", format: (item) => Ajax.ActionLink("Add to Cart", "ADDTOCART",
new { brandname = #item.BrandName, purchaseqty = #item.Purchaseqty, drugcode = #item.Drug_Code }, new AjaxOptions { HttpMethod = "Post", OnSuccess = "ADDTOCART" }))
)
</div>
}
Edit: added a more complete example.
I'm not sure from the comments above if it's working to your satisfaction or not, but I think the root of your issue is that you are trying to use a model of IEnumerable where you don't need one. I understand that you need it for your grid, but what if you either put the grid or the search box in a PartialView? The PartialView could have its own model, and then you wouldn't need to fit your search box into a model that doesn't really fit.
The way I understand it, you're not actually passing data into the search box. You are only using the model at the search box so you get field validation. Let me know if that is incorrect.
Edit your view to look like this:
#model IEnumerable< ShoppingCart.Models.ShoppingClass>
#{
ViewBag.Title = "Display";
}
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
#Html.ValidationSummary(true)
#{Html.RenderPartial("_Search", Model.First());} //Need to make sure Model.First() actually exists, or you'll get error when it doesn't
//If you change your partial view to have a view model with just brand name, call it like this:
//#Html.RenderPartial("_Search", new _SearchViewModel())
//If you're only using the view model for required field validation on the return trip, then you don't actually need to pass data down to it.
#{
var grid = new WebGrid(source: Model, defaultSort: "Drug_Code", rowsPerPage: 20);
<div id="grid">
#grid.GetHtml(tableStyle: "listing-border", headerStyle: "gridhead", footerStyle: "paging", rowStyle: "td-dark", alternatingRowStyle: "td-light",
columns: grid.Columns(
grid.Column("GenericName", format: #<text>#item.GenericName</text>),
grid.Column("BrandName", format: #<text>#item.BrandName</text>),
grid.Column("Purchaseqty", format: #<text>#item.Purchaseqty</text>),
grid.Column("Purchaseprice", format: #<text>#item.Purchaseprice</text>),
grid.Column("Drug_Code", format: #<text>#item.Drug_Code</text>),
grid.Column(header: "", format: (item) => Ajax.ActionLink("Add to Cart", "ADDTOCART",
new { brandname = #item.BrandName, purchaseqty = #item.Purchaseqty, drugcode = #item.Drug_Code }, new AjaxOptions { HttpMethod = "Post", OnSuccess = "ADDTOCART" }))
)
</div>
}
Create a Partial View (_Search):
#model ShoppingCart.Models.ShoppingClass
//You could also create a different View Model that just has brand name, and pass the data down another way
//See examples in the code for the view
#Html.ValidationSummary(true)
#using (Html.BeginForm("Display","Home", FormMethod.Post, new { id = "loginForm" }))
{
<table><tr><td>
#Html.LabelFor(o=>o.BrandName)</td>
<td>#Html.EditorFor(o => o.BrandName) <div>#Html.ValidationMessageFor(o => o.BrandName)</div></td>
<td></td></tr></table>
<input type="submit" value="Search" name="Search" />
}

Resources