Gran pregunta, y una que me tomó mucho tiempo para descubrir la mejor manera de resolverla.
El CodeIgniter Form Validation library es excelente, pero solo se puede usar con las vistas y los controladores adecuados, por lo que no funciona de la caja cuando está desarrollando una etiqueta frontal.
Normalmente, la forma preferida de enviar un formulario de cliente es registrar una 'Acción' en su archivo upd.addon.php (supongo que lo ha hecho para su función submit_form()
). A continuación, se le asigna un número, que puede publicar con la url /index.php?ACT=37
o algo similar. Este es un buen sistema, porque significa que sabemos que el envío del formulario provino de nuestro módulo. Sin embargo, con los formularios de entrada, esto es un obstáculo, porque significa que no podemos repoblar los campos de entrada. Por lo tanto, necesita configurar el formulario de entrada para publicar de nuevo en la URL actual, y esperar hasta que el motor de la plantilla intente representar su etiqueta antes de gestionar el envío del formulario.
La manera más fácil y visualmente más fea de lograr esto es usar $this->EE->output->show_user_error(FALSE, array_of_errors)
. Puede usar esto desde una acción o dentro de su código de módulo. Muestra la página gris estándar de mensaje de EE que todos hemos crecido para conocer y odiar.
Con ese tipo de introducción, probablemente sabía que la solución no iba a ser tan simple, ¿verdad? Aquí está un esqueleto de una función de etiqueta que implementa la comprobación de errores en línea:
function my_form()
{
// load default tag variables
$tag_vars = array();
$tag_vars[0] = array(
'first_name' => '',
'error:first_name' => '',
'last_name' => '',
'error:last_name' => ''
);
// handle a form submission
if ($this->EE->input->post('my_form_hidden') == '1'))
{
// load POST data into tag
$tag_vars[0]['first_name'] = $this->EE->input->post('first_name', TRUE);
$tag_vars[0]['last_name'] = $this->EE->input->post('last_name', TRUE);
// use CI validation library to check submission
$this->EE->load->helper('form');
$this->EE->load->library('form_validation');
$this->EE->form_validation->set_rules('first_name', 'lang:first_name', 'required');
$this->EE->form_validation->set_rules('last_name', 'lang:first_name', 'required');
$valid_form = $this->EE->form_validation->run();
if ($valid_form)
{
// probably save something to database, then redirect
}
else
{
$form_errors = array();
foreach (array('first_name', 'last_name') as $field_name)
{
$field_error = form_error($field_name);
if ($field_error)
{
$form_errors[] = $field_error;
$tag_vars[0]['error:'.$field_name] = $field_error;
}
}
if ($this->EE->TMPL->fetch_param('error_handling') != 'inline')
{
// show default EE error page
return $this->EE->output->show_user_error(FALSE, $form_errors);
}
}
}
// parse and output tagdata
$out = $this->EE->functions->form_declaration(array(
'action' => $this->EE->functions->fetch_current_uri(),
'hidden_fields' => array('my_form_hidden')));
$out .= $this->EE->TMPL->parse_variables($tagdata, $tag_vars);
return $out.'</form>';
}
De esta manera, el diseñador puede especificar error_handling="inline"
en la etiqueta si quieren errores en línea, de lo contrario sólo será redirigido al formulario de error estándar. Si lo hacen solicitar el tratamiento de errores en línea, simplemente tendrán que asegurarse de que sus entradas se ven así:
<input type="text" name="first_name" value="{first_name}" />
{error:first_name}
Nota el campo oculto sometemos junto con el formulario, esto nos permite garantizar que sólo manejamos presentación de este formulario, y no cualquier otro formulario en la página, como un formulario de inicio de sesión o algo así. Si tiene más de una instancia de su formulario en una página (por ejemplo, dentro de un bucle de entradas de canal o algo así), deberá implementar algunos trucos para asegurarse de que solo maneja la instancia de formulario que se envió, por ejemplo, enviando a lo largo de entry_id como un campo oculto también.
Me alegro de tener todo documentado, espero que esto también sea útil para otros desarrolladores de EE.
Muchas gracias, Adrian!Un poco molesto, pero ahora lo sé. Casi parece que pasar a una vista que muestra los errores con un botón de retroceso para corregirlo no sería un gran problema si tuviera también alguna validación de JavaScript en tiempo real, que la mayoría de los visitantes verían. –
Sí, en realidad esa es una solución bastante inteligente si solo está desarrollando para su propio sitio y sabe que habrá una validación de JS en el front-end. Mi solución probablemente sea más útil si está desarrollando un módulo comercial y desea que el diseñador tenga la mayor flexibilidad. –
¡Gracias! Descubrí cómo procesar el formulario con una acción, pero la validación me echó. – juddlyon