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
GridNestingDemo/Index.cshtml
@(Html.Awe().Grid("MasterDetailGrid")
.Columns(
new Column { ClientFormat = "<div class='detailbtn'><i class='ui-icon ui-icon-triangle-1-e awe-il'></i> .Id</div>", Width = 100, Header = "Id" },
new Column { Bind = "Person" },
new Column { Bind = "Food" },
new Column { Bind = "Location" }
)
.Url(Url.Action("GetItems", "LunchGrid"))
.Nests(new Nest { ButtonClass = "detailbtn", Url = Url.Action("LunchDetail"), LoadOnce = true }))
<style>
.detailbtn {
vertical-align: middle;
border: none;
background-color: transparent;
outline: none;
cursor: pointer;
margin-left: -5px;
padding-left: 5px;
}

.detailbtn .ui-icon {
vertical-align: middle;
}

.detailbtn.awe-on i {
background-position: -48px -16px;
}
</style>
Awesome/Grid/LunchGridController.cs
public class LunchGridController : Controller
{
public ActionResult GetItems(GridParams g, string person, string food, int? country)
{
food = (food ?? "").ToLower();
person = (person ?? "").ToLower();

var list = Db.Lunches
.Where(o => o.Food.ToLower().Contains(food) && o.Person.ToLower().Contains(person))
.AsQueryable();

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

return Json(new GridModelBuilder<Lunch>(list, g)
{
Key = "Id", // needed for Entity Framework | nesting | tree | api
Map = o => new
{
o.Id,
o.Person,
o.Food,
o.Location,
o.Price,
Date = o.Date.ToShortDateString(),
CountryName = o.Country.Name,
ChefName = o.Chef.FirstName + " " + o.Chef.LastName
}
}.Build());
}
}
Demos/Grid/GridNestingDemoController.cs
public ActionResult LunchDetail(int key)
{
var lunch = Db.Get<Lunch>(key);
return PartialView(lunch);
}
GridNestingDemo/LunchDetail.cshtml
@model AwesomeMvcDemo.Models.Lunch
<div style="padding:0.2em 2em;">
@Model.Person had @Model.Food at @Model.Location in @Model.Country.Name<br/>
View loaded from server at: @DateTime.UtcNow UTC
</div>

Nested grids / Hierarchy

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/Index.cshtml
@(Html.Awe().Grid("CategoriesGrid")
.Groupable(true)
.Resizable(true)
.Url(Url.Action("CategoriesGrid", "CascadingGridDemo"))
.Columns(new Column { Bind = "Name", ClientFormat = "<div class='detailbtn'><i class='ui-icon ui-icon-triangle-1-e awe-il'></i> .Name</div> " })
.Nests(new Nest { ButtonClass = "detailbtn", Url = Url.Action("MealGrid"), LoadOnce = true }))
Demos/Grid/GridNestingDemoController.cs
public ActionResult MealGrid(int key)
{
ViewData["Id"] = key;
return PartialView();
}
GridNestingDemo/MealGrid.cshtml
<div style="margin: 5px;">
@(Html.Awe().Grid("MealsGrid" + ViewData["Id"]) // please note, you need to have unique html ids
.Groupable(true)
.Url(Url.Action("MealsGrid", "CascadingGridDemo"))
.Columns(
new Column { Bind = "Id", Width = 50 },
new Column { Bind = "Name", Width = 150 },
new Column { Bind = "Description" })
.PersistenceKey("MealsCascade")
.ColumnsPersistence(Persistence.View)
.Resizable(true)
.Parameter("categories", ViewData["Id"]))
</div>

Demos/Grid/CascadingGridDemoController.cs
public ActionResult CategoriesGrid(GridParams g)
{
return Json(new GridModelBuilder<Category>(Db.Categories.AsQueryable(), g)
{
Key = "Id"
}.Build());
}

public ActionResult MealsGrid(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());
}

In nest editing grid

Combining the PopupForm, inline popup, and grid nesting to achieve in nest editing. We have 2 nests, both with js functions specified for loading the content, the js func uses the popup api to load the content inside the nest and binds to the popups aweclose event so that the nest will close when the popup closes. All the popups are in the same group so opening a create popup will close other edit/delete popups etc.
GridNestingDemo/Index.cshtml
@Html.InitCrudForGridNest("NestDinnersGrid", "DinnersGridCrud")

<div class="bar">
<button type="button" onclick="utils.nestCreate('NestDinnersGrid', 'createNestDinnersGrid')" class="awe-btn mbtn">Create</button>
</div>

@(Html.Awe().Grid("NestDinnersGrid")
.Url(Url.Action("GridGetItems", "DinnersGridCrud"))
.Mod(o => o.ColumnsAutohide())
.Height(0)
.PageSize(10)
.Nests(
new Nest { ButtonClass = "editnst", GetFunc = "utils.loadNestPopup('editNestDinnersGrid')" },
new Nest { ButtonClass = "delnst", GetFunc = "utils.loadNestPopup('deleteNestDinnersGrid')" })
.Columns(
new Column { Bind = "Id", Width = 70 },
new Column { Bind = "Name" }.Mod(o => o.NoAutohide()),
new Column { Bind = "Date" },
new Column { Bind = "Chef.FirstName,Chef.LastName", ClientFormat = ".ChefName", Header = "Chef" },
new Column { ClientFormat = ".Meals", Header = "Meals" },
new Column { ClientFormat = GridUtils.EditGridNestFormat(), Width = 50 }.Mod(o => o.Nohide()),
new Column { ClientFormat = GridUtils.DeleteGridNestFormat(), Width = 50 }.Mod(o => o.Nohide())))

@*utils.loadNestPopup is using the inlinePopup and needs utils.init to be called ( called in _Layout.cshtml )*@
<style>
.awe-btn.awe-on {
outline: gray auto 5px;
}
</style>