Joomla 3 use form in modal

2019-09-05 00:52发布

问题:

I want to use a jForms form in a Joomla modal window

I use:

  • Joomla 3.4.5
  • Bootstrap 3.3.5
  • jQuery 1.11.3
  • mootools (don't know which version)

I load the needed scripts via JHTML::_('behavior.modal');,
add .modal to the a element and used the Joomla url snippet &tmpl=component for only displaying the component.

The form is displayed in the modal.

Errors
Every time I open the modal, javascript gives me this error
Uncaught TypeError: jQuery(...).find(...).radioToBtn is not a function

The form is still displayed.

If i close it and open it again this error appears
Uncaught TypeError: Cannot read property 'response' of null

Then, after some closing and opening, the form will be displayed double.

回答1:

I kinda solved it.

1. The first step was to minimize the number of loaded scripts.

I unset mootools completly - because no body wants it. I noticed Joomla loaded the bootstrap.min.js, so it was loaded two times, one in my template and one from Joomla.

Now loading scripts:

  • jquery-migrate.js
  • jquery-min.js
  • jquery-noconflict.js
  • caption.js (Maybe someone has an idea for removing it correclty. When I do it I get an error Uncaught ReferenceError: JCaption is not defined)
  • bootstrap.min.js
  • my-own.js
  • and some scripts of an extension...

2. The form component

jForms works with mootools, that's because I switched to Visforms - seems to work fine.

3. Implement the Bootstrap modal

In the index.php after the opening body, I created the "standard modal".

Later the content will be loaded dynamicly into the modal.

<div class="modal fade" id="modal">
  <div class="modal-dialog">
    <div class="modal-content">
      <!--all the content will be loaded here-->        
    </div>
  </div>
</div>

3.1. The Modal trigger

To trigger the modal I have a button or a link.

<a href="#" class="btn callback-modal" type="button" data-toggle="modal" data-target="#modal">Click the button</a>

It's connected to the "standard modal" but with the unique class .callback-modal. So later The script knows what kind of button this is.
(Could have used an ID instead...)

3.2. The Javascript

The function:

// Callback Button
function customModal(modalTrigger, link) {
    var baseURL             = window.location.protocol + "//" + window.location.host + "/";
    var mainModal           = $("#modal");
    var mainModalString     = "#modal";         // not the best solution
    var mainModalContent    = mainModal.find(".modal-content");

    $(modalTrigger + '[data-target="' + mainModalString + '"]').click(function() {
        mainModal.on("show.bs.modal", function() {
            mainModalContent.load(baseURL + link);
        })  
    })
}

Execute the function for our .callback-modal:

customModal(".callback-modal", "index.php?option= SOME COMPONENT tmpl=component");

Because of the &tmpl=component after the link, Joomla will only display the component itselfe.

And because it's a function I can now create as many modals as I want. (It's not working perfectly with multiple modals)

Edit

I optimized the script for more dynamic modals.

Now you don't have to do this extra coding were you tell the script which class and what href the link has (Step 3.2).

In this case I switched from Bootstrap to Uikit, just because I do not understand Bootstraps remote method. I think with Bootstrap 4 the script can be adapted very easily.

Code

At the top of the index file sits again the basic modal:

<div id="modal" class="uk-modal">
    <div class="uk-modal-dialog">
        <div class="uk-modal-header">
            <a class="uk-modal-close uk-close"></a>
        </div>

        <div class="uk-modal-content">
            ...
        </div>
    </div>
</div>

The trigger links look like this:

<a href="some internal link" class="modal-trigger">Open modal</a>

Script:

var $modalTrigger = $(".modal-trigger");
var $modal = $("#modal");
var $modalContent = $(".uk-modal-content");
var spinner = '<div class="uk-modal-spinner"></div>';

if( $modalTrigger.attr("href") ){
    $modalTrigger.attr("data-uk-modal", "{target:'#modal'}");
};

$modalTrigger.click(function() {
    $modalContent.append(spinner);
    $modalContent.load( $(this).attr("href") );
});

$modal.on({
    'hide.uk.modal': function(){
        $modalContent.empty();
    }
});

On every link with the .modal-trigger class it adds the needed Uikit data attributes data-uk-modal", "{target:'#modal'},

grabs the link and loads it into the .uk-modal-content.

All content will be removed after closing the modal.