ASP.NET MVC 3 WebGrid Sort Order Image - asp.net-mvc-3

I am working with a WebGrid, and I would like to have an image or character like "^" "v" in the header showing the column with the sort order.
How can I do this?
This is the code of one of my Webgrids:
<div id="contenedor-gridACTIVIDAD">
#{
WebGrid gridACTIVIDAD = new WebGrid(Model.actividadDiaria, ajaxUpdateContainerId: "contenedor-gridACTIVIDAD", rowsPerPage: 20);
}
#gridACTIVIDAD.GetHtml(
fillEmptyRows: true,
alternatingRowStyle: "fila-alternativa",
headerStyle: "encabezado-grid",
footerStyle: "pie-grid",
mode: WebGridPagerModes.All,
firstText: "<<",
previousText: "<",
nextText: ">",
lastText: ">>",
columns: new[] {
gridACTIVIDAD.Column("contrato", header: "Contrato"),
gridACTIVIDAD.Column("Observacion", header: "Observación"),
gridACTIVIDAD.Column("DESCR", header: "Tarea"),
gridACTIVIDAD.Column("FECHA", header: "Fecha",
format: (item) =>
{
return item.fecha.ToString("dd/MM/yyyy");
}
),
gridACTIVIDAD.Column("",
header: "ESTADO",
format: (item) =>
{
if (item.estado == "VC")
{
return Html.Image("/Imagenes/vc.gif","Validado correcto", new { #border = "0"});
}
else if (item.estado == "VI")
{
return Html.Image("/Imagenes/vi.gif", "Validado incorrecto", new { #border = "0" });
}
else if (item.estado == "NV")
{
return Html.Image("/Imagenes/vp.gif", "No validado", new { #border = "0" });
}
else
{
return Html.Image("/Imagenes/nv.png", "Pendiente validar", new { #border = "0" });
}
}
),
gridACTIVIDAD.Column("JDP", header: "JDP")
}
)
</div>

I've solved this issue on server side using HTMLAgilityPack.
This is the code for the view:
WebGrid webGrid = new WebGrid(Model.myModel, defaultSort: "title", rowsPerPage: 20);
IHtmlString webGridHtml = webGrid.GetHtml(
columns: webGrid.Columns(
webGrid.Column("id", "ID"),
webGrid.Column("title", "Title")
)
);
#Helper.GetExtendedWebGrid(webGrid, webGridHtml);
And this is the code for the Helper class:
public static IHtmlString GetExtendedWebGrid(WebGrid webGrid, IHtmlString webGridHtml)
{
HtmlString result;
string webGridHtmlString = webGridHtml.ToString();
HtmlDocument htmlDocument = new HtmlDocument();
htmlDocument.LoadHtml(webGridHtmlString);
HtmlNode htmlNodeAnchor = htmlDocument.DocumentNode.SelectSingleNode("//a[contains(#href,'" + webGrid.SortColumn + "')]");
if (htmlNodeAnchor != null)
{
string imgSortDirection;
if (webGrid.SortDirection == SortDirection.Ascending)
imgSortDirection = "asc";
else
imgSortDirection = "desc";
HtmlNode htmlNodeIcon = HtmlNode.CreateNode("<img src=\"/images/" + imgSortDirection + ".png\" width=\"10\" height=\"10\" />");
htmlNodeAnchor.ParentNode.AppendChild(htmlNodeIcon);
webGridHtmlString = htmlDocument.DocumentNode.OuterHtml;
}
result = new HtmlString(webGridHtmlString);
return result;
}

I just did a google search on "webgrid sort indicator" and came back with a result from http://prokofyev.blogspot.com/2011/01/sort-indicator-in-systemwebhelperswebgr.html
Basically, the person uses jQuery to add in the sort direction image.
<script type="text/javascript">
$('thead > tr > th > a[href*="sort=#grid.SortColumn"]').parent()
.append('#(grid.SortDirection == SortDirection.Ascending ? "U" : "D")');
</script>
(As an added bonus, I just tested it myself, so you can copy and paste this code (the link one is a picture instead of a code sample :( ...) just replace the U and D with whatever you want to display instead.
Hope that helps.

This page has a very simple example of how to implement the sorting arrow or images, when using the WebGrid with AJAX.
http://www.mikesdotnetting.com/Article/203/Enhancing-The-WebGrid-With-Sort-Arrows

Related

jQGrid asp.net mvc 3 implementation from scratch

I am trying to implement jQGrid in my application with some basic features including filtering and sub grid. I looked numerous articles but many of them seem to be old and outdated. I think i am struggling with the basics of implementing it. I will really appreciate if you can provide basic controller view structure or refer to any sort of tutorial from scratch with asp. net mvc 3.
Here is the code in the View (first mark-up, then JS):
#model SampleApp.SampleModel
#{
ViewBag.Title = "Stackoverflow Title";
Layout = "~/Views/Shared/_defaultLayout.cshtml";
}
<link href="#Url.Content("~/Content/themes/cupertino/jquery-ui-1.8.13.custom.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/grid/ui.jqgrid.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/ui/jquery-ui-1.8.12.custom.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/grid/grid.locale-en.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/grid/jquery.jqGrid.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/myJSHelper.js")" type="text/javascript"></script>
<script type="text/javascript" id="loadGridResultsScript1">
// This code LOADs the grid by calling the MVC Action to get Data
$(document).ready(function () { helper.loadSearchResults('#Model.JobCode'); });
</script>
<!-- these are the jQuery Grid controls -->
<table id="list" class="scroll" cellpadding="0" cellspacing="0"></table>
<div id="pager" class="scroll" style="text-align:center;"></div>
Here is the JS function from myHelper JS file:
loadSearchResults: function (id) {
$("#list").jqGrid({
url: vpath + '/Sample/GetTargets/' + id,
datatype: 'json', mtype: 'POST', colNames: cols,
colModel: colModel, pager: $('#pager'),
rowNum: 15, rowList: [5, 10, 15, 25, 50, 100], sortname: cols[1],
sortorder: "asc", viewrecords: true,
imgpath: '', caption: ' '
});
$("#list").setGridWidth(1000, true);
$("#list").setGridHeight(350, true);
}
and here is the Action that jQuery calls:
public ActionResult GetTargets(string id, string sidx, string sord, int page, int rows)
{
var repo = IOCContainer.Resolve<DataRepository>();
////////////////////////////////////////////////////////////////////
var job = svc.GetJobByCode(id);
// job is my 'Model', it is a System.Data.DataSet
int pageIndex = Convert.ToInt32(page) - 1;
int pageSize = rows;
int totalRecords = (job.Targets == null) ? 0 : job.Tables[0].Rows.Count;
int totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);
List<DataRow> pageSet = Enumerable.Empty<DataRow>().ToList();
if (totalRecords > 0)
{
// Get rows for current page!!!
if (sord == "asc")
{
if (sidx == " ") sidx = job.Tables[0].Columns[0].ColumnName;
pageSet = job.Tables[0].Rows.Cast<DataRow>()
.OrderBy(q => q[sidx])
.Skip(pageIndex * pageSize)
.Take(pageSize)
.ToList();
}
else
pageSet = job.Targets.Tables[0].Rows.Cast<DataRow>()
.OrderBy(q => q[sidx])
.Reverse()
.Skip(pageIndex * pageSize)
.Take(pageSize)
.ToList();
}
var cols = GetColumnNames(job.Tables[0]);
// Func to get Cells, called later on in code...
Func<DataRow, string[], string[]> getCells = (pkg, columns) =>
{
var cellList = new List<string>();
cellList.Add(pkg[0].ToString());
foreach (var col in columns)
{
if (col.StartsWith("_")) continue;
object cellContent = pkg[col];
string cellText = string.Empty;
if (cellContent is DateTime)
{
cellText = ((DateTime)cellContent).ToString("MM/dd/yyyy");
}
else if (cellContent is decimal || cellContent is double)
{
cellText = string.Format("{0:c}", cellContent);
}
else
{
cellText = String.Format("{0}", cellContent);
}
cellList.Add(cellText);
}
return cellList.ToArray();
};
var jsonData = new
{
total = totalPages,
page,
records = totalRecords,
rows = (
from item in pageSet
select new
{
i = item[0].ToString(),
cell = getCells(item, cols)
}).ToArray()
};
return Json(jsonData);
}
I hope you find this helpful. Let me know if there are any questions

Paging/Sorting not working on web grid used in Partial View

I have a partial view where I am showing a web grid depending upon a value selected from a page.
For drop down I have used
#Html.DropDownListFor(
x => x.ItemId,
new SelectList(Model.Items, "Value", "Text"),
new {
id = "myddl",
data_url = Url.Action("Foo", "SomeController")
}
)
For drop down item select I have used
$(function() {
$('#myddl').change(function() {
var url = $(this).data('url');
var value = $(this).val();
$('#result').load(url, { value: value })
});
});
and below is my action
public ActionResult Foo(string value)
{
SomeModel model = ...
return PartialView(model);
}
everything works good, but when I try doing a paging or sorting on my webgrid which is on my partial view I am showing a new window with the web grid.
I wanted to be able to sort and page on the same page without postback
Please help
The following example works fine for me.
Model:
public class MyViewModel
{
public string Bar { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Foo(string value)
{
var model = Enumerable.Range(1, 45).Select(x => new MyViewModel
{
Bar = "bar " + value + " " + x
});
return PartialView(model);
}
}
Index.cshtml view:
<script type="text/javascript">
$(function () {
$('#myddl').change(function () {
var url = $(this).data('url');
var value = $(this).val();
$.ajax({
url: url,
type: 'GET',
cache: false,
data: { value: value },
success: function (result) {
$('#result').html(result);
}
});
});
});
</script>
#Html.DropDownList(
"id",
new[] {
new SelectListItem { Value = "val1", Text = "value 1" },
new SelectListItem { Value = "val2", Text = "value 2" },
new SelectListItem { Value = "val3", Text = "value 3" },
},
new {
id = "myddl",
data_url = Url.Action("Foo", "Home")
}
)
<div id="result">
#Html.Action("Foo")
</div>
Foo.cshtml partial:
#model IEnumerable<MyViewModel>
#{
var grid = new WebGrid(
canPage: true,
rowsPerPage: 10,
canSort: true,
ajaxUpdateContainerId: "grid"
);
grid.Bind(Model, rowCount: Model.Count());
grid.Pager(WebGridPagerModes.All);
}
#grid.GetHtml(
htmlAttributes: new { id = "grid" },
columns: grid.Columns(
grid.Column("Bar")
)
)
Notice that I have used a GET request to refresh the grid instead of POST because this way the value query string parameter selected in the dropdown is preserved for future sorting and paging.

MVC3 WebGrid - Creating Columns Dynamically (foreach?)

I want to create a WebGrid with columns based on a collection, such as List. Something like this (which obviously doesn't work):
#grid.GetHtml(
columns: grid.Columns(
#foreach (var column in Model.ListOfColumns) {
grid.Column(column.Name, column.Title);
}
)
)
Any clever ideas?
You could ViewBag it like below.
Controller:
List<WebGridColumn> columns = new List<WebGridColumn>();
columns.Add(new WebGridColumn() { ColumnName = "Id", Header = "Id" });
columns.Add(new WebGridColumn() { ColumnName = "Name", Header = "Name" });
columns.Add(new WebGridColumn() { ColumnName = "Location", Header = "Location" });
columns.Add(new WebGridColumn() { Format = (item) => { return new HtmlString(string.Format("<a href= {0}>View</a>", Url.Action("Edit", "Edit", new { Id = item.Id }))); } });
ViewBag.Columns = columns;
View:
#grid.GetHtml(tableStyle: "ui-widget ui-widget-content",
headerStyle: "ui-widget-header",
columns: ViewBag.Columns
)
Try this:
#{
List<WebGridColumn> cols = new List<WebGridColumn>();
foreach(var column in Model.ListOfColumns)
{
cols.Add(grid.Column(column.Name, column.Title));
}
}
#grid.GetHtml(
columns: cols
)
You could use helper method
public static class GridExtensions
{
public static WebGridColumn[] DynamicColumns(
this HtmlHelper htmlHelper,
WebGrid grid
)
{
var columns = new List<WebGridColumn>();
columns.Add(grid.Column("Property1", "Header", style: "record"));
columns.Add(grid.Column("Property2", "Header", style: "record"));
columns.Add(grid.Column("Actions", format: (item) => { return new HtmlString(string.Format("<a target='_blank' href= {0}>Edit </a>", "/Edit/" + item.Id) + string.Format("<a target='_blank' href= {0}> Delete</a>", "/Delete/" + item.Id)); }));
return columns.ToArray();
}
Usage:
#{
var grid = new WebGrid(Model);
}
#grid.GetHtml(columns: grid.Columns(Html.DynamicColumns(grid)))

MVC 3 WebGrid with a checkbox filter

I'm developing a web application using MVC 3 RTM. In a view I have a WebGrid which works fine with sorting and paging. However, I also needed some filtering support on the page, so I added a textbox and a checkbox. The view code looks like this:
#using (Html.BeginForm("Index", "Customer", FormMethod.Get))
{
<fieldset>
<legend>Filter</legend>
<div class="display-label">
Search for</div>
<div class="display-field">#Html.TextBox("filter", null, new { onchange = "$('form').submit()" })</div>
<div class="display-label">
Show inactive customers?
</div>
<div class="display-field">
#Html.CheckBox("showInactive", false, new { onchange = "$('form').submit()" })
</div>
</fieldset>
var grid = new WebGrid(canPage: true, canSort: true, ajaxUpdateContainerId: "grid", rowsPerPage: 10, defaultSort: "Name");
grid.Bind(Model, rowCount: Model.Count, autoSortAndPage: false);
grid.Pager(WebGridPagerModes.All);
#grid.GetHtml(htmlAttributes: new { id = "grid" },
columns: grid.Columns(
grid.Column("Name", "Name"),
grid.Column("Address", "Address"),
grid.Column("IsActive", "Active", (item) => item.IsActive ? "Yes" : "No")));
}
This works fine except when I check the checkbox. When I load the page for the first time, the checkbox is not checked. Sorting and paging works, and I can enter some text as a filter and it filters my result, and sorting and paging still works after that. However, if I check the checkbox, it updates the result, but sorting no longer works. The filter still works though, so if I enter some text, it correctly filters the result and still respects the checkbox.
I've tried setting a breakpoint in my controller, and there's no problem there. The request is sent when I try to sort, and the controller correctly returns the view with the result as the model. But it doesn't seem like the WebGrid is updating itself.
Has anyone else experienced this, or has anyone some good advice on what to look for?
Thanks!
I normally add a form (above my WebGrid) which contains a textbox called "Keywords" and a checkbox called "IsActive" and when the "Go" button is clicked it reloads the WebGrid adding the "Keywords" and "IsActive" options to the query string.
You can add more elements to your form and their values will be sent al
Use the following helper script - webgrid.helper.js:
function reloadGrid(form) {
var grid = form._grid ? form._grid.value : "grid";
var args = {};
updateQueryParams(args, grid + " th a");
args.sort = "";
args.sortdir = "";
updateQueryParams(args, grid + " tfoot a");
args.page = 1;
for (var i = 0; i < form.elements.length; i++) {
var el = form.elements[i];
if (el.type == "text" || el.type == "select" || (el.type == "radio" && el.checked))
args[el.name] = el.value;
else if (el.type == "checkbox")
args[el.name] = el.checked;
}
//get controller name
var s = $("#grid th a")[0].onclick.toString();
s = s.substring(s.indexOf("/"));
var controller = s.substring(0, s.indexOf("?"));
var queryString = "";
for (var key in args)
queryString += "&" + key + "=" + escape(args[key]);
var url = controller + "?" + queryString.substring(1);
$("#" + grid).load(url + " #" + grid);
}
function updateQueryParams(args, path) {
var links = $("#" + path);
if (links.length == 0)
return;
var s = links[0].onclick.toString();
s = s.substring(s.indexOf("?") + 1);
s = s.substring(0, s.indexOf(" #"));
var a = /\+/g; // Regex for replacing addition symbol with a space
var r = /([^&=]+)=?([^&]*)/g;
var d = function (s) { return decodeURIComponent(s.replace(a, " ")); };
var q = s;
while (e = r.exec(q))
args[d(e[1])] = d(e[2]);
}
Then just above my webgrid, I have the following partial file - *_ListFilter.cshtml*
#using (Html.BeginForm(null, null, FormMethod.Get))
{
<div id="filter">
<table width="600">
<tr>
<td>#Html.TextBoxFor(c => c.Keywords, new { size = 50, placeholder = Strings.SearchByKeywords, title = Strings.SearchByKeywords })</td>
<td>&nbsp

Retrieve the selected value from jQUery AutoComplete control

I need two questions answer if possible:
How to set the key\value within the jQuery Autocomplete control.
Retrieve the selected value from the jQuery Autocomplete control once a user selects a school name.
Thank in advance for your help.
<script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.min.js" type="text/javascript"></script>
function RetrieveSchoolsBasedOnSchoolTypeSelected() {
//Item Selected Value
var ItemSelectedValue = $("#selSchoolTypes: option[selected]").val();
$("#example").val("");
$.getJSON("http://devportal2/apps/parisinterndb/_vti_bin/ListData.svc/Schools?$filter=SchoolTypeId eq " + ItemSelectedValue + "", function(DataResults) {
var count = 0;
var resultDataItems = "";
$.each(DataResults.d.results, function(i, result) {
var title = result.Title;
resultDataItems += title +",";
});
resultDataItems += "";
var data = resultDataItems.split(',');
$("#example").autocomplete(data,
{ delay: 10,
minChars: 1,
cacheLength: 10,
autoFill: true
});
});
$("#example").result(findValueCallback).next().click(function() {
$(this).prev().search();
});
}
function findValueCallback(event, data, formatted) {
alert(formatted+" "+data);
}
for getting the selected value,just parse the data paramter in the findValueCallback function.You may need to parse the "data" using split function and all.
ex : if (data != null) {
var model = "";
model = data.toString().split(".")[1];
selectedItem= data.toString().split(".")[0];
}
For setting the key value pair in the autosuggest dropdown,u can use the autocomplete function with a server page which can load data,
$("#txtSearchKey").autocomplete("Lib/ajaxpages/GetModelOptions.aspx", {
minChars: 2,
width: 550,
max: 4,
highlight: false,
scroll: true,
scrollHeight: 300,
formatItem: function(data, i, n, value) {
return "<b>" + value.split(".")[0] + "</b>";
},
formatResult: function(data, value) {
return value.split(".")[0];
}
});
the GetModelOptions.aspx can retun data in the form a string like
1.Alaska \n 2.Mexico \n 3.Michigan \n
and in the javascript u extract it

Resources