Enkele formulier validatieset

From Joomla! Documentation

This page is a translated version of the page Single form validation set and the translation is 100% complete.
Other languages:
English • ‎Nederlands • ‎español • ‎français
Joomla! 
≥ 3.0
Handleiding
Enkele formulier validatieset

Deze pagina legt uit hoe dezelfde formulier validatieregels voor de client- en serverkant gebruikt kunnen worden. Standaard gebruikt Joomla! PHP formuliervalidatieregels voor de servervalidatie en JavaScriptregels voor de clientvalidatie. Dit betekent dat we alle regels moeten kopiëren die we in PHP en JavaScript beide willen valideren. Hoog tijd om dat anders aan te pakken.

Nog een voordeel van het gebruik van één set validatieregels is dat je dezelfde tekst kan gebruiken voor alle foutmeldingen.

De backend heeft geen speciale code nodig omdat deze altijd al PHP validatieregels heeft gebruikt, dit werkt dus standaard al.

We gaan een paar bestanden aanpassen/bewerken:

  • enquiry.xml (definitie formulier)
  • validate.js (transport)
  • validate.json.php (controller)
  • validate.php (model)
  • edit.php (formulier)
  • en-GB.com_helloworld.ini (taal)

Het proces

De manier waarop dit werkt is door het volgende proces:

  1. Gebruiker laad een pagina met een bewerkingsformulier in
  2. Na het invullen van het formulier klik de gebruiker op de submit knop
  3. De functie Joomla.submitbutton = function(task) vangt de submit-actie af
  4. Deze functie zal de validateForm() functie aanroepen in het validate.js bestand
  5. De validateForm() zal de benodigde data van het formulier ontvangen en deze doorgeven aan de sendForm functie
  6. Nu zijn we klaar voor het versturen, de sendForm() zal de data naar de server sturen om daar gevalideerd te worden.
  7. In het geval dat het antwoord van de server een probleem geeft met de validatie kan het bericht getoond worden aan de gebruiker en het formulier wordt niet ingediend.
  8. In het geval dat het antwoord van de server geen problemen bevat zal het formulier ingediend worden.

De bestanden

enquiry.xml

Laten we voor het formulier met het XML-bestand enquiry.xml beginnen, deze zal 5 velden bevatten:

<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field name="enquiry_id"
		       type="hidden" />

		<field name="title"
		       type="text"
		       label="COM_HELLOWORLD_ENQUIRY_TITLE_LABEL"
		       maxlength="50"
		       required="true" />

		<field name="publish_up"
		       type="text"
		       label="COM_HELLOWORLD_ENQUIRY_PUBLISH_UP_LABEL"
		       hint="dd-mm-jjjj"
		       required="true"
		       validate="hello.date"
		       message="COM_HELLOWORLD_FORM_NO_VALID_DATE_MESSAGE"/>

		<field name="publish_down"
		       type="text"
		       label="COM_HELLOWORLD_ENQUIRY_PUBLISH_DOWN_LABEL"
		       hint="dd-mm-jjjj"
		       field="publish_up"
		       validate="hello.dategreater"
		       required="true"
		       message="COM_HELLOWORLD_FORM_NO_VALID_GREATERDATE_MESSAGE"/>

		<field name="phone"
		       type="tel"
		       label="COM_HELLOWORLD_PHONE"
		       validate="tel"
		       required="false"
		       message="COM_HELLOWORLD_FORM_NO_VALID_PHONE_MESSAGE"/>
	</fieldset>
</form>

Hier hebben we 5 velden: enquiry_id, title, publish_up, publish_down en phone.

  • "'title"': Dit veld heeft geen validatieregel.
  • "'publish_up"': Dit veld heeft een validatieregel van hallo.date.
  • "'publish_down"': Dit veld heeft een validatieregel van hallo.greaterdate.
  • "'phone'"': Dit veld heeft een validatieregel van phone.

validate.js

Dit bestand bevat de code die validatie-aanvraag naar de server verstuurd.

function validateForm(form, xml, group, token) {
	// Load all the form fields
	var filter = '[name^=jform';

	if (group) {
		filter += '\\[' + group + '\\]';
	}

	filter += ']';

	var fields = jQuery('#' + form + ' ' + filter);

	// Collect the fields and their values
	var data = [];

	fields.each(function (key, field) {
		data.push(field.name + '=' + encodeURIComponent(field.value));
	});

	// Send the form with the field info
	return sendForm(data, xml, group, token);
}

/**
 * Validate the fields on the server
 *
 * @param   array   data   An array with the data to validate.
 * @param   string  xml    The name of the XML file to validate against.
 * @param   string  group  The name of the group the fields belong to.
 * @param   string  token  The security token.
 */
function sendForm(data, xml, group, token) {
// Send the data to the server for validation
	return jQuery.ajax({
		async: true,
		url: 'index.php',
		dataType: 'json',
		cache: false,
		method: 'post',
		data: 'option=com_helloworld&task=validate.validateform&xml=' + xml + '&group=' + group + "&" + data.join('&') + '&format=json&' + token + '=1',
		success: function (data) {
			if (data) {
				var msg = '';

				jQuery(data).each(function (index, item) {
					if (item.message.length > 0) {
						var msgtype = item.type;

						msg =
						{
							msgtype: [item.message]
						};
					}
				});

				// Render the message
				if (jQuery(msg).size() > 0) {
					Joomla.renderMessages(msg);
				}
			}
		},
		error: function (request, status, error) {
			var msg = {
				error: [request.status + ' ' + request.statusText + '<br />' + request.responseText]
			};

			// Render the message
			Joomla.renderMessages(msg);
		}
	});
}

validate.json.php

Dit is de controller die de AJAX request ontvangt en deze data doorstuurt naar het model om gevalideerd te worden.

defined('_JEXEC') or die;

/**
 * Validate controller.
 *
 * @package     Helloworld
 * @since       1.0
 */
class HelloworldControllerValidate extends JControllerForm
{
	/**
	 * Add a new lead.
	 *
	 * @return  string  JSON encoded string.
	 *
	 * @since   1.0
	 */
	public function validateForm()
	{
		// Check for request forgeries.
		JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));

		$model = $this->getModel();
		$data = $this->input->post->get('jform', array(), 'array');
		$xml = $this->input->post->getCmd('xml', '');
		$group = $this->input->post->getCmd('group', '');
		$return = array(
			'message' => '',
			'type' => '',
			'continue' => true
		);

		// Validate the posted data.
		// Sometimes the form needs some posted data, such as for plugins and modules.
		$form = new JForm($xml);
		$form->addFormPath(JPATH_SITE . '/components/com_helloworld/models/forms');
		$form->loadFile($xml);

		if (!$form)
		{
			$return['message'] = $form->getErrors();
			$return['type'] = 'error';
			$return['continue'] = false;
		}
		else
		{
			// Test whether the data is valid.
			$validData = $model->validate($form, $data, $group);

			// Check for validation errors.
			if ($validData === false)
			{
				// Get the validation messages.
				$errors = $model->getErrors();

				// Push the validation messages out to the user.
				for ($i = 0, $n = count($errors); $i < $n && $i < 1; $i++)
				{
					if ($errors[$i] instanceof Exception)
					{
						$return['message'] = $errors[$i]->getMessage();
						$return['type'] = 'warning';
						$return['continue'] = false;
					}
					else
					{
						$return['message'] = $errors[$i];
						$return['type'] = 'warning';
						$return['continue'] = false;
					}
				}
			}
		}

		echo json_encode($return);

		jexit();
	}
}

@todo: Gebruik JResponseJson om de resultaten te retourneren.

validate.php

Het model is simpelweg daar om de aanvraag naar Joomla goed te keuren.

defined('_JEXEC') or die;

/**
 * Validate form model.
 *
 * @package  Helloworld
 * @since    1.0
 */
class HelloworldModelValidate extends JModelForm
{
	/**
	 * Method to get the contact form.
	 * The base form is loaded from XML and then an event is fired
	 *
	 * @param   array    $data      An optional array of data for the form to interrogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  JForm  A JForm object on success, false on failure
	 *
	 * @since   1.0
	 */
	public function getForm($data = array(), $loadData = true)
	{
		return false;
	}
}

edit.php

Het formulier dat de werkelijke formulier laat zien. In ons templatebestand zullen we de volgende formulieren hebben:

<form action="<?php echo JRoute::_('index.php?option=com_helloworld&view=enquiry&layout=edit&id=' . $this->item->enquiry_id, false); ?>" method="post" name="item-form" id="item-form">
	<div>
		<?php echo $this->form->getLabel('title'); ?>
		<div class="controls">
			<?php echo $this->form->getInput('title'); ?>
		</div>
	</div>

	<div>
		<?php echo $this->form->getLabel('publish_up'); ?>
		<div class="controls">
			<?php echo $this->form->getInput('publish_up'); ?>
		</div>
	</div>

	<div>
		<?php echo $this->form->getLabel('publish_down'); ?>
		<div class="controls">
			<?php echo $this->form->getInput('publish_down'); ?>
		</div>
	</div>

	<input type="hidden" name="task" value="enquiry.submit">
	<input type="hidden" name="enquiry_id" value="<?php echo $this->item->enquiry_id; ?>">
	<?php echo JHtml::_('form.token'); ?>
</form>
<script type="text/javascript">
	Joomla.submitbutton = function(task)
	{
		if (task == 'enquiry.cancel')
		{
			Joomla.submitform(task, document.getElementById('item-form'));
		}
		else
		{
			jQuery.when(validateForm('item-form', 'enquiry', '', '<?php echo JSession::getFormToken(); ?>')).done(function(result)
			{
				if (result.continue)
				{
					Joomla.submitform(task, document.getElementById('item-form'));
				}
			});
		}
	}
</script>

De validatieregels

Alle aangepaste validatieregels worden bewaard in de administrator/componentes/com_helloworld/models/rules map. Dus we hebben één plek waar alle aangepaste regels staan. Joomla! weet waar de standaardregels staan, de aangepaste regels niet dus de volgende regel code moet nog toegevoegd worden aan het component invoerbestand:

JForm::addRulePath('administrator/components/com_helloworld/models/rules');

hello.date

defined('_JEXEC') or die;

/**
 * Form Rule class that checks for a valid date value.
 *
 * @package     Helloworld
 * @since       1.0
 */
class HelloFormRuleDate extends JFormRule
{
	/**
	 * Method to test the field is not empty.
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the <field /> tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control value. This acts as as an array container for the field.
	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
	 *                                      full field name would end up being "bar[foo]".
	 * @param   JRegistry         $input    An optional JRegistry object with the entire data set to validate against the entire form.
	 * @param   JForm             $form     The form object for which the field is being tested.
	 *
	 * @return  boolean  True if the value is valid, false otherwise.
	 *
	 * @since   11.1
	 */
	public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null)
	{
		try
		{
			JDate::getInstance($value);
		}
		catch (Exception $e)
		{
			return false;
		}

		return true;
	}
}

hello.greaterdate

defined('_JEXEC') or die;

/**
 * Form Rule class that checks for a date is later than another date.
 *
 * @package     Helloworld
 * @since       1.0
 */
class HelloFormRuleDategreater extends JFormRule
{
	/**
	 * Method to test the field is not empty.
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the <field /> tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control value. This acts as as an array container for the field.
	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
	 *                                      full field name would end up being "bar[foo]".
	 * @param   JRegistry         $input    An optional JRegistry object with the entire data set to validate against the entire form.
	 * @param   JForm             $form     The form object for which the field is being tested.
	 *
	 * @return  boolean  True if the value is valid, false otherwise.
	 *
	 * @since   11.1
	 */
	public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null)
	{
		try
		{
			// Check for a valid date
			$date1 = JDate::getInstance($value);

			// Check if the second date is after the first date
			$field = (string) $element['field'];
			$fvalue = $input->get($group . '.' . $field, false);

			if ($value)
			{
				try
				{
					$date2 = JDate::getInstance($fvalue);

					if ($date1 < $date2)
					{
						return false;
					}
				}
				catch (Exception $e)
				{
					return false;
				}
			}
		}
		catch (Exception $e)
		{
			return false;
		}

		return true;
	}
}

Taalbestand

In de vorige codesnippets zijn er een aantal taalstrings gebruikt, vergeet niet om deze aan de juiste taalbestanden toe te voegen. U zal de taalstrings aan de frontend taalbestand toevoegen maar ook aan het backend taalbestand voor het geval u dezelfde validatieregels in de backend wil gebruiken. Een andere optie is alleen de frontend taalbestand te gebruiken en deze zowel in de frontend als in de backend te gebruiken.