2

I've just coded a module in J!3.7 which should auto-generate the values of optional fields based on another required field value on save. I know that I can check values using a rule class but I had no luck overwriting the form fields there so I think it's just not possible this way. Unfortunately, I haven't found any documentation about this. I'm using a subform so things also get a bit more complicated. In my test()-function

$input->get( 'params.gmcp_content.gmcp_content0.gmcp_lng' ); // returns 8.4368239

returns the expected value which was entered manually and saved properly before to have test case. So I tried this to set the value:

$input->set( 'params.gmcp_content.' . $key . '.gmcp_lng', $lng );

But this didn't work. Neither did this:

$form->setValue( 'params.gmcp_content.' . $key . '.gmcp_lng', null, $lng );

When I dump the post array, it looks like this:

Array
(
    [jform] => Array
        (
            [title] => Locations
            [params] => Array
                (
                    [gmcp_content] => Array
                        (
                            [gmcp_content0] => Array
                                (
                                    [gmcp_contact_id] => 2
                                    [gmcp_lat] => 49.3161506 // entered manually for testing
                                    [gmcp_lng] => 8.4368239 // entered manually for testing
                                )
                            [gmcp_content1] => Array
                                (
                                    [gmcp_contact_id] => 1
                                    [gmcp_lat] => 
                                    [gmcp_lng] => 
                                )
                        )
...
)

So how can I manipulate form data before the module params get saved in the database?

2 Answers 2

3

If you're talking about module definition file that holds module options you can't do much in the file using framework it-self. But you can do it in 3 other ways.

In the UI by Java Script

Just create custom field class that will include Java Script into document head that will perform a sample data fill on save/apply button click. Here is some short tutorial about creating custom Joomla! form field. It requires from you both PHP, Joomla Framework and Java Script knowledge but it gives you most possibilities. If its only about changing settings depending on other input values in form. Its the best option.

In module helper

If you don't need the data to alter system behaviour (for example by selecting a layout, bootstrap size or caching) you can alter the data when it is retrieved in your module helper (or directly in your module main file). You should use that one if you need to change data pushed to the module depending on values from the database or other extensions. That way the module settings holds only the params, and processing is made by the module it-self.

As a separate plugin

As @Rico pointed out there is also a possibility to use a plugin from extension group and onExtensionBeforeSave event. If you gonna need to install both module and plugin at once use Package extension type. Details about creating package can be found here. This is the last resort. It makes the job done but also creates a problem if a data sources changes. Then you would have to update the module too (at least open and save).

9
  • Thanks for your help Artur. By using the module helper you mean preparing the data every time before it gets displayed on the website? But that way there's no way to save changes permanently to the database, is it?
    – Rico
    Commented May 23, 2017 at 6:41
  • You're right. There isn't and there shouldn't. You should not update your data from your module, you can do a manual sql query but have in mind that preparing your data in helper is a common thing. Its nothing wrong if it doesn't cause a performance drop. If you really need to have this data in the database cause it's used by other extensions you can always use the first solution. In other case, just prepare the data in a helper. Commented May 23, 2017 at 10:54
  • Artur, I created a custom field to include javascript. Now I need to get data from the server via an ajax call. I've already found this thread joomla.stackexchange.com/questions/15802/… and now I'm facing the same problem ... it seems you can use com_ajax only from the frontend but not from within the admin area. I can reach the helper.php using com_ajax (status 200) but I receive an error object including the message "Module mod_mymodule is not published, you do not have access to it, or it's not assigned to the current menu item.".
    – Rico
    Commented May 23, 2017 at 18:22
  • I can't use a physical path like '/modules/my_module/ajax.php' either because Joomla rebuilds it internally and returns 404. Am I still using it the wrong way or is it just impossible? Thanks again for clarifying this, can't believe how long I've been struggling with this now.
    – Rico
    Commented May 23, 2017 at 18:22
  • But why are you trying to get the data with ajax? Don't you have your data already in the form? Access the form inputs and depending on values fill the desired fields. The point in using Java Script is to alter the data using the form you already have. Why do you use ajax for that if you already have the data in inputs. Commented May 23, 2017 at 18:28
0

Well, after a long series of struggles I've found at least one way which finally worked for my situation. I had to code a plugin, a fact which feels very counter-intuitive and oversized to me ... what I don't like about this solution is that it's not "bundled" with the module what it should be. Anyways here's my solution:

// IMPORTANT:
// in your "myplugin.xml": "group" must be "extension":
// <extension version="3.1" type="plugin" group="extension" method="upgrade">
// in your "myplugin.php": class name must start with "PlgExtension"

class PlgExtensionMyPlugin extends JPlugin {

    public function onExtensionBeforeSave( $context, &$table, $isNew ) {

        // not the right context
        if( $context !== 'com_modules.module' ) {
            return true;
        }
        // not the right module
        if( $table->module !== 'mod_mymodule' ) {
            return true;
        }

        // get the params of the module
        $params = json_decode( $table->params );


        // ... process $params in some way


        // build params json string and assign new params value to module reference
        $table->params = json_encode( $params );

        return true;
    }
}

Don't forget to ACTIVATE your plugin after installing it.

8
  • I still don't get why you could not process the data directly in the form using for example the java script. This would make it work without additional extensions. if you need to install it in a single package you can create something like this docs.joomla.org/Package Commented May 24, 2017 at 12:15
  • When I hit save, all the client has at that moment is the contact_id. To get the geocoords of the contact I have to: - get the address(es) based on the contact_id(s) - geocode the address(es) and assign the data to the corresponding fields How can I do that without interacting with the database (php)?
    – Rico
    Commented May 24, 2017 at 12:21
  • 1
    So you should use module helper for that for sure. Now if some one changes the contact data you should update the module settings as well. If you would use module helper for that kind of function you would be able to validate if user did not moved automaticly when data is displayed. Geocoding data can be stored in cache easly. And user doesn't have to update address in two places (one in contact details and then updating the module). There would be no need for additional plugin and there would be no hassle with managing the data. Commented May 24, 2017 at 12:27
  • That's actually a good point that I would have to update the geoinfo in two places if addresses changed. I didn't have that in mind. Actually I thought it would be very time-consuming to geocode addresses "on the fly" but I haven't considered using the cache. Your suggestion is obviously the cleaner solution.
    – Rico
    Commented May 24, 2017 at 12:55
  • Another solution that just came to my mind is to store the geocode info within custom fields of the contact and update it whenever a contact address changes. There would still be the need of a plugin that catches the onbeforesave event though but there would be just one call to the gecode api instead of 10 or 12 for geocoding all the contacts again which should be less error prone.
    – Rico
    Commented May 24, 2017 at 12:57

Your Answer

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

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