Saturday, 23 January 2016

MVC - Sorting and filtering by each column - add drop down list to the header

Watch this example on YouTube:
1. create new MVC project
2. add Entity Model to it with 1 table - here is my simple table




3. Rebuild project
4. Add controller
5. Change route config to the new controller, run project to test
6. modify header in Index file, add html.actionlinks to it
@model IEnumerable<MVCSortAndFilter.Models.Employee>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    @using (Html.BeginForm("Index", "Employee", FormMethod.Get))
    {
        <tr>
            <th>
                @Html.ActionLink("First Name", "Index",
                new { SortOrder =ViewBag.FirstName})
            </th>
            <th>
                @Html.ActionLink("Last Name", "Index",
                new { SortOrder = ViewBag.LastName})
            </th>
            <th></th>
        </tr>
7. Modify controller index, ensure it looks like this
        public ActionResult Index(string SortOrder, string SelectedFirstName, string SelectedLastName)
        {
            ViewBag.FirstName = String.IsNullOrEmpty(SortOrder) ? "FirstName_desc" : "";
            ViewBag.LastName = SortOrder == "LastName" ? "LastName_desc" : "LastName";

            var emp = from s in db.Employees
                      select s;

            switch (SortOrder)
            {
                case "FirstName_desc" :
                    emp = emp.OrderByDescending(s => s.FirstName);
                    break;
                case "LastName":
                    emp = emp.OrderBy(s => s.LastName);
                    break;
                case "LastName_desc":
                    emp = emp.OrderByDescending(s => s.LastName);
                    break;
                default:
                    emp = emp.OrderBy(s => s.FirstName);
                    break;
            }

            return View(emp.ToList());
        }

8. Now we have sorting completed.  Run the project to test
Now - let's add filtering
Ensure Index view looks like this:
@model IEnumerable<MVCSortAndFilter.Models.Employee>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    @using (Html.BeginForm("Index", "Employee", FormMethod.Get))
    {
        <tr>
            <th>
                @Html.ActionLink("First Name", "Index",
                new { SortOrder =ViewBag.FirstName,
                    SelectedFirstName = ViewBag.SelectedFirstName, SelectedLastName = ViewBag.SelectedLastName})
            </th>
            <th>
                @Html.ActionLink("Last Name", "Index",
                new { SortOrder = ViewBag.LastName,
                      SelectedFirstName = ViewBag.SelectedFirstName,
                      SelectedLastName = ViewBag.SelectedLastName
                })
            </th>
            <th></th>
        </tr>
        <tr>
            <th>
                @Html.DropDownList("SelectedFirstName",
                new SelectList(ViewBag.UniqueFirstNames, "Value", "Text", "ViewBag.SelectedFirstName"),
                "All", new {onchange = "form.submit();"})
            </th>
            <th>
                @Html.DropDownList("SelectedLastName",
                new SelectList(ViewBag.UniqueLastNames, "Value", "Text", "ViewBag.SelectedLastName"),
             "All", new { onchange = "form.submit();"})
            </th>
        </tr>
    }


@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.FirstName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.LastName)
        </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>
}

</table>
9. Modify controller, ensure it looks like this:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MVCSortAndFilter.Models;

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

        //
        // GET: /Employee/

        public ActionResult Index(string SortOrder, string SelectedFirstName, string SelectedLastName)
        {
            ViewBag.FirstName = String.IsNullOrEmpty(SortOrder) ? "FirstName_desc" : "";
            ViewBag.LastName = SortOrder == "LastName" ? "LastName_desc" : "LastName";

            var rawData = (from s in db.Employees
                           select s).ToList();
            var emp = from s in rawData
                      select s;

            if (!String.IsNullOrEmpty(SelectedFirstName))
            {
                emp = emp.Where(s => s.FirstName.Trim().Equals(SelectedFirstName.Trim()));
            }
            if (!String.IsNullOrEmpty(SelectedLastName))
            {
                emp = emp.Where(s => s.LastName.Trim().Equals(SelectedLastName.Trim()));
            }

            var UniqueFirstNames = from s in emp
                                   group s by s.FirstName into newGroup
                                   where newGroup.Key != null
                                   orderby newGroup.Key
                                   select new { FirstName = newGroup.Key };
            ViewBag.UniqueFirstNames = UniqueFirstNames.Select(m => new SelectListItem { Value = m.FirstName, Text = m.FirstName }).ToList();

            var UniqueLastNames = from s in emp
                                  group s by s.LastName into newGroup
                                  where newGroup.Key != null
                                  orderby newGroup.Key
                                  select new { LastName = newGroup.Key };
            ViewBag.UniqueLastNames = UniqueLastNames.Select(m => new SelectListItem { Value = m.LastName, Text = m.LastName }).ToList();

            ViewBag.SelectedFirstName = SelectedFirstName;
            ViewBag.SelectedLastName = SelectedLastName;

            switch (SortOrder)
            {
                case "FirstName_desc" :
                    emp = emp.OrderByDescending(s => s.FirstName);
                    break;
                case "LastName":
                    emp = emp.OrderBy(s => s.LastName);
                    break;
                case "LastName_desc":
                    emp = emp.OrderByDescending(s => s.LastName);
                    break;
                default:
                    emp = emp.OrderBy(s => s.FirstName);
                    break;
            }

            return View(emp.ToList());
        }

        //
        // GET: /Employee/Details/5

        public ActionResult Details(int id = 0)
        {
            Employee employee = db.Employees.Find(id);
            if (employee == null)
            {
                return HttpNotFound();
            }
            return View(employee);
        }

        //
        // GET: /Employee/Create

        public ActionResult Create()
        {
            return View();
        }

        //
        // POST: /Employee/Create

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(Employee employee)
        {
            if (ModelState.IsValid)
            {
                db.Employees.Add(employee);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(employee);
        }

        //
        // GET: /Employee/Edit/5

        public ActionResult Edit(int id = 0)
        {
            Employee employee = db.Employees.Find(id);
            if (employee == null)
            {
                return HttpNotFound();
            }
            return View(employee);
        }

        //
        // POST: /Employee/Edit/5

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(Employee employee)
        {
            if (ModelState.IsValid)
            {
                db.Entry(employee).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(employee);
        }

        //
        // GET: /Employee/Delete/5

        public ActionResult Delete(int id = 0)
        {
            Employee employee = db.Employees.Find(id);
            if (employee == null)
            {
                return HttpNotFound();
            }
            return View(employee);
        }

        //
        // POST: /Employee/Delete/5

        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Employee employee = db.Employees.Find(id);
            db.Employees.Remove(employee);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}

Run to test

1 comment:

  1. Last combobox parameter doesn`t have delimiters (ViewBag.SelectedFirstName instead of "ViewBag.SelectedFirstName").

    ReplyDelete