PopupForm

The PopupForm is used to load and post a form in a popup. It can be initialized using Html.Awe().InitPopupForm and opened using awe.open js function or Html.Awe().OpenPopup helper. It loads the content from the .Url(string) provided and when the user clicks ok, the form will be posted, if the result of the post is view/string (usually when ModelState not valid) the content of the popup will be replaced with the post result, when the result is a json object the popup will close, if the PopupForm has a success function defined the json object will be passed that function.

You can see the PopupForm being used in all of the Crud demos (Grid), also in the Wizard Demo. In most Crud demos the call to Html.Awe().InitPopupForm is being wrapped in a custom helper Html.InitCrudPopupsForGrid which calls this helper multiple times (for Create, Edit, Delete).

PopupForm with Success function assigned

PopupFormDemo/Index.cshtml
@(Html.Awe().InitPopupForm(new PopupFormOpt
{
Name = "createDinner",
Height = 400,
Url = Url.Action("Create", "DinnersGridCrud"),
OnSuccess = "created"
}))

@Html.Awe().Button().Text("Create").OnClick(Html.Awe().OpenPopup("createDinner"))

<script type="text/javascript">
function created(result, popup) {
alert('dinner created');
}
</script>
Demos/Grid/DinnersGridCrudController.cs
/// </summary>
/// Edit and Delete post actions must return an object with property "Id" - in utils.js itemEdited and itemDeleted functions expect it this way;
/// parameters for Edit, Delete controller Actions need to remain called "id", that's how they are set in GridUtils.cs ( "params:{{ id:" );
/// or in MapToGridModel additionally to o.MyId add another property Id = o.MyId
/// and for the action columns (edit, delete btns) you can either specify the MyId property (e.g. GridUtils.EditFormatForGrid("DinnersGrid", "MyId"));
/// change the Bind = "MyId" (if you have an Id column),
/// Note: If your Key Property is not "Id" (but "MyId"), you need to change the GridModelBuilder.Key = "MyId" in GridGetItems and in the view
/// <summary>
public class DinnersGridCrudController : Controller
{
private readonly MyContext mcx = new MyContext();// mock EF Db context

public DinnersGridCrudController()
{

}

private static object MapToGridModel(Dinner o)
{
return
new
{
o.Id,
o.Name,
Date = o.Date.ToShortDateString(),
ChefName = o.Chef.FullName,
Meals = string.Join(", ", o.Meals.Select(m => m.Name)),
BonusMeal = o.BonusMeal.Name
};
}

public async Task<IActionResult> GridGetItems(GridParams g, string search = "")
{
var query = mcx.Dinners
.Include(o => o.Chef)
.Include(o => o.Meals)
.Include(o => o.Country)
.Include(o => o.BonusMeal)
.Where(o => o.Name.Contains(search)).AsQueryable();

var model = new GridModelBuilder<Dinner>(query, g)
{
KeyProp = o => o.Id, // needed for api select, update, tree, nesting, EF
Map = MapToGridModel,
};

return Json(await model.EFBuildAsync());
}

public IActionResult Create()
{
// make sure to use "return PartialView" for PopupForm/Popup views
// this will ignore _viewstart.cshtml so that you don't use the _Layout.cshtml and reload all the scripts
return PartialView();
}

[HttpPost]
public async Task<IActionResult> Create(DinnerInput input)
{
return await save(input);
}

public async Task<IActionResult> Edit(int id)
{
var dinner = await mcx.Dinners
.Include(o => o.Chef)
.Include(o => o.Meals)
.Include(o => o.BonusMeal)
.SingleAsync(o => o.Id == id);

var input = new DinnerInput
{
Id = dinner.Id,
Name = dinner.Name,
ChefId = dinner.Chef.Id,
Date = dinner.Date,
MealsIds = dinner.Meals.Select(o => o.Id),
BonusMealId = dinner.BonusMeal.Id
};

return PartialView("Create", input);
}

[HttpPost]
public async Task<IActionResult> Edit(DinnerInput input)
{
return await save(input);
}

private async Task<IActionResult> save(DinnerInput input)
{
if (!ModelState.IsValid) return PartialView("Create", input);

var isCreate = !input.Id.HasValue;

var ent = isCreate ? new Dinner() :
await mcx.Dinners
.Include(o => o.Meals)
.FirstAsync(o => o.Id == input.Id);

ent.Name = input.Name;
ent.Date = input.Date.Value;
ent.Chef = await mcx.FindAsync<Chef>(input.ChefId);

// ToList req for EF
ent.Meals = await mcx.Meals
.Where(o => input.MealsIds.Contains(o.Id)).ToListAsync();

ent.BonusMeal = await mcx.FindAsync<Meal>(input.BonusMealId);
ent.Organic = input.Organic ?? false;

if (isCreate)
{
mcx.Add(ent);
}

await mcx.SaveChangesAsync();

if (isCreate)
{
// the create PopupForm's success function utils.itemCreated expects the grid row model obj, to render and append the new row
return Json(MapToGridModel(ent));
}

// the edit PopupForm's success function utils.itemEdited expects an obj with "Id" property
return Json(new { Id = ent.Id });
}

public async Task<IActionResult> Delete(int id)
{
var dinner = await mcx.FindAsync<Dinner>(id);

return PartialView(new DeleteConfirmInput
{
Id = id,
Type = "dinner",
Name = dinner.Name
});
}

[HttpPost]
public async Task<IActionResult> Delete(DeleteConfirmInput input)
{
await mcx.DeleteAsync<Dinner>(input.Id);

// the delete PopupForm's success function utils.itemDeleted expects an obj with "Id" property
return Json(new { Id = input.Id });
}
}
DinnersGridCrud/Create.cshtml
@model AweCoreDemo.ViewModels.Input.DinnerInput
@using (Html.BeginForm())
{
using (Html.Awe().BeginContext())
{
@Html.EditorFor(o => o.Name)
@Html.EditorFor(o => o.Date)
@Html.EditorFor(o => o.ChefId)
@Html.EditorFor(o => o.MealsIds)
@Html.EditorFor(o => o.BonusMealId)
}
}

Sending client side parameters to server on content load

Value sent to the server action that returns the popup's content:
PopupFormDemo/Index.cshtml

@(Html.Awe().InitPopupForm(new PopupFormOpt
{
Name = "PopupFormParams",
Url = Url.Action("PopupWithParameters"),
ParameterFunc = "setParams"

}
.Button("Help", "helpClick")
.Parent("txtParam1")
.Parameter("p1", 15)))

@(Html.Awe().Button().Text("Open Popup")
.OnClick(Html.Awe().OpenPopup("PopupFormParams").Params(new { Id = 123 })))

<script>
function setParams() {
return { a: "hi", b: "how are you" };
}

function helpClick() {
awe.flash($(this).find('.msg1').html('help clicked'));
}
</script>
Demos/Helpers/PopupFormDemoController.cs
public IActionResult PopupWithParameters(int? id, string parent, int p1, string a, string b)
{
ViewData["parent"] = parent;
ViewData["p1"] = p1;
ViewData["a"] = a;
ViewData["b"] = b;
ViewData["id"] = id;
return PartialView();
}

[HttpPost]
public IActionResult PopupWithParameters()
{
return Json(new { });
}
PopupFormDemo/PopupWithParameters.cshtml
parameter set in the OpenPopup call: id = @ViewData["id"]
<br />
value of the parent: @ViewData["parent"] <br />
<br />
value of the p1 parameter: @ViewData["p1"] <br />
<br />
parameters sent by js function set using ParameterFunc:<br />
a = @ViewData["a"] <br />
b = @ViewData["b"] <br />

@using (Html.BeginForm())
{
}

<div class="msg1"></div>

Submit confirmation using OnLoad func

Confirmation dialog before posting a valid form.
PopupFormDemo/Index.cshtml
@(Html.Awe().InitPopupForm(new PopupFormOpt
{
Name = "confirmedPopup",
Height = 200,
Url = Url.Action("PopupConfirm"),
UseDefaultButtons = true,
OnLoad = "regConfirm"
}))

@Html.Awe().Button().Text("Open popup").OnClick(Html.Awe().OpenPopup("confirmedPopup"))

<script>
function regConfirm() {
var $popup = this.d;
var $form = $popup.find('form');
$form.on('submit', function (e) {
if (!$form.valid() || !confirm("Are you sure ?")) {
return false;
}
});
}
</script>

Confirm close

Confirming popup close when closing it via the Cancel or X button, valid form posts are not confirmed.
PopupFormDemo/Index.cshtml
@(Html.Awe().InitPopupForm(new PopupFormOpt
{
Name = "confirmClosePopup",
Height = 200,
PopupClass = "needConfirm",
OnSuccess = "logConfClose",
Url = Url.Action("PopupConfirm")
}))

@Html.Awe().Button().Text("Open confirm close popup").OnClick(Html.Awe().OpenPopup("confirmClosePopup"))
<div id="logConfClose"></div>
<script>
function logConfClose(res) {
$('#logConfClose').html(res.Name);
}

$(function() {
// registering a global confirm close for all popups that have "needConfirm" popup class
$(document).on('awebfclose', function (e, opt) {
var pdiv = $(e.target);

// opt.post = close popup after successful form post
if (!pdiv.closest('.needConfirm').length || opt.post || opt.force) return;

// flag that we can set in 'awebfclose', tells the popup not to close
opt.noclose = true;

var pp = pdiv.data('o');
awe.open('confirmClose', {
title: 'Confirm close',
content: '<div style="padding: 1em;">Are you sure you want to close this popup ?</div>',
height: 200,
width: 500,
modal: true,
btns: [
{
text: "Yes",
ok: 1,
action: function () {
$(this).data('api').close();
pp.cx.api.close({ force: true });
}
},
{
text: "No",
action: function () {
$(this).data('api').close();
}
}]
});
});
});
</script>

Note: besides the features shown on this page the PopupForm also inherits the features of the Popup




Comments