Reputation: 2483
I have an existing form which relies on a category being selected, if a category does not exist for the user the company belongs too, the user must be able to create one.
I believe jQuery and JSON is the route forward, but I cannot generate a true popup above the current Bootstrap form, nor can I get the popup form to post without posting the main form.
If possible I'd like the jQuery function getCategories to open a popup form only if no data is returned, then the popup form using validation, once a record has been successfully added to the database, the popup form close and then recall the jQuery function getCategories and select the newly added record.
HomeController.cs
public JsonResult GetCategories(int companyId)
{
var categories = _repository.GetCategories(companyId);
return Json(categories, JsonRequestBehavior.AllowGet);
}
_Layout.cshtml
@using Documents
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="" />
<meta name="author" content="@ViewBag.LenderName" />
<title>@ViewBag.Title - @ViewBag.LenderName</title>
@Styles.Render("~/Content/css")
@Styles.Render("~/Content/dataTablesCss")
@Styles.Render("~/Content/blue")
<!--[if lt IE 9]>
@Scripts.Render("~/bundles/ie8")
<![endif]-->
</head>
<body class="has-navbar-fixed-top page-index">
@Scripts.Render("~/bundles/jquery")
<!--[if lt IE 9]>
@Scripts.Render("~/bundles/jqueryvalidate")
<![endif]-->
@RenderSection("featusearch", required: false)
@RenderBody()
<footer id="footer" class="text-center">
<div class="container">
<div class="row">
<div class="col-lg-12">
<p> </p>
<p>
Copyright © 2015 - @ViewBag.CompanyName
</p>
</div>
</div>
</div>
</footer>
@Scripts.Render("~/bundles/bootstrap")
@Scripts.Render("~/bundles/dataTables")
@Scripts.Render("~/bundles/money")
@Scripts.Render("~/bundles/tooltip")
@Scripts.Render("~/bundles/jquery-ui")
<script type="text/javascript" language="javascript">
$("#menu-close").click(function (e) {
e.preventDefault();
$("#sidebar-wrapper").toggleClass("active");
});
$("#menu-toggle").click(function (e) {
e.preventDefault();
$("#sidebar-wrapper").toggleClass("active");
});
$(function () {
$('a[href*=#]:not([href=#])').click(function () {
if (location.pathname.replace(/^\//, '') === this.pathname.replace(/^\//, '') || location.hostname === this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
if (target.length) {
$('html,body').animate({
scrollTop: target.offset().top
}, 1000);
return false;
}
}
});
});
</script>
<script type="text/javascript" charset="utf-8">
$(function () {
$('.validation-summary-errors').each(function () {
$(this).addClass('alert');
$(this).addClass('alert-danger');
});
$('form').each(function () {
$(this).find('div.form-group-individual').each(function () {
if ($(this).find('span.field-validation-error').length > 0) {
$(this).addClass('has-error');
$(this).find('span.field-validation-error').removeClass('field-validation-error');
}
});
});
});
</script>
<script language="javascript" type="text/javascript">
$(document).ready(function () {
var oTable = $('#orders').dataTable({
responsive: true,
"pagingType": "full",
"iDisplayLength": 5,
"aLengthMenu": [[5, 10, 25, -1], [5, 10, 25, "All"]],
columnDefs: [{ type: 'date-euro', targets: 4 }],
"aoColumns": [
{ "visible": false },
{ "bSortable": true, "bSearchable": true },
{ "bSortable": true, "bSearchable": true },
{ "bSortable": true, "bSearchable": true },
{ "bSortable": true, "bSearchable": true },
null,
null,
null
],
"order": [[0, "desc"]]
});
$('#Form').find('select').each(function () {
$(this).tooltip({
placement: "top",
trigger: "focus"
});
});
$('#Form').find('input').each(function () {
$(this).tooltip({
placement: "top",
trigger: "focus"
});
});
$('#Form').find('button').each(function () {
$(this).tooltip({
placement: "top",
trigger: "hover",
container: "body"
});
});
});
</script>
@RenderSection("scripts", false)
</body>
</html>
$(document).ready(function () {
var companyId = parseInt($('#CompanyId').val(), 0);
function getCategories() {
$.getJSON('/Home/GetCategories', { companyId: companyId }, function (data) {
$('#Categories option').remove();
$('#Categories').append('<option value="0">Please select a Category</option>');
for (var i = 0; i < data.length; i++) {
if (data[i].Id != categoryId) {
$('#Categories').append('<option value="' + data[i].Id + '">' + data[i].CategoryName + '</option>');
} else {
$('#Categories').append('<option value="' + data[i].Id + '" selected>' + data[i].CategoryName + '</option>');
}
}
if (data.length > 0) {
// We Have Date
} else {
// No Data
// Create Dialog Popup
alert('Error getting Categories, please add a Category');
}
}).fail(function () {
debugger;
alert('Error getting Categories, please add a Category');
});
}
$('#Categories').change(function () {
var selected = $(this).find('option:selected');
categoryId = selected.val();
$('#CategoryId').val(categoryId);
});
});
Index.cshtml
@using WebApplication1
@using WebApplication1.Helpers
@model WebApplication1.Models.Order
@{
ViewBag.Title = "Test";
}
<div id="navigation" class="wrapper">
<div class="navbar navbar-fixed-top" id="top">
<div class="navbar-inner">
<div class="inner">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle btn btn-navbar" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/" title="Home"><h1>Test</h1><span>@ViewBag.CompanyName</span></a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-right" id="main-menu">
@Html.MenuLink("Logout", "Login", "Logout", "", "Logout")
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="highlighted">
<div class="container">
<div class="header">
<h2 class="page-title">
<span>Test</span> <small>This is a test page.</small>
</h2>
<p></p>
</div>
</div>
</div>
<div id="content">
<div class="container">
<div class="row">
<div class="col-sm-12">
@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { @class = "form-horizontal", role = "form", @Id = "Form" }))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(m => m.CategoryId, new { @Value = @ViewBag.CategoryId, @Id = "CategoryId" })
<fieldset>
<div class="form-group">
<div class="form-group-individual">
<div class="col-sm-6">
<div class="input-group">
<span class="input-group-addon">Title</span>
@Html.DropDownListExt("SalutationId", ViewBag.SalutationList as SelectList, "Title")
</div>
<p class="help-block">@Html.ValidationMessageFor(m => m.SalutationId)</p>
</div>
<div class="col-sm-6">
<div class="input-group">
<span class="input-group-addon">Forename</span>
@Html.TextBoxForExt(m => m.Forename, new Dictionary<string, object> { { "Value", @ViewBag.Forename } })
</div>
<p class="help-block">@Html.ValidationMessageFor(m => m.Forename)</p>
</div>
</div>
</div>
<div class="form-group">
<div class="form-group-individual">
<div class="col-sm-6">
<div class="input-group">
<span class="input-group-addon">Middle Name</span>
@Html.TextBoxForExt(m => m.MiddleName, new Dictionary<string, object> { { "Value", @ViewBag.MiddleName } })
</div>
<p class="help-block">@Html.ValidationMessageFor(m => m.MiddleName)</p>
</div>
<div class="col-sm-6">
<div class="input-group">
<span class="input-group-addon">Surname</span>
@Html.TextBoxForExt(m => m.Surname, new Dictionary<string, object> { { "Value", @ViewBag.Surname } })
</div>
<p class="help-block">@Html.ValidationMessageFor(m => m.Surname)</p>
</div>
</div>
</div>
<div class="form-group">
<div class="form-group-individual">
<div class="col-sm-6">
<div class="input-group">
<span class="input-group-addon">Categories</span>
<select id="Categories" name="Categories" class="form-control" data-toggle="tooltip" title="Categories">
<option></option>
</select>
</div>
<p class="help-block">@Html.ValidationMessageFor(m => m.CategoryId)</p>
</div>
<div class="col-sm-1">
<button type="submit" class="btn btn-primary" name="Submit" value="Submit" title="Click to Submit">Submit</button>
</div>
</div>
</div>
</fieldset>
}
</div>
</div>
</div>
</div>
<script type="text/javascript" src="/Scripts/form.js"></script>
form.js
$(document).ready(function () {
var companyId = parseInt($('#CompanyId').val(), 0);
var categoryId = parseInt($('#CategoryId').val(), 0);
getCategories();
function getCategories() {
$.getJSON('/Home/GetCategories', { companyId: companyId }, function (data) {
$('#Categories option').remove();
$('#Categories').append('<option value="0">Please select a Category</option>');
for (var i = 0; i < data.length; i++) {
if (data[i].Id != categoryId) {
$('#Categories').append('<option value="' + data[i].Id + '">' + data[i].Category + '</option>');
} else {
$('#Categories').append('<option value="' + data[i].Id + '" selected>' + data[i].Category + '</option>');
}
}
if (data.length > 0) {
// We Have Data
} else {
// No Data
// Create Dialog Popup
alert('Error getting Categories, please add a Category');
}
}).fail(function () {
debugger;
alert('Error getting Categories, please add a Category');
});
}
$('#Categories').change(function () {
var selected = $(this).find('option:selected');
categoryId = selected.val();
$('#CategoryId').val(categoryId);
});
});
Add.cshtml
@using WebApplication1.Helpers
@model WebApplication1.Models.Category
<div id="content">
<div class="container">
<div class="row">
<div class="col-sm-4">
@using (Html.BeginForm("Add", "Home", FormMethod.Post, new { @class = "form-horizontal", role = "form", @Id = "AddForm" }))
{
@Html.HiddenFor(m => m.CompanyId, new { @Value = @ViewBag.CompanyId, @Id = "CompanyId" })
<fieldset>
<div class="form-group">
<div class="form-group-individual">
<div class="col-sm-4">
<div class="input-group">
<span class="input-group-addon">Category Name</span>
@Html.TextBoxForExt(m => m.CategoryName)
</div>
<p class="help-block">@Html.ValidationMessageFor(m => m.CategoryName)</p>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-1">
<button type="submit" class="btn btn-primary" name="Add" value="Add" title="Click to Add a Category">Add</button>
</div>
</div>
</fieldset>
}
</div>
</div>
</div>
</div>
BundleConfig.cs
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.IgnoreList.Clear();
bundles.UseCdn = true;
BundleTable.EnableOptimizations = false;
bundles.Add(new ScriptBundle("~/bundles/ie8").Include(
"~/Scripts/html5shiv.js",
"~/Scripts/respond.js"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js"));
var jquery = new ScriptBundle("~/bundles/jquery", "~/Scripts/jquery-2.1.4.js").Include(
"~/Scripts/Compatibility/jquery-1.11.3.js");
jquery.CdnFallbackExpression = "window.jQuery";
bundles.Add(jquery);
bundles.Add(new ScriptBundle("~/bundles/jqueryvalidate").Include(
"~/Scripts/jquery.validate.js",
"~/Scripts/jquery.validate.unobtrusive.js",
"~/Scripts/_extensions.js"));
bundles.Add(new ScriptBundle("~/bundles/money").Include(
"~/Scripts/jquery.price_format.2.0.js"));
bundles.Add(new ScriptBundle("~/bundles/tooltip").Include(
"~/Scripts/tooltip.js"));
bundles.Add(new ScriptBundle("~/bundles/dataTables").Include(
"~/Scripts/DataTables-1.10.9/jquery.dataTables.js",
"~/Scripts/DataTables-1.10.9/dataTables.bootstrap.js",
"~/Scripts/DataTables-1.10.9/date-euro.js"));
bundles.Add(new ScriptBundle("~/bundles/awesomeMvc").Include(
"~/Scripts/AwesomeMvc.js"));
bundles.Add(new ScriptBundle("~/bundles/jquery-ui").Include(
"~/Scripts/jquery-ui.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/Site.css"));
bundles.Add(new StyleBundle("~/Content/blue").Include(
"~/Content/colour-blue.css"));
bundles.Add(new StyleBundle("~/Content/red").Include(
"~/Content/colour-red.css"));
bundles.Add(new StyleBundle("~/Content/dataTablesCss").Include(
"~/Content/DataTables-1.10.9/dataTables.bootstrap.css",
"~/Content/DataTables-1.10.9/Buttons-1.0.3/buttons.bootstrap.css"));
}
}
Any help would be much appreciated :-)
Upvotes: 0
Views: 1586
Reputation: 2483
Following on from Drew Rochon's suggestion, I have researched and resolved my issue.
The following code is either replacement or addition where specified.
_Add.cshtml (Replacement for Add.cshtml)
@using WebApplication1.Helpers
@model WebApplication1.Models.Category
<div class="modal fade" id="AddCategoryModal" tabindex="-1" role="dialog" aria-labelledby="Add" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h5 class="modal-title">Add Category</h5>
</div>
<div class="modal-body">
@using (Html.BeginForm(null, null, FormMethod.Post, new { @Id = "AddCategoryForm" }))
{
@Html.HiddenFor(m => m.CompanyId, new { @Id = "CompanyId" })
<fieldset>
<div class="form-group">
<div class="form-group-individual">
<div class="col-sm-12">
<div class="input-group">
<span class="input-group-addon">Category Name</span>
@Html.TextBoxForExt(m => m.CategoryName)
</div>
<p class="help-block">@Html.ValidationMessageFor(m => m.CategoryName)</p>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="submit" class="btn btn-primary">Add</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div>
</fieldset>
}
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
var path = $("#Path").val();
var companyId = parseInt($('#CompanyId').val(), 0);
var categoryId = parseInt($('#CategoryId').val(), 0);
var abort = false;
$("#AddCategoryModal").modal('show');
$('#AddCategoryModal').off("hidden.bs.modal").on('hidden.bs.modal', modalClose);
function modalClose() {
$("#AddAdvisoryModal").remove();
$('.modal-backdrop').remove();
}
$('#AddCategoryForm').formValidation({
framework: 'bootstrap',
excluded: ':disabled',
icon: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
CategoryName: {
validators: {
notEmpty: {
message: 'Category Name is required'
}
}
}
}
}).on('success.form.fv', function (e) {
e.preventDefault();
var companyId = $("#CompanyId").val();
var categoryName = $("#CategoryName").val();
var model = {
CompanyId: companyId,
CategoryName: categoryName
};
$.ajax({
url: "/Home/_Add/",
type: "POST",
contentType: "application/json;charset=utf-8;",
dataType: "html",
data: JSON.stringify(model),
success: function (markup) {
categoryId = parseInt(markup, 0);
if (categoryId > 0) {
$('#Categories').val(categoryId);
getCategories();
alert("Category added successfully.");
modalClose();
}
},
error: function () {
alert('Ajax request not recieved!');
}
});
});
function getCategories() {
$.getJSON(path + 'GetCategories', { companyId: companyId }, function (data) {
$('#Categories option').remove();
$('#Categories').append('<option value="0">Please select a Category</option>');
$('#Categories').append('<option value="9999999">Add a Category</option>');
for (var i = 0; i < data.length; i++) {
if (data[i].Id != categoryId) {
$('#Categories').append('<option value="' + data[i].Id + '">' + data[i].CategoryName + '</option>');
} else {
$('#Categories').append('<option value="' + data[i].Id + '" selected>' + data[i].CategoryName + '</option>');
}
}
if (data.length > 0) {
if (categoryId > 0) {
$('#Categories').val(categoryId);
}
} else {
alert('Error getting Categories, please add a Category');
}
}).fail(function () {
debugger;
alert('Error getting Categories, please add a Category');
});
}
$('#AddCategoryForm').find('select').each(function () {
$(this).tooltip({
placement: "top",
trigger: "focus"
});
});
$('#AddCategoryForm').find('input').each(function () {
$(this).tooltip({
placement: "top",
trigger: "focus"
});
});
});
</script>
form.js (Replacement)
$(document).ready(function () {
var companyId = parseInt($('#CompanyId').val(), 0);
var categoryId = parseInt($('#CategoryId').val(), 0);
getCategories();
$('#Categories').change(function () {
var selected = $(this).find('option:selected');
categoryId = selected.val();
if (categoryId == 9999999) {
openModal();
}
$('#CategoryId').val(categoryId);
});
function getCategories() {
$.getJSON(path + 'GetCategories', { companyId: companyId }, function (data) {
$('#Categories option').remove();
$('#Categories').append('<option value="0">Please select a Category</option>');
$('#Categories').append('<option value="9999999">Add a Category</option>');
for (var i = 0; i < data.length; i++) {
if (data[i].Id != categoryId) {
$('#Categories').append('<option value="' + data[i].Id + '">' + data[i].CategoryName + '</option>');
} else {
$('#Categories').append('<option value="' + data[i].Id + '" selected>' + data[i].CategoryName + '</option>');
}
}
if (data.length > 0) {
if (categoryId > 0) {
$('#Categories').val(categoryId);
}
} else {
alert('Error getting Categories, please add a Category');
openModal();
}
}).fail(function () {
debugger;
alert('Error getting Categories, please add a Category');
});
}
function openModal() {
var companyId = $("#CompanyId").val();
var model = { CompanyId: companyId };
$.ajax({
url: "/Home/_Add/",
type: "POST",
contentType: "application/json;charset=utf-8;",
dataType: "html",
data: JSON.stringify(model),
success: function (markup) {
if (isNaN(markup) || markup == "0") {
$(document.body).append(markup);
}
}
});
}
});
BundleConfig.cs (Addition)
bundles.Add(new StyleBundle("~/Content/formValidationCss").Include(
"~/Content/formValidation.css"));
bundles.Add(new ScriptBundle("~/bundles/formValidation").Include(
"~/Scripts/formValidation.min.js",
"~/Scripts/foundationBootstrap.min.js",
"~/Scripts/foundation.min.js"));
_Layout.cshtml (Addition)
@Styles.Render("~/Content/formValidationCss")
@Scripts.Render("~/bundles/formValidation")
HomeController.cs (Addition)
public ActionResult _Add(WebApplication1.Models.Category model)
{
int id;
if (ModelState.IsValid)
{
id = _documentsRepository.SetCategory(model);
}
else
{
ModelState.Clear();
return PartialView(model);
}
return Content(id.ToString());
}
Hope this proves useful to others.
Upvotes: 0
Reputation: 419
It sounds like you might be looking for a Modal popup. Bootstrap already has this built in. You can learn about it here: http://www.w3schools.com/bootstrap/bootstrap_modal.asp
You can also pull what to show in the modal from another view using the Html.RenderPartial(view)
Upvotes: 1