0

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>&nbsp;</p>
                    <p>
                        Copyright &copy; 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 :-)

6
  • Hi @iggyweb you should be able to stack a modal on top of another modal or a modal on top of a regular html form. Have you checked into using those? Commented Mar 22, 2016 at 14:38
  • Not yet, I've lost count how many jQuery Dialog examples with Partial Views or hidden sub forms I've researched. Commented Mar 22, 2016 at 14:41
  • Let me work up a small example of what i'm talking about and i'll post as answer below. I think they look nice too. Commented Mar 22, 2016 at 14:41
  • Much appreciated, thank you. Commented Mar 22, 2016 at 14:42
  • I included just the script part you mentioned to save some space.. long answer as it is. Commented Mar 22, 2016 at 14:51

2 Answers 2

1

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)

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, I like the look of this.
0

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">&times;</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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.