melsenc Posted August 30, 2021 Report Share Posted August 30, 2021 (edited) Hi all, I wanted to share a solution I came up with, which might be helpful for you. Problem: I have recently been trying to streamline page loading times, and one of the ways I've done this is to move record update datapages to Bootstrap 5 modals. It was working great for me with single record update datapages embedded in modals, but when it came to a report datapage, with a bulk edit feature, I was stumped. See the attached image. Basically, when I clicked the edit button, the pop-up for bulk edit would show up, but it would be BEHIND the modal (see my attached screenshot). Since I have my modal set to static background, that basically meant I wasn't able to edit anything in the pop-up window until I closed the modal. Not helpful! Solution: Use jQuery to assign a .click() handler to any bulk edit buttons in my datapage that is embedded in the modal. The .click() handler will wait half a second (to give the bulk edit pop-up time to be written to the page), then it will move the bulk edit pop-up div to inside the modal body. This solution is only for situations where you're including jQuery and Bootstrap 5. Here's my html modal, which lives at the bottom of my html page where the first datapage is embedded: <div class="modal fade" id="cb-modal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="imgModalLabel" aria-hidden="true"> <div id="cb-modal-dialog" class="modal-dialog modal-larger-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="cb-modal-title">Modal title</h5> <button type="button" class="btn-close bg-transparent" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> <div id="cb-modal-body" class="cb-form-fluid cb-form-resp"></div> </div> </div> </div> </div> The datapage that is embedded in that html page happens to be a report style datapage. Every record includes a link which will dynamically embed a second datapage in my modal, and open it. Complete with params. Here is the code for one of my links: <a href="#" role="button" data-bs-toggle="modal" data-bs-target="#cb-modal" onclick="openModal( 'Edit/Add Items', '1dae6000bcb0b9a06b9841e2a9c0', '?cbResetParam=1&garments_CustomerInvoiceNo=[@field:PSST_CustomerInvoiceNo]&garments_TrackingNo=[@field:PSST_TrackingNo]&garments_Order_id=[@field:PSST_workOrder_id]&garments_CustCode=[@field:Garments_Items_CustCode]&garments_ShipVia=[@field:Garments_Items_ShipVia_endcodedForURL]&garments_ShipDate=[@field:PSST_ShipDate]&garments_Distributor=[@field:Garments_Items_Distributor_encodedForURL]&garments_Whse=[@field:PSST_Whse]&garments_CustomerName=[@field:Garments_Items_CustomerName_encodedForURL]&garments_CustomerPO=[@field:Garments_Items_CustomerPO_encodedForURL]&garments_CustomerAccount=[@field:Garments_Items_CustomerAccount]' );">Edit/Add Items</a> Here is my function for openModal(), saved in an external javascript file, which is included with my html page: // function - deploy DP in modal function openModal(modalTitle, appKey, params) { $('#cb-modal-body').html(''); deployDP('cb-modal-body', appKey, params); $('#cb-modal-title').html(modalTitle); // draggable modal $(".modal-header").on("mousedown", function(mousedownEvt) { var $draggable = $(this); var x = mousedownEvt.pageX - $draggable.offset().left, y = mousedownEvt.pageY - $draggable.offset().top; $("body").on("mousemove.draggable", function(mousemoveEvt) { $draggable.closest(".modal-content").offset({ "left": mousemoveEvt.pageX - x, "top": mousemoveEvt.pageY - y }); }); $("body").one("mouseup", function() { $("body").off("mousemove.draggable"); }); $draggable.closest(".modal").one("bs.modal.hide", function() { $("body").off("mousemove.draggable"); }); }); } function deployDP(containerID, appKey, params) { var params = params || ''; var dataPageScript = document.createElement("script"); var container = document.getElementById(containerID); dataPageScript.src = cbDataPagePrefix + appKey + '/emb' + params; container.innerHTML = ''; container.appendChild(dataPageScript); } Finally, in the Footer in the Configure Results Page Fields section of my second datapage - the one that is embedded dynamically within the modal - I have this code: <script type="text/javascript"> document.addEventListener('DataPageReady', function (event) { $('#cb-modal .cbResultSetBulkEditActionLink').click(function () { setTimeout(function () { // gives the bulk edit update form time to load if (document.getElementById('BulkUpdateForm') && document.getElementById('cb-modal')) { $('#cb-modal div.modal-body').append($('#BulkUpdateForm')); // moves the bulk edit update form inside the modal body, thereby making it editable while the modal is open. } }, 500); }); $('#cb-modal .cbResultSetBulkDeleteActionLink').click(function () { setTimeout(function () { // gives the delete confirmation time to load if (document.getElementById('Alert') && document.getElementById('cb-modal')) { $('#cb-modal div.modal-body').append($('#Alert')); // moves the delete confirmation alert inside the modal body. } }, 500); }); }); </script> I know this is a really specific example, but it seemed to me like something that could come up for other people, so I figured I'd share! Hope this is helpful. Edited August 30, 2021 by melsenc Added code to make delete alert pop-up also show TellMeWhy and Kurumi 2 Quote Link to comment Share on other sites More sharing options...
gscavalry Posted December 1, 2021 Report Share Posted December 1, 2021 Hello melsenc, Thank you for sharing this. It was very helpful to me in building my own varying modal content. If anybody else is using bootstrap 5 and just wants the functionality of dynamically embedding scripts to a modal (say, to vary a single record update DataPage), I made it work using the data-bs-* attributes framework shown here: https://getbootstrap.com/docs/5.0/components/modal/#varying-modal-content. This revision removes the need for jquery (removed from bootstrap 5) but also removes the functionality that melsenc had of dragging the modal and allowing bulk edit on a report DataPage. Once my js improves maybe I can add those in (I'm still very novice, as you more experienced programmers may detect in my code). I've also added a few clarifications if you were trying to get the code melsenc posted to work. Unless I am mistaken (very real possibility) what melsenc's code does is reconstruct an embed script with parameters already set. My HTML code for the modal generally mirrors that of melsenc, only revisions are the class for the modal size is "modal-lg" instead of "modal-larger-dialog": <div class="modal fade" id="cb-modal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="cb-modal-title" aria-hidden="true"> <div id="cb-modal-dialog" class="modal-dialog modal-lg"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="cb-modal-title">Modal title</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> <div id="cb-modal-body"></div> </div> </div> </div> </div> My anchor element (link) code in the HTML Block field of my tabular report is below. You will notice that I'm not using onclick to call the function and pass function parameters, but rather passing the info as data-bs-* attributes to the function triggered by the event listener. You may also notice that what melsenc has named appKey I have named data-bs-dpkey, which is the 28-character string that identifies the DataPage you want to embed in the modal. You can get this string from the embed script when you deploy the DataPage--it's the string between "/dp/" and "/emb". For security purposes, I have replaced the actual string with "###..." <a data-bs-dpkey="############################" data-bs-param="?cbResetParam=1&parameterNameYouArePassing=[@field:parameterFieldYouArePassing]" data-bs-target="#cb-modal" data-bs-title="Title You Want for the Modal" data-bs-toggle="modal" href="#">Edit Something</a> My javascript is kept in an external file and it basically follows the structure shown in the bootstrap 5 documentation. As I said, it doesn't (yet) have the functionality of a draggable modal or the delay melsenc wrote to deal with the bulk edit issue. One thing I couldn't find in melsenc's code is where the variable cbDataPagePrefix was defined. I'm assuming this is the prefix that defines your caspio account so it would make sense to not show where it is defined. I defined my account in the function (replaced with ######## in this example). Perhaps there is a better way to handle this? var Modal = document.getElementById('cb-modal'); Modal.addEventListener('show.bs.modal', function (event) { // Button that triggered the modal var button = event.relatedTarget // Extract info from data-bs-* attributes let newModalTitle = button.getAttribute('data-bs-title'); let datapageKey = button.getAttribute('data-bs-dpkey'); let params = button.getAttribute('data-bs-param'); // If necessary, you could initiate an AJAX request here // and then do the updating in a callback. // // Update the modal's content. var modalTitle = Modal.querySelector('#cb-modal-title'); var modalBodyInput = Modal.querySelector('#cb-modal-body'); var dataPageScript = document.createElement("script"); var cbDataPagePrefix = "https://########.caspio.com/dp/"; dataPageScript.src = cbDataPagePrefix + datapageKey + '/emb' + params; modalTitle.textContent = newModalTitle; modalBodyInput.innerHTML = ''; modalBodyInput.appendChild(dataPageScript) }) Hope this helps someone! Kurumi 1 Quote Link to comment Share on other sites More sharing options...
Kurumi Posted April 8, 2022 Report Share Posted April 8, 2022 Hi! I would like to share this helpful video from Caspio Labs about using modal in DataPages: Check the description to download the files needed. Quote Link to comment Share on other sites More sharing options...
GoodBoy Posted July 17, 2022 Report Share Posted July 17, 2022 Hello @melsenc, this is a good solution! I have encountered this issue as well when I put my results page in a modal and I just added some CSS to resolve it. In my solution, I used the position and z-index property to show the bulk edit form in front of my modal. <style> #BulkUpdateForm { position: fixed !important; z-index: 999 !important; } </style> Quote Link to comment Share on other sites More sharing options...
GoodBoy Posted July 18, 2022 Report Share Posted July 18, 2022 Just to add, if ever you encounter another issue about bulk update form fields being unclickable, then you may insert the code below inside the footer of results page. This is also an issue in Bootstrap where the modal steals the focus of other elements, hence they are unclickable. <script> $(document).off('focusin.modal'); </script> Here is the thread I used as a reference: https://stackoverflow.com/questions/38568621/cannot-type-or-even-focus-in-input-type-text-while-bootstrap-modal-is-open/38614737#38614737 Quote Link to comment Share on other sites More sharing options...
GoodBoy Posted July 18, 2022 Report Share Posted July 18, 2022 It seems that Caspio has a new article to implement modal in our application. This will be helpful! https://howto.caspio.com/tech-tips-and-articles/advanced-customizations/open-details-datapages-in-a-lightbox/ Quote Link to comment Share on other sites More sharing options...
sandy159 Posted October 5, 2022 Report Share Posted October 5, 2022 Hi all, I had the similar issue as GoodBoy but with the Inline Delete modal window that was not visible. I added the following modifications to the DataPage with the modal. Header: <style> #Alert{ position: fixed !important; z-index: 1100 !important; } </style> Footer: <script type="text/javascript"> $('.cbResultSetActionCell a').on('click', function(e) { const myInterval = setInterval( function() { if($("#Alert .ActionButton").length !=0 ){ $('#Alert .ActionButton').on('click', function(e) { $("#cb-modal").modal('hide'); }) clearInterval(myInterval); } } , 100); }) </script> Quote Link to comment Share on other sites More sharing options...
Kurumi Posted November 25, 2022 Report Share Posted November 25, 2022 Hi! Just an update - if you have a modal that is showing behind the Results Page, you can use this code in the Header: <style> .modal { z-index: 9999 !important; } </style> In addition, if you would like to automatically adjust the size of the modal based on its content. You can use this code in the Header as well: <style> body .modal-dialog { /* Width */ max-width: 50%; width: auto !important; } </style> Quote Link to comment Share on other sites More sharing options...
Kurumi Posted January 31, 2023 Report Share Posted January 31, 2023 Hello - In addition to the previous post, if you have a modal and Form Elements that are not showing such as AutoComplete, Dropdowns, and Date Pickers, you can use a custom CSS to show these elements in front of the modal. Insert this code in the Header of the DataPage. <style> .modal-backdrop{ z-index:4 !important; } .modal { z-index: 5 !important; } .header-navbar{ z-index: 3 !important; } </style> Quote Link to comment Share on other sites More sharing options...
futurist Posted June 20, 2023 Report Share Posted June 20, 2023 Hi, sharing this bulk edit feature I came up with that you might find useful: Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.