1

I have created a Joomla module that renders a set of headlines in a widget, with links to the main item. It loads these headlines from either a Joomla category or an RSS feed, and is extensible so I could add further data sources.

In the config XML, I've got a select field to pick the data source, and subsequent fields that use showon to enable one or more of them depending on which source is picked. This works well.

Now I want to move the code for the data sources into separate plugins, to make it more easily extensible. But I'm running into a stumbling block over how to show fields from these plugins in the module config.

I can see how to create a plugin field in the module which will allow me to offer a list of the relevant plugins, but I also need to be able to pull in config fields from the selected plugin.

I know I could just have the config for the plugins in the plugins themselves, but I would prefer to have it at the module level because you might want more than one widget on your site with different config but using the same plugin.

I'm currently looking at either creating a custom field type, as per this question on SO or to use a subform.

However, as far as I can see, this only allows me to create a single field; what I need is to create an arbitrary number of fields, and also to link them back to the plugin list field so they can be shown or hidden as appropriate.

Can anyone give me some advice on how to achieve this?

Thank you!

1 Answer 1

3

No answers here, but I have managed to work it out for myself. The answer is actually to use both of the solutions I had in mind already -- a custom field type and a subform.

My solution works like this: I have created a custom field type that overrides the subform field type, specifically overriding the formsource behaviour.

The standard subform field type takes a formsource attribute, which contains the path to another XML file with the form definition that you want to include.

My class overrides this, and instead of loading an external XML file, it generates one for itself by triggering an event, and reading the data returned to it by the plugins. Each plugin responds with its own list of config parameters which are then combined into a form XML string.

jimport('joomla.form.helper');
JFormHelper::loadFieldClass('subform');

class JFormFieldFieldsFromPlugins extends JFormFieldSubform {
    protected $type = 'FieldsFromPlugins';

    public function getInput() {
        //override $this->formsource that the main Subform class uses.
        $this->formsource = $this->buildSubformFromPlugins();
        return parent::getInput();
    }

    private function buildSubformFromPlugins()
    {
        JPluginHelper::importPlugin('myPluginType');
        $dispatcher = JEventDispatcher::getInstance();
        $results = $dispatcher->trigger('onGetPluginFields', []);
        // .... now build XML string from $results ....
        return $xml;
    }
}

That's it in a nutshell.

However, there were a few other things the caught me out here that are worth mentioning, for completeness.

  • The fields in the subform are handled independently of fields in the main form. I wanted to have a main field that offered a select list of plugins, and for only the relevant plugin fields to be shown. This is done using a showon attribute in the XML. However showon doesn't work between the subform and the main form. The work-around for this was to move the select list into the subform. This isn't ideal as it means there's now a block of XML in my PHP code that would be better in the module's XML file, but it does at least work this way.

  • The default layout for a subform has all of the fields indented by a couple of hundred pixels. I didn't want this, but it took quite a bit of effort to get rid of it. In theory, you can override the layout by writing a getLayoutPaths() method in the class, but that doesn't work well for subforms because the override layout path is inherited by all the sub-fields as well. I worked around this by loading the default paths as well as the override path into my getLayoutPaths() method. This works, although it does feel like a bit of a fudge. I'm considering offering a patch for Joomla to avoid some of the ugliness here.

This has been a good learning experience for me. I'm glad I had a bit of free time to experiment with it though, because it wasn't obvious and not well documented. I hope some of this write-up is useful to anyone else trying to do something similar.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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