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

What is the best way to choose the member variables in this specific data structure?

I have been assigned the task of retrieving the cities from various countries, but I am unsure of the best approach to do so. How can I easily extract city names like: For example, for USA it would be NYC and SFO. I attempted using the code snippet cityD ...

Problem with AngularJS function execution - require a delay in executing the second function

I am developing a small utility in AngularJS to manage the shopping cart for users. Here is the code snippet from my cart-service.js file: var myStoreCartService = angular.module("myStoreCartService", []); myStoreCartService.factory('Cart', fu ...

Having trouble with my jQuery .hover() code not running as expected

Whenever I hover over my divs, I want them to change color. However, the code doesn't seem to be working as expected when I try to do so. I suspect that the issue might be related to the z-index property used in the class that I am trying to hover ove ...

The alternative text for the oversized image exceeds the boundaries

After setting the width and height for an image, along with testing overflow:hidden, I've encountered an issue where the alt text for a broken image overflows the bounds of the image and the image size is lost. How can I contain the alt text within th ...

Attempting to persist a nested document in MongoDB using mongoose within a Nodejs environment

I attempted to save an address as a nested document in the following format When sending data from the client side, it was formatted like this: const address = JSON.stringify( { addressline1:form.addressline1.value, addressline2:form.addressline2.value, c ...

How can I ensure that my jQuery code only executes after the mobile CSS has been loaded

When it comes to loading my mobile-only CSS, I typically use a media query similar to: <link rel="stylesheet" type="text/css" media="only screen and (max-device-width: 480px)" href="/includes/css/mobile.css" /> However, in addition to these CSS mod ...

The web page's content remains hidden until it is scrolled into view, despite the fact that the page has finished loading

I'm a beginner with Angular and currently working on creating a website. On the following page , when viewed on mobile, I am experiencing an issue where the content doesn't load until it's brought into view by scrolling down the page. I am u ...

Exporting Textures with Custom Offsets to GLTF from Three.js Scene

UPDATE: I was initially puzzled about exporting to obj and mtl formats, but then I stumbled upon the GLTFExporter.js in three.js which allowed me to successfully extract both the geometry and texture from my project. However, a new challenge arose with t ...

height detection is not functioning

Here is a straightforward script that I'm using: var element = document.getElementById("container"); if (element.clientHeight == "372") { element.style.height = "328px"; element.style.marginBottom = "44px"; } else { element.style.height = "21 ...

Guide on setting the dropdown's selected index through JavaScript

Is there a way to use javascript to set the selected value of a dropdown? Here is the HTML code I am working with: <select id="strPlan" name="strPlan" class="formInput"> <option value="0">Select a Plan</option> </select> I am ...

What is the best way to create a promise in a basic redux action creator?

My function add does not return any promises to the caller. Here's an example: let add = (foo) => {this.props.save(foo)}; In another part of my application, I want to wait for add() to finish before moving on to something else. However, I know t ...

Utilizing Loops to Generate Unique CSS Designs on an HTML Page

View reference image ->Take a look at the reference image provided. ->In the image, a for loop is used to create box designs and displayed above. ->The goal is to change the background color and border color of all boxes using a single HTML cla ...

Scrapy and Python data gets corrupted by <br> tags causing issues

As I attempt to extract the text from Amazon reviews using scrapy, I encounter an issue. Reviews with multiple lines have their text separated by "< br >" tags within a span element. So, when I try to scrape the first review, I use this line of code: ...

Python Script for Scanning a Website for a Specific Tag

Currently, I am exploring the process of creating a website monitoring script (which will eventually be set up as a cron job) that can access a specified URL, verify the presence of a specific tag. If the tag is not found or does not contain the expected i ...

Is it necessary to establish a connection to my mongodb database directly within my jest test file, or is it permissible to invoke functions from separate classes that handle the database connection?

Currently in the process of testing my database functions using jest. My javascript file contains a variety of functions that connect to the database, retrieve data, and return an array. The issue I'm facing is when calling these functions from my jes ...

To access a restricted selection of images stored in Firebase

Is there a way to load additional images from Firebase by clicking a button? I created a function that looks like this: onLoadMore() { if (this.all.length > 1 ) { const lastLoadedPost = _.last(this.all); const lastLoadedPostKey = lastLoadedP ...

Creating a dropdown menu using Vue.js

My latest project involves coding an html page that features a drop-down list using HTML, CSS, and VueJS. The goal is to have something displayed in the console when a specific option from the drop-down list is selected. Here's the snippet of my html ...

Determine whether a variable includes an alphabetic character

I need to eliminate any results from an array that include alphabetic characters. To do this, I am using the following code: if(gtin.toString().length != 13 || /[a-z\-]+/ig.test(gtin) == true) { gtin = "null"; } Although it works for some variab ...

Error in Access-Control-Allow-Origin when using Node.js and JSONP

It seems like JSONP eliminates cross domain restrictions. I am currently attempting to create a JSONP service with node and express. Below is a simple example of the code: self.routes['/portfolio'] = function(req, res) { // Website you wis ...

Troubleshooting WordPress <?php body_class(); ?> Problem

After successfully integrating my theme into WordPress, I decided to add WooCommerce to create a shop. However, I encountered an issue where the styles of WooCommerce were not appearing properly. Upon researching, I discovered that the root cause was the a ...