Enkele formulier validatieset
From Joomla! Documentation
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:
- Gebruiker laad een pagina met een bewerkingsformulier in
- Na het invullen van het formulier klik de gebruiker op de submit knop
- De functie Joomla.submitbutton = function(task) vangt de submit-actie af
- Deze functie zal de validateForm() functie aanroepen in het validate.js bestand
- De validateForm() zal de benodigde data van het formulier ontvangen en deze doorgeven aan de sendForm functie
- Nu zijn we klaar voor het versturen, de sendForm() zal de data naar de server sturen om daar gevalideerd te worden.
- 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.
- 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.