Wednesday, 18 May 2016

MVC - Sorting Paging Filtering using ViewModel (not ViewBag)

watch this example on YouTube


SortAndPage class
namespace MvcSortAndFilterAndPage.Models
{
    public class SortAndPage
    {
        public string SortField { get; set; }
        public string SortDirection { get; set; }
        public int PageSize { get; set; }
        public int PageCount { get; set; }
        public int CurrentPageIndex { get; set; }
    }
}
Customer Custom class
namespace MvcSortAndFilterAndPage.Models
{
    public class CustomerCustom :SortAndPage
    {
        public IEnumerable<Customers2> cust { get; set; }
        public IEnumerable<Customers2> custDDL { get; set; }
        public string SelectedFirstName { get; set; }
        public string SelectedLastName { get; set; }
    }
}

add the following to _layout.cshtml 
        @Scripts.Render("~/Scripts/jquery-1.8.2.min.js")
        @Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.js")
    </head>

Here is modified part of CustomerController
using MvcSortAndFilterAndPage.Models;

namespace MvcSortAndFilterAndPage.Controllers
{
    public class CustomerController : Controller
    {
        private TESTEntities db = new TESTEntities();

        //
        // GET: /Customer/

        public ActionResult Index(CustomerCustom model = null)
        {
            int i;
            if (model != null)
            {
                i = model.CurrentPageIndex;
            }
            model = new CustomerCustom
            {
                cust = db.Customers2.ToList(),
                custDDL = db.Customers2.ToList()
            };
            var res = (from s in model.cust
                       select s);
            res = res.ToList();
            if (model.CurrentPageIndex == 0)
            {
                model.CurrentPageIndex = 0;
            }
            model.PageSize = 2;
            model.PageCount = ((res.Count() + model.PageSize - 1) / model.PageSize);
            if (model.CurrentPageIndex > model.PageCount)
            {
                model.CurrentPageIndex = model.PageCount;
            }
            model.cust = res.Skip(model.CurrentPageIndex * model.PageSize).Take(model.PageSize);



            return View(model);
        }

        [HttpPost]
        public ActionResult Index(CustomerCustom model, string btn = null){
            if (model.SortField == null){
                model.SortField = "CustomerFirstName";
                model.SortDirection = "ascending";
            }
            #region SortData

            switch(model.SortField){
                case "CustomerFirstName":
                    model.cust = (model.SortDirection == "ascending" ?
                        db.Customers2.OrderBy(c => c.CustomerFirstName):
                        db.Customers2.OrderByDescending(c => c.CustomerFirstName));
                    break;
                case "CustomerLastName":
                    model.cust = (model.SortDirection == "ascending" ?
                        db.Customers2.OrderBy(c => c.CustomerLastName):
                        db.Customers2.OrderByDescending(c => c.CustomerLastName));
                    break;
            }
               
            #endregion

            var ddl = (from d in model.cust
                       select d);
            model.custDDL = ddl;

            #region FilterData

            if (!String.IsNullOrEmpty(model.SelectedFirstName))
            {
                model.cust = model.cust.Where(s => s.CustomerFirstName.ToString().Trim().Equals(model.SelectedFirstName.Trim()));
            }
            if(!String.IsNullOrEmpty(model.SelectedLastName))
            {
                model.cust = model.cust.Where(s => s.CustomerLastName.ToString().Trim().Equals(model.SelectedLastName.Trim()));
            }

            #endregion

            var res = (from s in model.cust
                           select s);
            res = res.ToList();
            if(model.CurrentPageIndex == 0){
                model.CurrentPageIndex = 0;
            }
            model.PageSize =2;
            model.PageCount = ((res.Count() + model.PageSize - 1) / model.PageSize);
            if(model.CurrentPageIndex > model.PageCount){
                model.CurrentPageIndex = model.PageCount;
            }
            model.cust = res.Skip(model.CurrentPageIndex * model.PageSize).Take(model.PageSize);
            return View(model);
        }
View(Index.cshtml) will look like this:
@model MvcSortAndFilterAndPage.Models.CustomerCustom

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>

@using (Html.BeginForm(null, null, FormMethod.Post))
{
    @Html.AntiForgeryToken()
    @Html.Hidden("SortField", Model.SortField)
    @Html.Hidden("SortDirection", Model.SortDirection)
    @Html.Hidden("PageCount", Model.PageCount)
    @Html.Hidden("PageSize", Model.PageSize)
    @Html.Hidden("CurrentPageIndex", Model.CurrentPageIndex)
   
    @Html.Hidden("SelectedFirstName", Model.SelectedFirstName)
    @Html.Hidden("SelectedLastName", Model.SelectedLastName)


<table>
    <tr>
        <th>
            <a href="#" data-sortfield="CustomerFirstName" class="header">@Html.DisplayNameFor(model => model.cust.First().CustomerFirstName)</a>
        </th>
        <th>
            <a href="#" data-sortfield="CustomerLastName" class="header">@Html.DisplayNameFor(model => model.cust.First().CustomerLastName)</a>
        </th>
        <th></th>
    </tr>
    <tr>
        <th>
            @Html.DropDownListFor(model => model.SelectedFirstName,
            new SelectList(Model.custDDL, "CustomerFirstName", "CustomerFirstName", Model.SelectedFirstName), "All", new  {@id = "fn" })
        </th>
        <th>
            @Html.DropDownListFor(model => model.SelectedLastName,
            new SelectList(Model.custDDL, "CustomerLastName", "CustomerFirstName", Model.SelectedLastName), "All", new { @id = "ln" })
        </th>

    </tr>

@foreach (var item in Model.cust) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.CustomerFirstName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.CustomerLastName)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
        </td>
    </tr>
}

    <tr>
        <td colspan="4">
            @for (var i = 0; i < Model.PageCount; i++)
            {
                if (i == Model.CurrentPageIndex)
                {
                    <span class="current-pager" id="CurrentPageIndex">@(i + 1)</span>
                }
                else
                {
                    <a href="#" data-pageindex="@i" class="pager">@(i + 1)</a>
                }
            }
        </td>
    </tr>

</table>
   
}
<script type="text/javascript">
    $(document).ready(function () {
        $(".header").click(function (evt) {       
            var sortfield = $(evt.target).data("sortfield");
            if ($("#SortField").val() == sortfield) {
                if ($("#SortDirection").val() == "ascending") {
                    $("#SortDirection").val("descending");
                }
                else{
                    $("#SortDirection").val("ascending");
                }
            }
            else {
                $("#SortField").val(sortfield);
                $("#SortDirection").val("ascending");
            }
            evt.preventDefault();
            $("form").submit();
           
        });

        $(".pager").click(function (evt) {
            var pageindex = $(evt.target).data("pageindex");
            $("#CurrentPageIndex").val(pageindex);
            evt.preventDefault();
            $("form").submit();
        });

        $("#fn").change(function (evt) {
            $("#SelectedFirstName").val($("#fn").val().trim());
            evt.preventDefault();
            $("form").submit();
        })
        $("#ln").change(function (evt) {
            $("#SelectedLastName").val($("#ln").val().trim());
            evt.preventDefault();
            $("form").submit();
        })
    });
</script>

1 comment:

  1. Wonderful tutorial. Is there an easy way to pass the filters and sorting when the user clicks edit or details and then returns to the index page?

    ReplyDelete