Filter is getting lost in WebGrid + Paging + Sorting + Filtering in .NET 4.0
Asked Answered
D

3

14

I've implemented a WebGrid. Sorting, paging and filtering do not work together. They work when you use them alone. When you combine the three, at the same time, filtering doesn't work.

The symptom:
Filter the resultset, then sort.

or

Filter the resultset, then go to next page.

In both cases, the filter is lost. But it does page and sort.

In the code behind: When the action method is called via a sort or pagination, nulls show for each of the filter parameters.

When the action method is called via the filter, the filter parameters come through.

This tells me that when you initiate a sort or a pagination that it's not submitting the form.

public ActionResult MyPage(int? page, int? rowsPerPage, 
              string sort, string sortdir, 
              string orderNumber, string person, string product)

I've looked around on SO and elsewhere. There are plenty of examples and people asking how to do one or another or all three. But I have only seen one with my issue, so I'm posting it here. (his was unsolved as well)

I have my page implemented as follows:

@using (Ajax.BeginForm("MyPage", null, new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "myGrid" }, new { id = "filter" }))
{
    <div class="right">
        <select id="rowsPerPage" name="rowsPerPage">
            <option>15</option>
            <option>25</option>
            <option>50</option>
            <option>75</option>
            <option>100</option>
        </select>
    </div>  

    <div class="table">
        <div class="tableRow">
            <div class="tableCell">
                Order Number
            </div>
            <div class="tableCell">
                Person
            </div>
            <div class="tableCell">
                Product
            </div>
        </div>
        <div class="tableRow">
            <div class="tableCell">
                <input type="text" id="orderNumber" name="orderNumber" />
            </div>
            <div class="tableCell">
                <input type="text" id="person" name="person" />
            </div>
            <div class="tableCell">
                <input type="text" id="product" name="product" />
            </div>          
            <div class="tableCell">
                <input type="submit" class="button" value="Search" />
            </div>  
        </div>
    </div>

<br/>

<div id="myGrid">
    @Html.Partial("_MyPage", Model)
</div>

}

The grid is implemented as a partial view like this:

<script type="text/javascript">
    $(document).ready(function () {
        resetUI();
    });
</script>

@{
    var grid = new WebGrid(canPage: true, rowsPerPage: Model.rowsPerPage, canSort: true, ajaxUpdateContainerId: "grid", ajaxUpdateCallback: "resetUI");
    grid.Bind(Model.rows, rowCount: Model.TotalRecords, autoSortAndPage: false);
    @grid.GetHtml(
        tableStyle: "fancyTable",
        headerStyle: "header",
        footerStyle: "footer",
        rowStyle: "row",
        alternatingRowStyle: "alt",
        mode: WebGridPagerModes.Numeric | WebGridPagerModes.NextPrevious,
        nextText: "Next",
        previousText: "Previous",
        htmlAttributes: new { id = "grid" },
        columns: grid.Columns(
            grid.Column("OrderDate", "Order Date", format: @<text>@((item.OrderDate != null) && (item.OrderDate.ToString("MM/dd/yyyy") != "01/01/0001") ? item.OrderDate.ToString("MM/dd/yyyy") : "")</text>),
            grid.Column("OrderNumber", "Order Number"),
            grid.Column("Field1, "Field 1"),
            grid.Column("Field2", "Field 2"),
            grid.Column("Person", "Person"),
            grid.Column("Product", "Product"),
            grid.Column(format: (item) => Html.ActionLink("View", "Details", new { id = item.orderNumber }))
            )
        );
}
Dillondillow answered 7/4, 2012 at 4:37 Comment(2)
Did you find solution for this?Kindrakindred
Be aware that asp.net mvc will create extra hidden input elements for checkboxes and that the WebGrid seems to reinterpret these 2 elements if present in the querystring into a single element with 2 values, which can cause parsing issues in Razor if a model is bound to a checkbox via checkboxfor. I had to use jQuery to delete these hidden fields on the client side.Pharmacy
R
24

When building the pagination and sort links, the WebGrid helper takes into account all query string parameters present in the current url. It ignores POSTed and route values. And since your Search form POSTs, the values that have been entered by the user in this form are not present in the query string, so they are not part of the pagination and sort links and when you click on one of those links the values are lost. This is by design.

So one way to fix that is to replace your AjaxForm:

@using (Ajax.BeginForm("MyPage", null, new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "myGrid" }, new { id = "filter" }))

with a standard HTML form using the GET verb:

@using (Html.BeginForm("MyPage", null, FormMethod.Get))

or an AJAX form using the GET verb:

@using (Ajax.BeginForm("MyPage", null, new AjaxOptions { HttpMethod = "Get", InsertionMode = InsertionMode.Replace, UpdateTargetId = "myGrid" }, new { id = "filter" }))

Now, when the user wants to filter something and hits the Search submit button the values he entered in the search form will end up in the query string and when rendering the WebGrid helper will use them to generate its Sort and Page links and of course when you click on those links the values will be sent to the server.

If you want more control over this you might consider more advanced grid controls such as MvcContrib.Grid or the Telerik Grid for ASP.NET MVC.

Result answered 7/4, 2012 at 7:28 Comment(7)
It will also work with Ajax.BeginForm with GET using new AjaxOptions { HttpMethod = "Get", ...Workmanlike
No, I don't think it will work (although I haven't tested it and I might be wrong). When you do an AJAX request (no matter whether it is GET or POST) you are not modifying the current url.Result
It will work even with AJAX (I've tested it :)), the WebGrid internally uses the Request.QueryString to pass through the values to the pager and sorting links which gets populated also in AJAX requests.Workmanlike
@nemesv, great, I have updated my answer to include this information.Result
This isn't working. The entire page, not the grid, is being placed where the grid is. The entire page -- even the header and the search boxes are in there.Dillondillow
Did you reference the jquery.unobtrusive-ajax.js script? If you intend to use any of the Ajax.* helpers you need to add this script.Result
@010110110101 You have to return a partial view with the grid and not the entire one. elylucas.net/post/…Connacht
C
1

Submit the form to the URL that the paging link points to:

<script type="text/javascript">
     $(function () {
        $('th a, tfoot a').click(function () {
            $('form').attr('action', $(this).attr('href')).submit();
            return false;
        });
    });
</script>

This doesnot help me but might help you

Cervicitis answered 27/11, 2012 at 13:30 Comment(0)
C
1

Just create a GET for your action method, whenever a sort or paging fires from the grid it hits the GET method along with a lot of parameters (You can see by pointing at the paging number or sort header of the grid using web developer tools of your browser), there you can filter your dataset and then pass the model to the view :

[HttpGet]
public ActionResult MyPage()

Everytime you do Sort or Paging this method would be hit, then you can do your filtering, you could add some static flags which can be assigned depending on what you want to filter.

Chancroid answered 1/2, 2017 at 20:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.