MVC3 Webgrid sorting problem with 2nd+ columns - asp.net-mvc-3

in this sample the sorting of the grid works well with the first column. Every other column can only be sorted ascending, the "sortdir" never switches to "DESC". (Ajax caching is also disabled)
Does anybody knows a solution or had the same problem? What im doing wrong?
Controller:
[OutputCache(Location = OutputCacheLocation.None)]
public ActionResult Index_Result_Org(string sort, string sortdir)
{
this.setRep();
this.rep.LoadOV();
return View("Index_OV", rep.GetOV(sort != null ? sort : "Kennung", sortdir != null ? sortdir == "ASC" : true));
}
View:
#model List<Models.OV_View>
#{
Layout = null;
var grid_BA = Html.Grid<OV_View>(Model, ajaxUpdateContainerId: "BAS_OV", canPage: false, defaultSort: "Kennung");
}
<div id="BAS_OV">
#grid_BA.GetHtml(
htmlAttributes: new { #id = "webgrid_BA" },
alternatingRowStyle: "alt",
tableStyle: "BAS",
columns: grid_BA.Columns(
grid_BA.Column("Kennung", header: "Verbandskennung", format: #<text>#Html.Label(#item.Data.Kennung)</text>, canSort: true),
grid_BA.Column("Name", header: "Verbandsname", format: #<text>#item.Data.Name</text>, canSort: true),
grid_BA.Column("Anzahl", header: "Anzahl", format: #<text>#item.Data.Anzahl</text>, canSort: true, style: "counter_column"),
grid_BA.Column("Select", header: "X", canSort: false, format: #<text><input id="Select" name="Select" type="checkbox" onclick="Select(this)" value="#item.Select" #(item.Select == true ? "Checked" : null) /></text>, style: "checkbox_column"),
grid_BA.Column("ID", "", format: #<text>#item.Data.ID</text>, canSort: false, style: "invisible_column")
)
)
</div>

Got it.
Only the defaulSort: Column can be sorted descending.
So i added the following line to the controller:
this.ViewBag.Sort = sort;
And andded and changed the following lines in the view:
var grid_BA = Html.Grid<ErgoBAS_OV_View>(Model, ajaxUpdateContainerId: "BAS_OV", canPage: false, defaultSort: "Kennung");
to:
string temp = this.ViewBag.Sort != null ? this.ViewBag.Sort : "Kennung";
var grid_BA = Html.Grid<ErgoBAS_OV_View>(Model, ajaxUpdateContainerId: "BAS_OV", canPage: false, defaultSort: temp);
This is the dirty solution, think to be clean the defaultSort has to be added to the View Model, thats what i will do now.

Related

Pagination on WebGrid deactivates after adding entries

I'm using a WebGrid with pagination in conjunction with an AJAX popup window to add new entries. I've noticed that after I've added an entry the pagination links at the bottom of the WebGrid become inactive.
The popup calls the controller's Save action which finishes with the following:
return PartialView("_PersonGrid", pModel.Persons);
There are three views that are used here. An index, a grid and a popup. The grid is embedded in the index and the popup can be called by clicking on buttons on the grid and index.
The index view has the following code:
#using (Ajax.BeginForm(new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "myUserGrid" }))
{
<div id="myUserGrid">
#Html.Partial("_PersonGrid", Model.Persons)
</div>
<br />
//other code
}
The grid view (_PersonGrid.cshtml) is:
#model IEnumerable<CIMsWebApp.Client.Group.Entities.IPerson>
#{ var grid = new WebGrid(Model, canSort: true, canPage: true, defaultSort: "UserName", ajaxUpdateContainerId: "myUserGrid"); }
#grid.GetHtml(
tableStyle: "dataGrid",
headerStyle: "header",
alternatingRowStyle: "evenRow",
columns: grid.Columns
(
grid.Column(header: "User Name", columnName: "UserName", format: item => Html.Raw("<a href='#' class='userNames' data-personid='"+item.PersonId+"'>" + item.UserName + "</a>"), canSort: false),
grid.Column(header: "Role(s)", columnName: "Rolebuilder", canSort: false),
grid.Column(header: "Active", columnName: "ActiveIndBuilder", canSort: false),
grid.Column(header: "Action", format:
#<span><input type="button" class="edit-user" id="#item.PersonId" value="EDIT" />
</span>, canSort: false)
)
)
finally the popup view is:
#model CIMsWebApp.Models.PersonModel
#using (Html.BeginForm("Save", "Person", FormMethod.Post, new { id = "formUser" }))
{
//code
}
When I first arrive at the page or If I refresh it they become active again.
I'm guessing your "ajaxUpdateContainerId: "myUserGrid"" is a div with an id="myUserGrid" and the partial is loaded in there.. So correct me if I'm wrong but I believe that div should be in your partial. It's a bit confusing sometimes but you should try this out..
View:
#*Everything else except the div*#
#{Html.RenderPartial("_PersonGrid", Model)
PartialView:
#model IEnumerable<CIMsWebApp.Client.Group.Entities.IPerson>
<div id="myUserGrid">
#{ var grid = new WebGrid(Model, canSort: true, canPage: true, defaultSort: "UserName", ajaxUpdateContainerId: "myUserGrid"); }
#grid.GetHtml(
tableStyle: "dataGrid",
headerStyle: "header",
alternatingRowStyle: "evenRow",
columns: grid.Columns
(
grid.Column(header: "User Name", columnName: "UserName", format: item => Html.Raw("<a href='#' class='userNames' data-personid='"+item.PersonId+"'>" + item.UserName + "</a>"), canSort: false),
grid.Column(header: "Role(s)", columnName: "Rolebuilder", canSort: false),
grid.Column(header: "Active", columnName: "ActiveIndBuilder", canSort: false),
grid.Column(header: "Action", format:
#<span><input type="button" class="edit-user" id="#item.PersonId" value="EDIT" />
</span>, canSort: false)
)
)
</div>
If this doesn't work, give some additional data (the view in which you call the partial, where and how you call the save action, etc...)
After looking into how the WebGrid pagination actually works it seems that after carrying out a save it then tries to call a GET method on the Save method. So I created a method for this very purpose and then redirected it back to the Index method. The final two parameters get passed directly to the query string which are then used in the pagination.
[ActionName("Save")]
public ActionResult Pagination(string page, string __, long id = 0)
{
return RedirectToAction("Index", new {id = id, page=page, __ = __ });
}

Inserting links into a WebGrid

I'm looking to create some hyperlinks in a Webgrid. I'd like to have the "User Name" column display it's values as hyperlinks instead of text. Is it possible to incorporate the #Html.ActionLink function into the WebGrid below?
The columnName expects a string which corresponds to a property of the model that is being passed to the view. So the problem is how to get that into a link.
View:
#model IEnumerable<CIMsWebApp.Client.Group.Entities.IUser>
#{ var grid = new WebGrid(Model, canSort: true, canPage: true, defaultSort: "UserName", ajaxUpdateContainerId: "myUserGrid"); }
#grid.GetHtml(
tableStyle: "dataGrid",
headerStyle: "header",
alternatingRowStyle: "evenRow",
columns: grid.Columns
(
grid.Column(header: "User Name", columnName: "UserName", canSort: false),
grid.Column(header: "Role(s)", columnName: "Rolebuilder", canSort: false),
grid.Column(header: "Active", columnName: "ActiveInd", canSort: false),
grid.Column(header: "Action", format:
#<span><input type="button" class="edit-user" id="#item.PersonId" value="EDIT" />
</span>, canSort: false)
)
)
So the problem is how to get that into a link.
You could use the format parameter to provide any custom format you like for this cell (btw you already did this for the last column):
grid.Column(
header: "Subject",
columnName: "UserName",
format: item => Html.ActionLink((string)item.UserName, "SomeAction", new { id = (int)item.PersonId })
)

Razor webgrid sorting not working if grid is loaded using ajax

This is my code
WebGrid passiveAdGrid = new WebGrid(Model.InactiveAds, rowsPerPage: 10, ajaxUpdateContainerId: "passiveAdGrid");
<div >
#passiveAdGrid.Pager(WebGridPagerModes.NextPrevious);
#passiveAdGrid.GetHtml(tableStyle: "webGrid",
headerStyle: "header",
alternatingRowStyle: "alt",
htmlAttributes: new { id = "passiveAdGrid" },
columns: passiveAdGrid.Columns(
passiveAdGrid.Column(format: #<text><img src="#Url.Content("~/Content/images/preview-photo.gif")" alt="Image"/></text>),
passiveAdGrid.Column("Title", "Title", canSort: true),
passiveAdGrid.Column("ExpirationDate", "Date of Expiry", canSort: true),
passiveAdGrid.Column("NumViews", "Number of views", canSort: true),
passiveAdGrid.Column(format: (item) => Html.ActionLink("Activate", "PostAd", "Ads", new { relist = item.Id }, null)),
passiveAdGrid.Column(format: (item) => #Ajax.ActionLink("Remove", "RemoveAd", "Ads", new { adID = item.Id, status = "ActivationPending" }, new AjaxOptions { UpdateTargetId = "AdView", HttpMethod = "POST", OnBegin = "return confirm('Are you sure you wish to delete this Ad?');" }))
));
</div>
its works fine if the above code is executed while page first time loading ...
In my case I am loading this grid using ajax (ie,calling a action in cotroller which return a partial view via ajax and replace that resulting html with existing html)... But sorting is not working anymore after relaoding the grid using ajax

Custom message inside the webgrid if empty

#if (Model.ActivityCollection.Count > 0)
{
var grid = new WebGrid(source: Model.ActivityCollection, rowsPerPage: 12, canSort: false);
#grid.GetHtml(tableStyle: "webGrid",
headerStyle: "header",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column("EffectiveDate", "Effective Date", style: "date"),
grid.Column("PremiumPaymentAmount", "Premium Payment Amount", style: "amount"),
grid.Column("PaymentType", "Payment Type", style: "date")
));
}
else
{
}
I would like to display a message "No Payment Information Found" inside the web grid in the above else statement. Can someone help me with this?
<div class="grid" style="margin-left:5px;" id="grid">
#if (Model.ActivityCollection.Count > 0)
{
var grid = new WebGrid(source: Model.ActivityCollection, rowsPerPage: 12, canSort: false);
#grid.GetHtml(tableStyle: "webGrid",
headerStyle: "header",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column("EffectiveDate", "Effective Date", style: "date"),
grid.Column("PremiumPaymentAmount", "Premium Payment Amount", style: "amount"),
grid.Column("PaymentType", "Payment Type", style: "date")
));
}
else
{
<div class="grid">
<table cellspacing="0" width="80%">
<thead>
<tr>
<th>Effective Date</th>
<th>Premium Payment Amount</th>
<th>Payment Type</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="3" align="center" ><br />No payment information found<br /><br /> </td>
</tr>
</tbody>
</table>
<br/><br/><br/><br/>
</div>
}
</div>
I made this jQuery-function to be triggered when the grid has loaded, and if there is no data in the table it will insert a new row in the empty table to display the text. Much more manageable than building a replica of the WebGrid in HTML.
I added a row style to the Webgrid, to identify the rows (not wanting the header+footer): "webGridDataRow".
function addNoDataTextIfNeeded(){
if($(".webGrid .webGridDataRow").length < 1){ //if there are no data-rows in table, our text should be displayed
var newCell = $("<td>") //create the cell
.attr("colspan", $(".webGrid tr:first th").length) //set colspan so it will span entire grid width (counting the number of column headers)
.text("No data found"); //add the text to be displayed
$("<tr>").append(newCell).appendTo(".webGrid"); //add the cell to a row to the grid :)
}
}
you can do something like this?
public class MyWebGrid : WebGrid
{
public WebGridMkf(IEnumerable<dynamic> source = null,
IEnumerable<string> columnNames = null,
string defaultSort = null,
int rowsPerPage = 10,
bool canPage = true,
bool canSort = true,
string ajaxUpdateContainerId = null,
string ajaxUpdateCallback = null,
string fieldNamePrefix = null,
string pageFieldName = null,
string selectionFieldName = null,
string sortFieldName = null,
string sortDirectionFieldName = null) :
base(source, columnNames, defaultSort, rowsPerPage, canPage, canSort, ajaxUpdateContainerId, ajaxUpdateCallback, fieldNamePrefix, pageFieldName, sortFieldName, sortDirectionFieldName)
{
}
public IHtmlString Table(string tableStyle = null,
string headerStyle = null,
string footerStyle = null,
string rowStyle = null,
string alternatingRowStyle = null,
string selectedRowStyle = null,
string caption = null,
bool displayHeader = true,
bool fillEmptyRows = false,
string emptyRowCellValue = null,
IEnumerable<WebGridColumn> columns = null,
IEnumerable<string> exclusions = null,
Func<dynamic, object> footer = null,
object htmlAttributes = null)
{
if (this.TotalRowCount.Equals(0))
{
return new HtmlString("<div>teste</div>");
}
return base.Table(tableStyle, headerStyle, footerStyle, rowStyle, alternatingRowStyle, selectedRowStyle, caption, displayHeader, fillEmptyRows, emptyRowCellValue, columns, exclusions, footer, htmlAttributes);
}
}
and call:
var grid = new MyWebGrid(
ajaxUpdateContainerId: "grid-test",
rowsPerPage: 10,
defaultSort: "id"
);
grid.Bind(
source: Model.ActivityCollection,
rowCount: Model.ActivityCollection.Count
);
#grid.Table(
alternatingRowStyle: "color1",
rowStyle: "color0",
tableStyle: "webgrid table table-striped table-hover table-condensed",
headerStyle: "webgrid-header",
footerStyle: "webgrid-footer",
footer: #<span></span>,
columns: grid.Columns(
grid.Column(columnName: "id",
header: "ID",
style: "column-id",
canSort: true)
)
)

Razor WebGrid doesn't keep scrollbar position

Whenever I page or sort my ajax enabled webgrid, my scrollbar position is reset to the top of the page. Is there a way to maintain the scrollbar position?
#model Registrar.WebUI.Models.InstructorPageViewModel
#{
var grid = new WebGrid(canPage: true,
canSort: true,
rowsPerPage: Model.PagingInfo.ItemsPerPage,
ajaxUpdateContainerId: "grid");
grid.Bind(Model.Instructors, rowCount:Model.PagingInfo.TotalItems, autoSortAndPage:false);
grid.Pager(WebGridPagerModes.All);
}
<div id="grid">
#grid.GetHtml(columns: grid.Columns(
grid.Column(format: x => Html.ActionLink("Edit", "Edit", new {id=x.Id})),
grid.Column("FirstName", "First Name"),
grid.Column("LastName", "Last Name"),
grid.Column("Email"),
grid.Column("UserName", "User Name"),
grid.Column("Phone") )
)
</div>
This is because generated sort link in your header has href="#". I've got the same problem and this is my solution.
This is my _grid.cshtml partial view
#{
var grid = new WebGrid(Model.LeaseOffers, canPage: false, ajaxUpdateContainerId: "offerGrid", ajaxUpdateCallback: "afterLoad()");
}
<div id="offerGrid" class="offer-table-wrapper">
#grid.GetHtml(
rowStyle: "offer-table-tr-odd",
alternatingRowStyle: "offer-table-tr-even",
columns: grid.Columns(
grid.Column("ProviderLogo", "", format: #<img src="#Url.Content(string.Format(Constants.LeaseOfferProviderLogoContentUrlFormat, item.ProviderId))" />, style: "col-first", canSort: false),
grid.Column("ProviderName", "Leasingodawca", format: #<div>#item.ProviderName</div>, style: "col-name"),
grid.Column("DownPayment", "Udział Własny", format: #<div>#item.DownPayment.ToString(Constants.PercentDataToStringFormat)</div>, style: "col-third"),
grid.Column("LeasePeriod", "Okres leasingu", format: #<div>#string.Format(Constants.LeasePeriodDataFormat, item.LeasePeriod)</div>),
grid.Column("LeasePayment", "Rata leasingu", format: #<div>#string.Format(Constants.MoneyDataFormat, item.LeasePayment)</div>),
grid.Column("ResidualValue", "Wartość wykupu", format: #<div>#item.ResidualValue.ToString(Constants.PercentDataToStringFormat)</div>),
grid.Column("TotalLeasePayments", "Suma opłat", format: #<div>#item.TotalLeasePayments.ToString(Constants.PercentDataToStringFormat)</div>),
grid.Column("Actions", "", format: #<div><img src="#Href("~/Modules/LeaseBroker.Orchard.Module/Content/Images/Mockups/wezleasing.png")"/></div>, style: "col-last", canSort: false)
),
htmlAttributes: new { cellpadding = "0", cellspacing = "0" }
)
<script language="javascript">
function afterLoad() {
$("#offerGrid > table > thead > tr > th > a").attr('href', 'javascript:void(0)');
}
jQuery(document).ready(function ($) {
afterLoad();
});
</script>
Just after grid is loading i'm replacing all href attributes in header links into "javascript:void(0)"
You need to make sure that autopostback is disabled, It sounds like your page is redirecting, you just may not be noticing as it is happening so fast.

Resources