Grid Filtering Misc

Grid outside filter row and custom render


Grid auto filters placed outside the grid.

Using the AutoFilter() extension method on the controls, so that their names and values are automatically added to the grid filter model, and handled automatically in the GridModelBuilder, no custom filtering logic required.
The OutsideFilter("#outfrow") method is used to specify the container of the filters.
We can also get data from the Grid Model, as we do as an example in the Date filter where we get the years from the grid model.
Additionally there is filter persistence, so after page refresh the grid will have the same filters applied.
And there's a custom item render mod applied so you can switch between cards view and rows.
Shared/Demos/GridFilterOutside.cshtml
@{
var pref = "frowOut";
var gridId = "GridFrowOut";
}
<div id="outfrow" class="o-flex o-flex-wrap o-gap-2 o-pb-2 o-items-end">
@*context will add a prefix to all awesome editors html ids*@
@using (Html.Awe().BeginContext(pref))
{
@*html input name matches filter rule name*@
<label class="o-flex o-flex-col">
Name<br />
@Html.Awe().TextBox(new TextBoxOpt {
Name = nameof(Dinner.Name),
ClearBtn = true,
Placeholder = "name"
}
.AutoFilter())
</label>
<label class="o-flex o-flex-col">
Chef<br />
@Html.Awe().DropdownList(new DropdownListOpt {
Name = "Chef.Id",
ClearBtn = true,
Url = Url.Action("GetChefs","Data")
}
.AutoFilter())
</label>
<label class="o-flex o-flex-col">
Year<br />
@Html.Awe().DropdownList(new DropdownListOpt {
Name = "Date.Year",
ClearBtn = true,
DataFunc = $"awe.filterData('Date', '#{gridId}')"
}.AutoFilter())
</label>
<label class="o-flex o-flex-col">
Meals<br />
@(Html.Awe().Multicheck(new MulticheckOpt
{
Name = nameof(Dinner.Meals),
ClearBtn = true,
Url = Url.Action("GetAllMeals", "Data")
}
.AutoFilter()))
</label>
<label class="o-flex o-flex-col">
Organic<br />
@Html.Awe().DropdownList(new DropdownListOpt {
Name = nameof(Dinner.Organic),
ClearBtn = true,
DataFunc = "awe.boolValData"
}.AutoFilter())
</label>

<label class="o-flex o-flex-col">
<button type="button" id="btnClearFilter" class="awe-btn">Clear filters
@MyAweIcons.ReloadIco()
</button>
</label>
}
<label class="o-nonflt o-flex o-flex-col">
Show items as:
@Html.Awe().Toggle(new ToggleOpt{ Name = "itemsType", No = "Rows", Yes = "Cards", Width = "7em" })
</label>
</div>

@(Html.Awex().Grid<Dinner>(gridId)
.Main()
.Url(Url.Action("DinnersFilterGrid", "GridFilterRowServerSideData"))
.Persistence(Persistence.Session)
.Height(350)
.OutsideFilter("#outfrow")
.Columns(b =>
{
b.Add(o => o.Id, new Column { Width = 75 });
b.Add(o => o.Name);
b.Add(o => new { o.Chef.FirstName, o.Chef.LastName }, new Column { Header = "Chef" });
b.Add(o => o.Date);
b.Add(o => o.Meals.Select(m => m.Name), new Column { MinWidth = 200, Grow = 2 });
b.Add(o => o.Organic);
}))
<script>
$(function () {
let grid = $('#@gridId');
$('#btnClearFilter').on('click', () => grid.data('api').outsideFilterClear());

// rows/cards render switch
$('#itemsType').on('change', function () {
awe.use({
useType: 'gridSwitchView',
o: grid.data('o'),
cards: $(this).val() === 'true'
});
});
});
</script>
Demos/Grid/GridFilterRowServerSideDataController.cs
public IActionResult DinnersFilterGrid(GridParams g)
{
var query = Db.Dinners.AsQueryable();

var yearsList = new List<KeyContent>
{
new KeyContent("", "all years")
};

var years = query.Select(o => o.Date.Year).Distinct().ToArray().OrderBy(o => o);
yearsList.AddRange(AweUtil.ToKeyContent(years));

var gmb = new GridModelBuilder<Dinner>(query, g)
{
KeyProp = o => o.Id
};

gmb.Tag = new
{
frow = new
{
Date = yearsList.ToArray()
}
};

gmb.Prop(o => o.Organic, render: o => o ? "Yes" : "No");

gmb.FilterCfgForCollection(o => o.Meals, nameof(Meal.Id));

return this.AweJson(gmb.Build());
}

Filter by all columns, client data

  you can search multiple columns at the same time (try 'pizza tavern')

Filtering by multiple columns at once from one textbox, you can type multiple keywords separated by space and the grid will get filtered.
The grid data is loaded once from the server after it is stored in the 'lunches' variable. The function defined in DataFunc can either return the grid model or a promise which will return the grid model later, and in this case on the first load we return a promise ($.get).
GridDemo/Filtering.cshtml
<div class="bar">
@Html.Awe().TextBox("txtsearch").Placeholder("search ...").CssClass("searchtxt")
<span class="hint">&nbsp; you can search multiple columns at the same time (try 'pizza tavern')</span>
</div>

@(Html.Awe().Grid("GridClientData")
.DataFunc("loadGridClientData")
.Height(350)
.Main()
.Resizable()
.Reorderable()
.Parent("txtsearch", "search", false)
.Columns(
new Column { Bind = "Id", Width = 75, Groupable = false, Resizable = false },
new Column { Bind = "Person" },
new Column { Bind = "DishName", Header = "Dish" },
new Column { Bind = "Location" },
new Column { Bind = "Date", Width = 120 },
new Column { Bind = "CountryName", Header = "Country" },
new Column { Bind = "ChefName", Header = "Chef" }))
<script>
function loadGridClientData(sgp) {
// cache storage used by this demo (cstorg.js), it will load data on first call
return $.when(cstorg.get('@Url.Action("GetLunches", "Data")')).then(function(lunches) {
return getGridClientData(sgp, lunches);
});
}

function getGridClientData(sgp, lunches) {
var where = awef.where, contains = awef.scont, loop = awef.loop;
var gp = aweUtils.getGridParams(sgp);
var list = lunches;

if (gp.search) {
var words = gp.search.toLowerCase().split(" ");

list = where(lunches, function (o) {
var matches = 0;
loop(words, function (w) {
if (contains(o.DishName, w) || contains(o.Person, w) || contains(o.Location, w) || contains(o.CountryName, w)
|| contains(o.DateStr, w)
|| contains(o.ChefName, w)) matches++;
});

return matches === words.length;
});
}

function map(o) { return { Id: o.Id, Person: o.Person, DishName: o.DishName, Location: o.Location,
Date: o.DateStr, CountryName: o.CountryName, ChefName: o.ChefName }; };

return aweUtils.gridModelBuilder(
{
key:"Id",
gp: gp,
items: list,
map:map,
// replace default group header value for Date column
getHeaderVal:{ Date: function(o){ return o.DateStr; } }
});
}

$(function() {
$('#txtsearch').keyup(function() {
$('#GridClientData').data('api').load();
});
});
</script>



Comments