Are you ready to create a Modal Factory?

For a while now, I have been utilizing modals in various front-end frameworks to communicate with users in my applications. Typically, the process involves defining the modal's html and then rendering it through a click event.

As my apps continue to expand, so does the number of modals used for user prompts and confirmations. These modals can range from simple text inputs to complex forms or dropdown menus.

Currently, I create each modal separately in a single html file and call them by their IDs. However, this method feels inefficient due to redundant boilerplate code. I am exploring ways to dynamically generate modals while maintaining clean and lightweight code.

I've considered implementing a "modal factory" where modal content, dimensions, styling, etc. are passed as parameters. Do you think this would be an effective approach?

Thank you for any suggestions!

Answer №1

My approach for loading Forms/HTML Content from the server involves creating a div with an ID - PartialViewDialog at the bottom of the page. This is where I load Partial Views inside a dialog.

The HTML structure follows Bootstrap 3.* principles, based on the Frontend framework.

Here's how the HTML looks:

<body>

<!-- Other page content -->


<div class="modal fade" id="PartialViewDialog">
    <div class="modal-dialog modal-lg">
        <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>
                <h4 class="modal-title" data-modal="title"></h4>
            </div>
            <div class="modal-body" data-modal="content">

            </div>
            <div class="modal-footer" data-modal="footer">
            </div>
        </div>
    </div>
</div>

</body>

Next, in JavaScript, a dialog Manager is created:

   var MyApp = MyApp || {};

MyApp.UIHelper = MyApp.UIHelper || {};

// The Dialog Manager module
MyApp.UIHelper.DialogManager = (function () {

    "use strict";

    // Initialization and configuration
    var self = {};
    self.divId = null;
    self.dialog = null;
    self.dialogBody = null;
    self.dialogTitle = null;
    self.dialogFooter = null;
    self.actionUrl = "";
    self.modalObject = null;
    self.options = {};

    function Initilize(divId, options) {
        self.options = $.extend({ buttons: [] }, options);
        self.divId = divId;
        self.dialog = $(self.divId);
        self.dialogBody = self.dialog.find('*[data-modal="content"]');
        self.dialogTitle = self.dialog.find('*[data-modal="title"]');
        self.dialogFooter = self.dialog.find('*[data-modal="footer"]');
        self.BootgridObject = null;
    };

    // Method to open the Partial View Dialog
    function OpenPartialViewDialog(url, title, preprocessingFunction, postProcessingFunction) {
        var options = self.GetPartialViewButtons(url, preprocessingFunction, postProcessingFunction);
        Initilize('#PartialViewDialog', options);
        self.actionUrl = url;
        self.dialogTitle.html(title);
        self.OpenModel();
    };

    // Method to create buttons for the Form dialog
    self.GetPartialViewButtons = function (url, preprocessingFunction, postProcessingFunction) {
        var buttons = {
            buttons: {
                Save: {
                    Text: "Save",
                    css: "btn btn-success",
                    click: function () {
                        if (preprocessingFunction) { preprocessingFunction(); }
                        $.ajax({
                            type: "POST",
                            url: url,
                            data: self.dialogBody.find("form").serialize(),
                            success: function (response) {
                                if (response.hasOwnProperty("IsSuccess")) {
                                    if (response.IsSuccess) {
                                        self.dialogBody.html("");
                                        self.dialog.modal("hide");
                                        if (postProcessingFunction) {
                                            postProcessingFunction();
                                        }
                                    } else {
                                        // Handle failure
                                    }
                                } 
                            },
                            error: function (response) {
                               // Handle failure
                            }
                        });
                    }
                },
                Cancel: {
                    Text: "Cancel",
                    css: "btn btn-danger",
                    click: function () {
                        self.dialogBody.html("");
                        self.dialogFooter.html("");
                        self.dialogTitle.html("");
                        self.dialog.modal("hide");
                    }
                }
            }
        };
        return buttons;
    };

    // Method to dynamically create button objects
    self.CreateButtonsHtml = function () {
        var htmlButtons = [];
        $.each(self.options.buttons, function (name, props) {
            var tempBtn = $("<button/>", {
                text: props.Text,
                id: "btn_" + props.Text,
                "class": props.css + "",
                click: props.click
            }).attr({ "style": "margin-right: 5px;" });

            htmlButtons.push(tempBtn);

        });
        return htmlButtons;
    };

    // Method to load content/form from the server and setup the dialog
    self.OpenModel = function () {
        $.ajax({
            url: self.actionUrl,
            type: "GET",
            success: function (response) {          
                if (response.hasOwnProperty("HasErrors")) { 
                    // Handle errors
                } else {
                    self.dialogBody.html(response);
                    self.modalObject = self.dialog.modal();
                    self.modalObject.show();
                }
            }
        });

        var buttons = self.CreateButtonsHtml();
        self.dialogFooter.html('');
        for (var i = 0; i < buttons.length; i++) {
            self.dialogFooter.append(buttons[i]);
        }
    };
    
    return {
        OpenPartialViewDialog: OpenPartialViewDialog,
    };

})();

To open a dialog from the server, you can utilize the following code snippet:

MyApp.UIHelper.DialogManager
          .OpenPartialViewDialog('/Content/Load', "My Title", 
                          function(){alert('pre-process')}, 
                          function(){alert('post-process')}
                  );

Please note that PreProcess and PostProcess functions are invoked when the Save button is clicked.

A live demo showcasing the functionality described above can be found here: https://jsfiddle.net/1L0eLazf/

For an example focusing on the buttons specifically, visit: https://jsfiddle.net/1L0eLazf/1/

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using jQuery to store the selection made in a select element option

Hello everyone, I need some help with saving the selected option on my form by the user. I am not sure how to accomplish this. Let me give you a brief overview of my setup... On my home page, I have a form that looks like this: <form class="form-home ...

Prevent clicking here

I'm attempting to only prevent the click event on the current item with a certain class. $(document).on('click', '.item', function() { $(".item").removeClass('is-expanded'); $(this).addClass('is-expanded'); ...

Is there an automatic bottom padding feature?

Currently, I am facing a challenge in fitting the loader into the container without it being overridden by the browser. Using padding-bottom is not an ideal solution as it results in the loader appearing un-resized and unprofessional. Any suggestions or co ...

Hey there, I'm looking to automatically delete new users from my mongoDB atlas database if they haven't verified their phone number within 2 minutes. I believe using the TTL feature would be

Database Schema In my User schema, the field isVerified is initially saved as false. The user enters their phone number, receives a verification token via SMS, and both the token and number are saved in the database. Once the user enters the verification ...

How to Retrieve the Number of Requests in an Express Application

Is there a method to retrieve the overall count of requests in a specific route using Expressjs? ...

How is it possible that my code is continuing to run when it is supposed to be

My API has a limitation of 50 requests per minute for any endpoint. In the code snippet below, I filter objects called orders based on their URLs and store the ones that return data in successfulResponses within my app.component.ts. Promise.all( orders.ma ...

Stop the Router from Displaying the Page momentarily prior to Redirecting

Currently, I have set up a session context for my NextJS application where users accessing pages within the /app/ directory are required to undergo an authorization check before being granted access. Although the logic is functioning correctly in redirect ...

Incorporating additional ES6 modules during the development process

As I build a React component, I find that it relies on an ES6 component that I'm currently developing. Since I created the latter first, what is the typical method to include it during development as I work on the second component? If the dependency w ...

retrieve the value of an HTML element once it has been modified

When I am working in a view, I encounter an issue where I need to retrieve the value of an HTML input box after it has been changed. Initially, the page loads with the following code: <input id="input_one" type="text" value = "apple" /> Upon loadin ...

Error in retrieving Ajax URL with incorrect .net format

Recently delving into C# tutorials to expand my skills, I encountered an issue while attempting to make an ajax call to the server using localhost. Despite my efforts, it seems like I am missing something crucial. It could be related to my folder structur ...

There seems to be an error with cheeriojs regarding the initialization of exports.load

I am currently using cheeriojs for web scraping, but I am encountering an issue after loading the body into cheerio. Although the body appears to be well-formatted HTML code, I am receiving errors such as exports.load.initialize. This is preventing me fr ...

What steps are involved in setting up a local server on my computer in order to create an API that can process http requests from Flutter?

New to API creation here, so please be patient. I plan to eventually host my API on a more robust server, but for now, I want to get started by setting something up locally on my PC to work on backend functions. The API goals include: Verify incoming requ ...

Alert: A notification when navigating away from your site

Is there a way to notify users when they click on an external link that they are leaving your site? <div class="row"> <div class="col-lg-12"> <div class="form-group"> *If you need information on other applicable forms, you ...

Problem with jQuery's .prepend method being called twice on list items

Looking to enhance the appearance of a list by adding some icons before the anchor links within each list item. <ul class="submenu-children"> <li><a href="#">Link</a></li> <li><a href="#">Link</a></li> ...

How can we enhance the efficiency of rendering text on the screen?

Imagine having a <p> tag inside a <div> with specific properties: div { height: 100px; width: 100px; overflow: hidden; } My goal is to continuously add words to the <p> tag until an overflow is detected, meaning stop when the f ...

Having trouble with a beginner problem that's hindering the functionality of my code

I have been struggling with a particular piece of code and it is driving me crazy as I am unable to locate the source of my error: $.post($form.attr('action'), $form.serialize(), function (result) { console.log(result); if (result.succes ...

In React (Next.js), the act of replacing a file is performed instead of adding a file

I kindly request a review of my code prior to making any changes. const test = () => { const [files, setFiles] = useState ([]); //I believe I need to modify the following statement. const handleFile = (e) => { const newFiles = [] for (let i= ...

JavaScript can be used to create a fullscreen experience without any toolbars, scrollbars, and the like, without having

Is there a way for me to expand the current window I am using to fullscreen mode and eliminate all toolbars? ...

Changing the value in a URL String using JavaScript

I am in possession of a String that contains a URL resembling the following: var url ="http://ispeakphone.com/checkout/cart/add/uenc/aHR0cDovL2lzcGVha3Bob25lLmNvbS9zYW1zdW5nL3NhbXN1bmctZ2FsYXh5LXMvZ2FsYXh5LXM5LXBsdXMuaHRtbA,,/product/619/form_key/foxmD7jg ...

Incorporate a Vue.js computed property into the data retrieved from a server

Coming from Knockout.js, where observables are easily created by defining them, I'm curious if there's a similar approach in Vue.js. let vm = { someOtherVar: ko.observable(7), entries: ko.observableArray() }; function addServerDataToEnt ...