Master Detail CRUD Demo using Grid and PopupForm

This is a demo for master detail CRUD using the Grid.
For master-detail grid see Master Detail Grid, or Hierarchy (Nested Grids)
MasterDetailCrudDemo/Index.cshtml
@Html.InitCrudPopupsForGrid("RestaurantGrid", "MasterDetailCrudDemo", 470, 1000)

<div class="bar">
<button type="button" class="awe-btn mbtn" onclick="awe.open('createRestaurantGrid')">Create</button>
</div>

@(Html.Awe().Grid("RestaurantGrid")
.Height(350)
.Attr("data-syncg", "rest") // crud sync using signalr in site.js
.Url(Url.Action("RestaurantGridGetItems"))
.Groupable(false)
.Columns(
new Column { ClientFormat = ".Id", Header = "Id", Width = 70 },
new Column { Bind = "Name" },
new Column { ClientFormat = GridUtils.EditFormatForGrid("RestaurantGrid"), Width = 50 },
new Column { ClientFormat = GridUtils.DeleteFormatForGrid("RestaurantGrid"), Width = 50 }))
MasterDetailCrudDemo/Create.cshtml
@model AwesomeMvcDemo.ViewModels.Input.RestaurantInput
@using (Html.Awe().BeginContext())
{
var gridId = "AddressesGrid";
using (Html.BeginForm())
{
@Html.EditorFor(o => o.Id)
@Html.EditorFor(o => o.Name)
}

@Html.InitCrudPopupsForGrid(gridId, "AddressesGridCrud", 230)

<div class="bar">
@Html.CreateButtonForGrid(gridId, new { restaurantId = Model.Id}, "Add address")
</div>
<div>
@(Html.Awe().Grid(gridId).Url(Url.Action("GridGetItems", "AddressesGridCrud"))
.Parameter("restaurantId", Model.Id)
.Attr("data-syncg","addr")
.Height(230)
.Groupable(false)
.Columns(
new Column { Bind = "Line1,Line2", ClientFormat = ".Line1 .Line2", Header = "Address" },
new Column { ClientFormat = Html.EditFormatForGrid(gridId), Width = 52 },
new Column { ClientFormat = Html.DeleteFormatForGrid(gridId), Width = 52 }))
</div>
}
AddressesGridCrud/Create.cshtml
@model AwesomeMvcDemo.ViewModels.Input.RestaurantAddressInput

@using (Html.BeginForm())
{
@Html.EditorFor(o => o.RestaurantId)
@Html.EditorFor(o => o.Line1)
@Html.EditorFor(o => o.Line2)
}
Demos/Grid/MasterDetailCrud/MasterDetailCrudDemoController.cs
using System;
using System.Linq;
using System.Web.Mvc;
using AwesomeMvcDemo.Models;
using AwesomeMvcDemo.ViewModels.Input;
using Omu.AwesomeMvc;

namespace AwesomeMvcDemo.Controllers.Demos.Grid.MasterDetailCrud
{
public class MasterDetailCrudDemoController : Controller
{
public ActionResult Index()
{
return View();
}

public ActionResult RestaurantGridGetItems(GridParams g)
{
var model = new GridModelBuilder<Restaurant>(Db.Restaurants.Where(o => o.IsCreated).AsQueryable(), g)
{
Key = "Id",
GetItem = () => Db.Get<Restaurant>(Convert.ToInt32(g.Key))
}.Build();
return Json(model);
}

public ActionResult Create()
{
// needed so we could add addresses even before the restaurant is created/saved
var rest = Db.Insert(new Restaurant());

return PartialView(new RestaurantInput { Id = rest.Id });
}

[HttpPost]
public ActionResult Create(RestaurantInput input)
{
if (!ModelState.IsValid)
{
return PartialView(input);
}

var restaurant = Db.Get<Restaurant>(input.Id);
restaurant.Name = input.Name;
restaurant.IsCreated = true;

return Json(restaurant); // use MapToGridModel like in Grid Crud Demo when grid uses Map
}

public ActionResult Edit(int id)
{
var rest = Db.Get<Restaurant>(id);
return PartialView("Create", new RestaurantInput { Id = id, Name = rest.Name });
}

[HttpPost]
public ActionResult Edit(RestaurantInput input)
{
if (!ModelState.IsValid)
{
return PartialView("Create", input);
}

var rest = Db.Get<Restaurant>(Convert.ToInt32(input.Id));

rest.Name = input.Name;

return Json(new { rest.Id });
}

public ActionResult Delete(int id, string gridId)
{
var restaurant = Db.Get<Restaurant>(id);

return PartialView(new DeleteConfirmInput
{
Id = id,
Message = string.Format("Are you sure you want to delete restaurant <b>{0}</b> ?", restaurant.Name)
});
}

[HttpPost]
public ActionResult Delete(DeleteConfirmInput input)
{
Db.Delete<Restaurant>(input.Id);
return Json(new { input.Id });
}
}
}
Demos/Grid/MasterDetailCrud/AddressesGridCrudController.cs
using System;
using System.Linq;
using System.Web.Mvc;
using AwesomeMvcDemo.Models;
using AwesomeMvcDemo.ViewModels.Input;
using Omu.AwesomeMvc;

namespace AwesomeMvcDemo.Controllers.Demos.Grid.MasterDetailCrud
{
public class AddressesGridCrudController : Controller
{
public ActionResult GridGetItems(GridParams g, int restaurantId)
{
var items = Db.RestaurantAddresses.Where(o => o.RestaurantId == restaurantId).AsQueryable();
var model = new GridModelBuilder<RestaurantAddress>(items, g)
{
Key = "Id",
GetItem = () => Db.Get<RestaurantAddress>(Convert.ToInt32(g.Key))
}.Build();
return Json(model);
}

public ActionResult Create(int restaurantId)
{
return PartialView(new RestaurantAddressInput { RestaurantId = restaurantId });
}

[HttpPost]
public ActionResult Create(RestaurantAddressInput input)
{
if (!ModelState.IsValid)
{
return PartialView(input);
}

var address = Db.Insert(new RestaurantAddress { Line1 = input.Line1, Line2 = input.Line2, RestaurantId = input.RestaurantId });

return Json(address); // use MapToGridModel like in Grid Crud Demo when grid uses Map
}

public ActionResult Edit(int id)
{
var address = Db.Get<RestaurantAddress>(id);

return PartialView(
"Create",
new RestaurantAddressInput
{
Line1 = address.Line1,
Line2 = address.Line2,
RestaurantId = address.RestaurantId
});
}

[HttpPost]
public ActionResult Edit(RestaurantAddressInput input)
{
if (!ModelState.IsValid)
{
return PartialView("Create", input);
}

var address = Db.Get<RestaurantAddress>(input.Id);
address.Line1 = input.Line1;
address.Line2 = input.Line2;
return Json(new { input.Id });
}

public ActionResult Delete(int id)
{
var address = Db.Get<RestaurantAddress>(id);

return PartialView(new DeleteConfirmInput
{
Id = id,
Message = string.Format("Are you sure you want to delete restaurant address <b>{0} {1}</b> ?", address.Line1, address.Line2)
});
}

[HttpPost]
public ActionResult Delete(DeleteConfirmInput input)
{
Db.Delete<RestaurantAddress>(input.Id);
return Json(new { input.Id });
}
}
}

Master Detail CRUD using in nest editing

MasterDetailCrudDemo/Index.cshtml
@Html.InitCrudForGridNest("RestaurantGrid2", "MasterDetailCrudDemo")

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

@(Html.Awe().Grid("RestaurantGrid2")
.Url(Url.Action("RestaurantGridGetItems"))
.PageSize(10)
.Attr("data-syncg", "rest")
.Nests(
new Nest { Name = "editnst", GetFunc = "utils.loadNestPopup('editRestaurantGrid2')" },
new Nest { Name = "delnst", GetFunc = "utils.loadNestPopup('deleteRestaurantGrid2')" })
.Columns(
new Column { ClientFormat = ".Id", Header = "Id", Width = 70 },
new Column { Bind = "Name" },
new Column { ClientFormat = GridUtils.EditGridNestFormat(), Width = 50 },
new Column { ClientFormat = GridUtils.DeleteGridNestFormat(), Width = 50 }))

Master Detail CRUD using Inline Editing and nesting

MasterDetailCrudDemo/Index.cshtml
@{
var grid3 = "RestaurantGridInline";
}

@Html.InitDeletePopupForGrid(grid3)

<div class="bar">
@Html.Awe().Button().Text("Create").OnClick("$('#" + grid3 + "').data('api').inlineCreate()").CssClass("mbtn")
</div>

@(Html.Awe().Grid(grid3)
.Url(Url.Action("RestaurantGridGetItems"))
.Mod(o => o.InlineEdit(Url.Action("Create", "RestInl"), Url.Action("Edit", "RestInl"), rowClickEdit: true))
.Groupable(false)
.Attr("data-syncg", "rest")
.Nests(new Nest { Name = "detailnst", Url = Url.Action("Addresses", "RestInl"), LoadOnce = true})
.Columns(
new Column { ClientFormat = ".Id", Header = "Id", Width = 70 }.Mod(o => o.InlineId()),
new Column { Bind = "Name" }.Mod(o => o.Inline(Html.Awe().TextBox("Name"))),
new Column
{
ClientFormat = "<button type='button' class='awe-btn o-pad detailnst'>details <i class='caretc'><i class='o-caret'></i></i></button>",
Width = 105
},
new Column { ClientFormat = GridUtils.InlineEditFormat(), Width = 70 },
new Column { ClientFormat = Html.InlineDeleteFormatForGrid(grid3), Width = 80 }))
<style>
/* hide addresses button for new rows */
.o-glnew .detailnst {
display: none;
}

.caretc
{
position: relative;
padding: .4em .5em;
display: inline-block;
}

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

.detailnst-on .caretc .o-caret
{
transform: rotate(0);
}
</style>
RestInl/Addresses.cshtml
@{
var restId = ViewData["Id"];
var gridId = "AddrGrid-" + restId;
}

@Html.InitDeletePopupForGrid(gridId, "AddressesGridCrud")

<div style="padding: .5em;">
<div class="bar">
<button type="button" class="awe-btn mbtn" onclick="$('#@gridId').data('api').inlineCreate()">Create</button>
</div>
@(Html.Awe().Grid(gridId)
.Url(Url.Action("GridGetItems", "AddressesGridCrud"))
.Mod(o => o.InlineEdit(Url.Action("Create", "AddrInlGrid"), Url.Action("Edit", "AddrInlGrid"), rowClickEdit:true))
.Parameter("restaurantId", restId)
.Attr("data-syncg", "addr")
.Height(200)
.Groupable(false)
.Columns(
new Column { Bind = "Id", Hidden = true }.Mod(o => o.InlineReadonly()),
new Column { Bind = "Line1", ClientFormat = ".Line1", Header = "Line 1" }
.Mod(o => o.Inline(Html.Awe().TextBox("Line1"))),
new Column { Bind = "Line2", ClientFormat = ".Line2", Header = "Line 2" }
.Mod(o => o.Inline(Html.Awe().TextBox("Line2"))),
new Column { ClientFormat = GridUtils.InlineEditFormat(), Width = 70 },
new Column { ClientFormat = Html.InlineDeleteFormatForGrid(gridId), Width = 80 }))
</div>
Demos/Grid/MasterDetailCrud/RestInlController.cs
using System.Web.Mvc;
using AwesomeMvcDemo.Models;
using AwesomeMvcDemo.ViewModels.Input;
using Omu.Awem.Utils;

namespace AwesomeMvcDemo.Controllers.Demos.Grid.MasterDetailCrud
{
public class RestInlController : Controller
{
public ActionResult Addresses(int key)
{
ViewData["Id"] = key;
return PartialView();
}

private object MapToGridModel(Restaurant o)
{
return new { o.Id, o.Name };
}

[HttpPost]
public ActionResult Create(RestaurantInput input)
{
if (!ModelState.IsValid)
{
return Json(ModelState.GetErrorsInline());
}

var ent = Db.Insert(new Restaurant
{
Name = input.Name,
IsCreated = true
});

return Json(new { Item = MapToGridModel(ent) });

}

[HttpPost]
public ActionResult Edit(RestaurantInput input)
{
if (!ModelState.IsValid)
{
return Json(ModelState.GetErrorsInline());
}

var ent = Db.Get<Restaurant>(input.Id);
ent.Name = input.Name;
Db.Update(ent);

return Json(new { });
}
}
}



Comments