iggyweb
iggyweb

Reputation: 2483

C# MVC Bootstrap Add Record Popup Form

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 :-)

Upvotes: 0

Views: 1586

Answers (2)

iggyweb
iggyweb

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">&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.

Upvotes: 0

Drew Rochon
Drew Rochon

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

Related Questions