Grid nesting demo

The awesome grid can have multiple nests, an url or js func can be specified for loading the nest content.
When using url the Key of the grid is sent as "Key" parameter to the url.
The class of the html element that will act as a toggle button for the nest needs to be specified, that element will get the awe-on class additionally while its nest is open. Opening a nest will close other nests that are open for the same row.

Master detail grid

Using one nest with url to achieve a master detail grid view

using grid api to open, close and toggle open nest for the first row:

GridNestingDemo.aspx
<% MasterDetailGrid.Grid()
.Columns(
new Column { ClientFormat = "<div class='detailnst'><i class='caretc'><i class='o-caret'></i></i> .(Id)</div>", Width = 100, Header = "Id" },
new Column { Bind = "Person" },
new Column { Bind = "Food.Name" },
new Column { Bind = "Location" })
.Url(Page.Url().Action("GetItems", "LunchGrid"))
.PageSize(5)
.Height(300)
.Nests(new Nest { Name = "detailnst", Url = Page.Url().Action("LunchDetail", "GridNestingDemo"), LoadOnce = true }); %>
<awe:Ocon runat="server" ID="MasterDetailGrid" />
<br/>
<p>
using grid api to open, close and toggle open nest for the first row:
</p>
<button type="button" class="awe-btn" id="btnOpenNest">Open nest</button>
<button type="button" class="awe-btn" id="btnCloseNest">Close nest </button>
<button type="button" class="awe-btn" id="btnToggleNest">Toggle nest</button>

<script>
$(function () {
var grid = $('#<%=MasterDetailGrid.ClientID %>');
var api = grid.data('api');

$('#btnToggleNest').click(function () {
api.nestToggle(grid.find('.awe-row:first'), 'detailnst');
});

$('#btnOpenNest').click(function () {
api.nestOpen(grid.find('.awe-row:first'), 'detailnst');
});

$('#btnCloseNest').click(function () {
api.nestClose(grid.find('.awe-row:first'), 'detailnst');
});
});
</script>

<style>
.detailnst {
cursor: pointer;
}

.caretc {
position: relative;
padding: 0 .7em;
margin-right: .5em;
}

.caretc .o-caret {
transform: rotate(-90deg);
zoom: 1.1;
}

.detailnst-on .caretc .o-caret {
transform: rotate(-45deg);
}
</style>
Awesome/Grid/LunchGridController.cs
using System;
using System.Linq;
using AwesomeWebFormsDemo.Data;
using AwesomeWebFormsDemo.Models;
using AwesomeWebFormsDemo.Utils.Awesome;
using System.Web.Mvc;


using Omu.AwesomeWebForms;

namespace AwesomeWebFormsDemo.Controllers.Awesome.Grid
{
public class LunchGridController : Controller
{
public ActionResult GetItems(GridParams g, int? country, string person, string food)
{
var query = Db.Lunches.AsQueryable();

// filtering
if (person != null) query = query.Where(o => o.Person.ToLower().Contains(person.ToLower()));
if (food != null) query = query.Where(o => o.Food.Name.ToLower().Contains(food.ToLower()));
if (country.HasValue) query = query.Where(o => o.Country.Id == country);

// data can be from any source as long here you pass an IQueryable<T>
var gmb = new GridModelBuilder<Lunch>(query.AsQueryable(), g);

// define grid key, used to identify rows
gmb.KeyProp = o => o.Id;

// grid row model
// columns bound to Prop1.Prop2 will automatically display Prop1Prop2,
// or you could specify in the view Column.Prop ="Prop1Prop2", or ClientFormat = ".(Prop1Prop2)"
gmb.Map = o => new
{
o.Id,
o.Person,
FoodName = o.Food.Name,
FoodPic = o.Food.Pic,
o.Location,
o.Price,
Date = o.Date.ToShortDateString(),
CountryName = o.Country.Name,
ChefName = o.Chef.FullName
};

return Json(gmb.Build());
}

public ActionResult GetItemsEFExample(GridParams g, int? country, string person, string food)
{
var query = Db.Lunches.AsQueryable();

// Filter - custom extension in demo code
// equivalent to .Where(o => o.Food.Name.Contains(food) || ...)

query = query
.Filter(food, o => o.Food.Name)
.Filter(person, o => o.Person);

if (country.HasValue) query = query.Where(o => o.Country.Id == country);

var gmb = new GridModelBuilder<Lunch>(query, g);
gmb.KeyProp = o => o.Id;
gmb.Map = o => new
{
o.Id,
o.Person,
FoodName = o.Food.Name,
FoodPic = o.Food.Pic,
o.Location,
o.Price,
Date = o.Date.ToShortDateString(),
CountryName = o.Country.Name,
ChefName = o.Chef.FullName
};

return Json(gmb.Build());
}
}
}
Demos/Grid/GridNestingDemoController.cs
public ActionResult LunchDetail(int key)
{
var lunch = Db.Get<Lunch>(key);
return PartialView(lunch);
}
\Views\GridNestingDemo/LunchDetail.cshtml
@model AwesomeWebFormsDemo.Models.Lunch
<div style="padding:0.2em 2em;">
@Model.Person had @Model.Food.Name at @Model.Location in @Model.Country.Name<br/>
View loaded from server at: @DateTime.UtcNow UTC
</div>

Nested grids / Hierarchical grid

the url of the nest points to an action that will render another grid, it also receives the key of the row (Id) as a parameter to filter it's content
GridNestingDemo.aspx
<% CategoriesGrid.Grid()
.Resizable()
.Url(Page.Url().Action("CategoriesGrid", "Data"))
.Columns(new Column { Bind = "Name", ClientFormat = "<div class='detailnst'><i class='caretc'><i class='o-caret'></i></i> .(Name)</div> " })
.Nests(new Nest { Name = "detailnst", Url = Page.Url().Action("MealGrid", "GridNestingDemo"), LoadOnce = true }); %>
<awe:Ocon runat="server" ID="CategoriesGrid" />
Demos/Grid/GridNestingDemoController.cs
public ActionResult MealGrid(int key)
{
ViewData["Id"] = key;
return PartialView();
}
\Views\GridNestingDemo/MealGrid.cshtml
<div style="margin: 5px;">
@(Html.Awe().Grid("MealsGrid" + ViewData["Id"]) // please note, you need to have unique html ids
.Url(Url.Action("ChildMealsGrid", "Data"))
.Columns(
new Column { Bind = "Id", Width = 50 },
new Column { Bind = "Name", Width = 150 },
new Column { Bind = "Description" })
.Resizable()
.Parameter("categories", ViewData["Id"]))
</div>
Awesome/DataController.cs
public ActionResult CategoriesGrid(GridParams g)
{
return Json(new GridModelBuilder<Category>(Db.Categories.AsQueryable(), g)
{
Key = "Id"
}.Build());
}

public ActionResult ChildMealsGrid(GridParams g, int[] categories)
{
categories = categories ?? new int[] { };

return Json(new GridModelBuilder<Meal>(Db.Meals
.Where(o => categories.Contains(o.Category.Id)).AsQueryable(), g).Build());
}



Comments