Grzegorz Fedczyszyn
Grzegorz Fedczyszyn

Reputation: 344

MVC 5 sorting and filtering data

On my view I have possibility to filter displayed data using Ajax.BeginForm that returns partail view and refreshes only a table with data. I also have a possibility to sort by column when clicking a column header using Ajax.ActionLink. The problem is that when I use Ajax.ActionLink I have to refresh whole page and I loose what was selected in filters (they are custom multiselect combo controls) so whole data is sorted and displayed.

I tried using ViewBag to send Json data to set back the filters but I failed. I would rather only refresh table even on sort. I am kind of new to MVC. How to do it in a nice way? Thanks for the help!

View:

@using (Ajax.BeginForm(new AjaxOptions() {HttpMethod = "get", InsertionMode = InsertionMode.Replace, UpdateTargetId = "exposureRecords"}))
{
    <div class="form-group">
        <select id="brands-select" name="brands" multiple="multiple">
            @{
                var brands = Model.Brands;

                foreach (var item in brands)
                {
                    <option value="@item">@item</option>
                }
            }
        </select>
    </div>
    (...similar for 3 other filters...)
    <table class="table">
        <tr>
            <th>
               @Html.ActionLink("Marka", "Index", new { sortOrder = ViewBag.BrandSortParam })
            </th>
            <th>
               @Html.ActionLink("Dyscyplina", "Index", new { sortOrder = ViewBag.DisciplineSortParm })
            </th>
            <th>
                @Html.ActionLink("Miesiąc", "Index", new { sortOrder = ViewBag.MonthSortParm })
            </th>
            <th>
                @Html.ActionLink("Liczba ekspozycji", "Index", new { sortOrder = ViewBag.QuantitySortParm })
            </th>
            <th>
                @Html.ActionLink("Ekwiwalent reklamowy", "Index", new { sortOrder = ViewBag.ValueSortParm })
            </th>
        </tr>
    </table>
}
@Html.Partial("_Table",Model)

then in controller I have

   public ActionResult Index(IEnumerable<string> brands, IEnumerable<string> disciplines,
        IEnumerable<string> months,string sortOrder)
    {
        ViewBag.BrandSortParam = String.IsNullOrEmpty(sortOrder) ? "brand_desc" : "";

        ViewBag.DisciplineSortParm = sortOrder == "discipline" ? "discipline_desc" : "discipline";

        ViewBag.MonthSortParm = sortOrder == "month" ? "month_desc" : "month";

        ViewBag.QuantitySortParm = sortOrder == "quantity" ? "quantity_desc" : "quantity";

        ViewBag.ValueSortParm = sortOrder == "value" ? "value_desc" : "value";


        model.ExposureRecords = FilterExposure(brands, disciplines, months);
        model.ExposureRecords = Sort(sortOrder, model.ExposureRecords);
        if (Request.IsAjaxRequest())
            return PartialView("_Table", model);
        return View(model);
    }

Upvotes: 1

Views: 2458

Answers (1)

wooters
wooters

Reputation: 977

My suggestion would be to use a client-side library. Sorting can be done in the controller, but in my experience, it is usually painful. I recently did what you're looking to accomplish in a project using sorttable.js, although there are several options to choose from (see Porschiey's comment above).

To use sortable, add the "sortable" class to your table. Also, be sure to run the "makesortable" js using the OnComplete property in your ajax.beginform ajaxoptions, that way the table will sort after an ajax call. Like this:

@using (Ajax.BeginForm(new AjaxOptions() {HttpMethod = "get", InsertionMode = InsertionMode.Replace, UpdateTargetId = "exposureRecords", OnComplete="makesortable"}))
{
...
}

function makesortable() {
sorttable.makeSortable(document.getElementById('exposureRecords'));
};

Upvotes: 2

Related Questions