I'm working on an Asp MVC application that contains a grid of data that I want to filter with a checkboxlist. I want to be able to filter my data from one or more selections. For the moment it works only from one selection. I use link expression to filter my data. I would like to have the following equivalent in sql :
select * from mission_supportmission where decision in (item1, item2..)
My view looks like this:
<div class="wrapper">
<nav id="sidebar">
@using (Html.BeginForm("Index", "Missions", FormMethod.Get))
{
@Html.EditorFor(x => x.Decision)
}
</nav>
<div id="content" class="container">
<table class="table table-bordered">
<tr>
<th class="col-md-2">
Decision
</th>
</tr>
@foreach (var item in Model.OnePageOfMissions)
{
<tr>
<td class="col-md-1">
@Html.DisplayFor(modelItem => item.decision)
</td>
</tr>
}
@Html.PagedListPager((IPagedList)Model.OnePageOfMissions, page => Url.Action("Index", new { page, Decision = Model.Decision}))
</table>
</div>
I created a template to display checkboxlist like this:
<div class="form-check row">
@Html.HiddenFor(x => x.ID)
@Html.CheckBoxFor(x => x.IsChecked, htmlAttributes: new { onchange = "form.submit();", @class = "form-check-input col-md-2" })
@Html.LabelFor(x => x.Display, Model.Display, htmlAttributes: new { @class = "form-check-label col-md-8" })
My controller looks like this:
public ActionResult Index(int? page, List<CheckBoxListItem> Decision)
{
IndexViewModel model = new IndexViewModel();
//Display Missions
model.missionsList = db.missions_supportmission.ToList();
//Retrieve parameters
model.Decision = Decision;
//PagedList
var pageNumber = page ?? 1; // if no page was specified in the querystring, default to the first page (1)
var onePageOfMissions = model.missionsList.ToPagedList(pageNumber, 10); // will only contain 10 products max because of the pageSize(equel to 10)
model.OnePageOfMissions = onePageOfMissions;
//Filter
if (model.Decision != null)
{
var selecteddecision = model.Decision.Where(x => x.IsChecked).Select(x => x.ID);
foreach (var item in selecteddecision)
{
model.OnePageOfMissions = db.missions_supportmission
.Where(a => a.decision.Contains(item))
.OrderBy(a => a.id)
.Select(s => s).ToPagedList(pageNumber, 10);
}
}
//Display CheckBox
//Checkboxlist (!important => mettre ce bloc de code après la requête link qui permet de filtrer sur les checkbox)
var allDecisions = db.list_decision.ToList();//returns List<list_decision>
var checkBoxListItems = new List<CheckBoxListItem>(); //nouvelle instance de la classe checkboxlist
model.Decision = checkBoxListItems;
foreach (var decison in allDecisions)
{//On assigne les valeurs "id", "display" et "is checked" à la variable checkboxlistitem
checkBoxListItems.Add(new CheckBoxListItem()
{
ID = decison.decision_id,
Display = decison.name_en,
IsChecked = false //On the add view, no decision are selected by default
});
}
return View(model);
}
I have also a ViewModel:
namespace MissionsDF.Models
{
public class IndexViewModel
{
public IEnumerable<missions_supportmission> missionsList { get; set; }
public List<CheckBoxListItem> Decision { get; set; }
public IndexViewModel()
{
this.Decision = new List<CheckBoxListItem>();
}
public IPagedList<missions_supportmission> OnePageOfMissions { get; set; }
public bool IsChecked;
}
}
//Filter
if (model.Decision != null)
{
var selecteddecision = model.Decision.Where(x => x.IsChecked).Select(x => x.ID);
model.OnePageOfMissions = (from m in db.missions_supportmission
join l in db.list_decision
on m.missionID equals l.missionID
where selecteddecision.Contains(l.decisionID)
select m)
.OrderBy(a => a.id)
.ToPagedList(pageNumber, 10);
}
Without any information of data structure on objects, this is my best approach to a solution.