Heads Up: This is the documentation for Joomla 3

We recommend using the Documentation for Joomla 5

It is more up-to-date and extensive. Most of it applies retrospectively to Joomla 3.

Joomla 5 Notice

We are pleased to announce that as of January 29, 2024, all of our Joomla extensions are compatible with Joomla 5.

For all who are still updateing from Joomla 3 to Joomla 4: Joomla 4 Migration instructions are available here:

There is now a separate Documentation for Visforms for Joomla 4 and for Visforms for Joomla 5!

Custom Submit Handler - Example for the development of a custom Visforms Plugin

Since Visforms 3.10.0 it is possible to add a custom submit handler to your forms by only creating a custom Visforms Plugins. In previous Visforms versions this was only possible, if you created a template override of the file validation.php, which was very often modified, so that it was often necessary to adapt this override after Visforms updates.

Mostly anybody has a different requirement for their custom submit handler. This is, why you have to create a custom Visforms plugin that manages your individual submit functions. This requires a bit of coding experience with php and javascript or willingness to learn. We provide you with a plugin master, that already contains the major code structures, which you have to adapt to your specific needs. The following article explains step by step, how you can do this and gives code examples for some submit handler actions.

Create you own plugin

Download the plugin master for Joomla 4 or the plugin master for Joomla 3, depending on which Joomla version you use. Unzip the archive. You will find three files in the unzip plgmaster.zip. The index.html, the plgmaster.xml and the plgmaster.php. Please Note: You need Visforms 3.10.0 (or higher) in order to use this feature. If you want to create a custom submit handler, that works with forms published by the Content Plugin Visforms Form View (which is part of the Visforms Subscirpiton) you need a Visforms Subscription 3.0.0 or higher as well.

The only purpose of the index.html is to protect your plugin folder. You do not need to modify this file.

The plgmaster.xml is the manifest master of the plugin. This file controls the installation process of the plugin and contains meta information about the plugin (like date, author...).

The plgmaster.php contains the code, which is executed by the plugin.

Name your plugin

First of all, you must give your plugin a unique name. The name is a lowercase string, without blanks or special characters, for example "mycustomsubmithandler". You have to replace the string "plgmaster" several times with your plugin name. Rename the files plgmaster.xml and plgmaster.php, by replacing "plgmaster" with your plugin name. Then you have to replace the string "plgmaster" inside the renamed files. Open each file with an editor appliction of your choise.

You have to replace the string "plgmaster" three times in the renamed plgmaster.xml. In <name>plgmaster</name> and in <filename plugin="plgmaster">plgmaster.php</filename>

You have to replace the string "plgmaster" one time in the renamed plgmaster.php, in order to rename the php class properly. Replace "plgmaster" in class plgVisformsPlgmaster extends JPlugin. You can read the class name more easily, if you start it with a Capital letter in this case. But this is not necessary. The code works with a lowercase name in the class name as well.

Adapt meta information

After that you should adapt the meta information in the renamed file plgmaster.xml, by changing the values of some XML-nodes. An XML-node consists of two elements - an opening element (i.e. <author>) and a closing element (i.e. </author>) - and a text (the actualy information transported by the xml node) between these elements. Please adapt the texts in the following XML-nodes. Some informations are optional.

  • <author>: Autor
  • <creationDate>: Creation date
  • <copyright>: Copyright Information (not required)
  • <license>: Licensetype (not required)
  • <authorEmail>: Author Email (not required)
  • <authorUrl>: Author Url (not required)
  • <description>: Description, displayed in the adminstration panel of the plugin

Keep all other XML-nodes unchanged.

The Plugin code

The plugin code is located in the renamed file plgmaster.php. Open this file and take a look at our demo code.

The function onVisformsFormPrepare is executed just before the form is displayed

Code, located in the public function onVisformsFormPrepare($context, $form, $menuparams) is executed just before the form is displayed. You can use this funtion to add custom javascript to the form or to manipulate the form and the fields.

You can use custom javascript in order to add hidden controls dynamically to your form and set the values in this controls dynamically. These values are submitted with the POST, so that you can react to their values afterwards. Or you can simple block the submit action with javascript.

The function onVisformsBeforeFormSave is executed before Visforms starts saving the submitted user inputs on the server.

Code, located in the function public function onVisformsBeforeFormSave($context, $form, $fields) is performed before user inputs are further processed (store data in data base, send mails...) by Visforms on the server. This is the place, where you can validate and evaluate values of dynamically set controls and use these values to change for example form options, which are used in the following processes by Visforms.

Basic code of function onVisformsFormPrepare

public function onVisformsFormPrepare($context, $form, $menuparams)
	{
		// Skip plugin if context is wrong
		$allowedContexts = array('com_visforms.form', 'mod_visforms.form', 'plg_vfformview.form');
		if (!in_array($context, $allowedContexts)) {
			return true;
		}
		$app = JFactory::getApplication();
		// only perform action, if we are in front end
		if ($app->isAdmin()) {
			return true;
		}
		//if $form->parentFormId is not set, Visforms or Content Plugin Form View version is to old
		if (!isset($form->parentFormId)) {
			return true;
		}
		// get value of id attribute of the form which is going to be displayed for furhter use
		$parentFormId = $form->parentFormId;
		// add custom submit handler function to the form	
		$script = 'jQuery(document).ready(function () {
			//add custom submit action function to form
			window["' . $parentFormId . 'SubmitAction"] = function (form) {
			// your code in here
			//return false to prevent form from being submitted, return true, if submithandler performs another action but form should be send
				return true;
			};
		});';
		JFactory::getDocument()->addScriptDeclaration($script);		
		// End: add custom submit handler function to the form	
	}

The $context

The $context tells you, whether the form is displayed by a menu item, in a module or using the Content Plugin Visforms Form View (Subscription). You can use this parameter for example in order to restrict a custom submit handler to forms that are displayed in a module, only.

  • $context === 'com_visforms.form' : Form is displayed via men item of type Visforms >> Form
  • $context === 'mod_visforms.form' : Form is displayed as Visforms module
  • $context === 'plg_vfformview.form' : Form is displayed using the Content Plugin Form View.

It is a good practice to make sure, that you code is only excuted when this is truely necessary. Use the variable $allowedContexts to control, in which context the code is executed.

The $form

This parameter contains a complete Visforms form object. $form->id will return the form id of the current form. $form->parentFormId returns the HTML id attribute of the <form> element, to which the form is attached.

You can use conditions like if ($form->id !== 1) {return true;} in order to make sure that the code is only execute if the form id is 1. Or you can implement different code for different forms.

	if ($form->id === 1) {
		// do stuff for form 1
	}
	if ($form->id === 2) {
		// do stuff for form 2
	}

The $menuparams

If you implement a custom submit handler you do not need this parameter. It could be used to decide dynamically, whether the form title is displayed or not.

The Javascript Submit Handler function

If a user tries to submit the form, Visforms first validates the user inputs with Javascript . Then it will check if there exists a Javascript function with a specific name for this form. The function name consists of the id of the HTML-form element ($parentFormId) and the string SubmitAction. If this javascript function exists, Visforms will execute then this function and it can be used to perform custom javascript code. Further on, depending on the return value of this function Visforms will either prevent the user from submitting the form or not. If the return value is "true", the form is submitted, if it is "false", the user cannot submit the form. Please make sure, that you always use the intended return value.

Basic code of function onVisformsBeforeFormSave

	public function onVisformsBeforeFormSave($context, $form, $fields)
	{
		// Skip plugin if context is wrong
		$allowedContexts = array('com_visforms.form', 'mod_visforms.form', 'plg_vfformview.form');
		if (!in_array($context, $allowedContexts)) {
			return true;
		}
		$app = JFactory::getApplication();
		// only perform action, if we are in front end
		if ($app->isAdmin()) {
			return true;
		}
		// your code in here
		return true;
	}

Please check out the description of the function onVisformsFormPrepare for further information about the function parameters. $form->parentFormId is only needed in front end and therefore not a parameter of this function.

Example code 1 - Prevent submit, if a user is not logged in

Adapt onVisformsFormPrepare

Replace the basic code in the renamed file plgmaster.php between // add custom submit handler function to the form and // End: add custom submit handler function to the form with the following code. This codes checks, if a user in logged in. If not, a message is displayed when the user tries to submit the form and the form cannot be submitted.

	// add custom submit handler function to the form	
	$user = JFactory::getUser();
	// user is not logged on. Add Javascript that prevent form from being send
	if (!$user->id) {
		$script = 'jQuery(document).ready(function () {
					//add custom submit action function to form
					window["' . $parentFormId . 'SubmitAction"] = function (form) {
						alert("Please log in first");
						return false;
					};
				});';
		JFactory::getDocument()->addScriptDeclaration($script);
	}

Adapt onVisformsBeforeFormSave

Please replace // your code in here with the following code

	$user = JFactory::getUser();
		if (!$user->id) {
			$message = 'Please log in first';
			$app = JFactory::getApplication();
			$input = $app->input;
			$return = $input->post->get('return', null, 'cmd');
			$url = (!empty($return)) ? base64_decode(strtr($return, '-_,', '+/=')) :  'index.php';
			$app->redirect(JRoute::_($url, false), $message, 'warning');
			$app->close();
		}

Example code 2 - Add a hidden control dynamically to the form and set the value dynamically, depending on a user action

For this example we assume, that you have added a second field of type submit to your form. Depending on which submit button the user clicks, we will set a value in a hidden control, which we add dynamically to our form using javascript. The php code, that is executed after the form is submitted, will do different things then, depending on the value in this hidden control. In this example, the result and the receipt mails are only send, if the user hit the 2. submit button. Please replace the base code in the renamed plgmaster.php between // add custom submit handler function to the form and // End: add custom submit handler function to the form with the following code.

(One advantage of creating controls dynamically is, that these controls are not part of the form configuration. So they are not stored in the database or added to any mails. The 2. submit button has a class "formready", which can be set in the field configuration..)

Apdapt onVisformsFormPrepare

	$script = 'jQuery(document).ready(function () {jQuery("<input/>",
		{"id" : "'. $parentFormId .'myhiddenfield", 
		"type" : "hidden", 
		"value" : "0", 
		"name" : "myhiddenfield"}).appendTo("#'.$parentFormId.'");
		//add custom submit action function to form
		window["'.$parentFormId.'SubmitAction"] = function (form) {if (jQuery(form.submitButton).hasClass("formready"))
		{
			jQuery("#'.$parentFormId.'myhiddenfield").val("1");
		}};
	});';
	JFactory::getDocument()->addScriptDeclaration($script);

Adapt onVisformsBeforeFormSave

Please replace // your code in here with the following code

	$formisready = $app->input->post->get('myhiddenfield', "0", 'STRING');
	if (!empty($formisready)) {
		$form->emailresult = 1;
		$form->emailreceipt = 1;
	}

Finalisation and Installation

  • create a zip archive of the folder with your modified files.
  • Install the extension using the Joomla! Extension Manager
  • Publish the plugin in the Plugin Manager
  • Test the plugin

Article list