2

I am trying work out how I can pop up a modal or open a new window or tab when selecting a button on a form that processes the form and passes to another extension? I can't seem to find any examples of where I could or should implement the trigger to the new window.

My currently working process gets data from a form on the press of a button that calls a subcontroller to prepare the data and then passes to a printing component that handles direct printing to label printers all within the same window. Because multiple components are calling this direct print component I rely on a Back button to take them back to the original component view.

It all works as expected however the end users are getting annoyed as the browser sometimes prompts them to reload the original page. So my thinking, open to alternatives, is to give them a new window/tab that they close and not have to use the Back key.

The button on my form page looks like this;

<button type="button"
        class="btn refresh hasTooltip "
        title="<?php echo Text::_('COM_INVENTORY_BUTTON_POTLABELS_TITLE'); ?>"
        onclick="Joomla.submitbutton('consignments.labelsPots');">
    <span class="icon-print" aria-hidden="true"></span>
    <?php echo 'Pot Labels'; ?>
</button>

In my subcontroller I have this code to get the data from the Form and prepare it for the printing component and then trigger a plugin to invoke the direct printing extension. The final redirect line never gets executed unless the plugin is removed or disabled.

public function labelsPots()
{
    ....prepare $data .....
    //Invoke plugin to redirect to webPrint extension
    $this->dispatcher->trigger('onContentWebprint', array('com_inventory.consignment.potlabels', $data));   
  
    $this->setRedirect(Route::_('index.php?option=com_inventory&view=' . $this->view));
}

In the plugin it is fairly straightforward

public function onContentWebprint($context, $payload)
{
    $this->app->setUserState("webprint.data.context", $context);
    $this->app->setUserState("webprint.data.payload", $payload);
    $this->app->redirect(Route::_('index.php?option=com_webprint&task=simple.array'));
}

And from there the webprint component, which I want to display in a new window/tab, is a simple page which allows them to select from a list of printer that are connect and online and chage quantity of labels.

Most of what I have read involves either adding target attribute to the link, e.g.<a href= .... target="_blank"> which I don't have, or putting some JS on the button to open a modal which I don't think allows me to get my data from the current page and process it in the subcontroller first.

I could be approaching this the wrong way but I seem to have a blockage on how to do it the way I think it should be possible.

1

I think that you could do this using a modal window, but it will be rather involved.

The Joomla MVC tutorial step adding a modal and associated video will provide some background help, but it will need to be adapted a fair bit.

Referring to the code in that tutorial step, these are the main things I think you'd need to change.

  1. Your button which results in the subcontroller being called could be replaced by the modal custom field definition of the tutorial step.

You'd have a field element for it in the XML definition of your form. As you have multiple components using the print facility you'd want to have some way of telling the field get_input() code which component it was and something like the way the code uses $this->id to get the name parameter of the field in the XML file would be possible. (ie set the name parameter different in the XML field for the different components).

  1. Within the html which get_input() produces you'd have to put the javascript code which would make an Ajax call to the server, to the appropriate component, passing up the parameters and receiving the processed data. You'd need to write that server code which handles the Ajax request.

This would then replace your current POST to your subcontroller, and instead of the print controller being invoked via the plugin redirect, your $data would just be passed back down in the Ajax response.

  1. The printer component would run within an iframe in the modal window, which you'd set as the src attribute of the iframe. You'd need to pass the $data to it as a parameter in the HTTP GET request to the print component's URL. You'd also want to use the &tmpl=component option within the iframe URL so that the usual Joomla menu etc isn't displayed within the iframe.

  2. The trickiest bit I think will be injecting the js code which makes the Ajax request into the mechanism which joomla/bootstrap uses to display the modal.

The tutorial code follows the joomla norm of calling bootstrap.renderModal() to set up the html and js for displaying the modal. This is in libraries/cms/html/bootstrap.php, and it makes use of the joomla layout in layouts/joomla/modal/main.php.

You'd need to replace that code to include your js to do the ajax request.

An alternative (which may be easier) is to have a second hidden button which displays the modal (as described in the tutorial and using bootstrap.renderModal), with its src attribute set to the URL of the print component.

Then your real button runs your js code to do the ajax request, and once it has received the $data back it changes the src parameter to include the $data in the URL, and then clicks the button to show the modal.

  1. The modal can be 'closed' just as described in the tutorial, and you don't really need to pass anything back to the main window.

All in all, a fair amount of rework however :-(.

1
  • Thanks for taking the time to try and solve this one, which I think is not possible as a new/modal window is a client side function and I need to process the form on the server side first. I agree that is a lot of reworking so I have thinking about ways to rework the process. – Irata 2 days ago

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.