Formulario Simple
Un formulario simple presenta una grilla de campos editables. A cada uno de estos campos se los denomina Elementos de Formulario (efs).
Eventos
El formulario cuenta con dos modelos de eventos predeterminados:
- Modelo Básico: Incluye un solo evento modificacion marcado como implícito, es decir se dispara sin necesidad de que lo haga explícitamente el usuario. Este modelo se utiliza por ejemplo en una operación con solapas en donde el formulario edita una única entidad (ej. datos básicos de una persona), cuando se cambia de solapa se quiere guardar la información cargada por el usuario sin necesidad de incluír un botón Modificar, sino que el sólo hecho de cambiar de solapa dispare la modificación en el server.
- Modelo ABM: Incluye los eventos clásicos de un formulario tipo ABM (alta, baja, modificacion y cancelar) todos explícitos e incluidos en la botonera. Este modelo se utiliza cuando se quiere que el usuario seleccione en forma explícita sobre el futuro del registro editado, generalmente se está editando un conjunto de registros, graficado por ejemplo en un Cuadro.
El formulario presenta dos grupos de eventos: cargado y no_cargado. En el modelo ABM la baja y la modificación pertenecen al grupo cargado mientras que en el grupo no_cargado se encuentra el alta.
Configuración
Para establecer los datos a mostrar en el formulario, es necesario
configurarlo, desde un CI se debería
escuchar la callback conf__formulario
. En este método es posible
cambiar la configuraciones específicas del formulario (campos
solo-lectura, etiquetas, etc.) y además brindarle los datos necesarios
para graticarse. Estos datos se esperan tengan el formato de un arreglo
asociativo del tipo 'id_ef' => valor
.
<?php
function conf__formulario(toba_ei_formulario $form)
{
$datos = array(
'id' => 1,
'importe' => 100,
'descripcion' => 'Esta descripción se especifica en la carga',
'tipo' => null
);
$form->set_datos($datos);
$form->set_solo_lectura(array('id', 'importe');
}
?>
Cascadas
Ver Cascadas de efs
Validaciones en PHP
El formulario posee una validación propia que itera validando cada ef. Esta validación garantiza que los datos ingresados por el usuario corresponden al tipo de campo con el que se definió (por ej. si es una fecha, que esta sea válida). Para hacer validaciones particulares relacionadas a la lógica de la operación se utilizan los eventos como punto de entrada. Así por ejemplo para validar la modificación en un formulario se escucharía el evento en el CI contenedor:
<?php
/**
* Valida que un campo 'importe' del formulario sea menor o igual que un tope fijo
*/
function evt__formulario__modificacion($datos)
{
if ($datos['importe'] > $this->tope ) {
throw new toba_error('El importe no puede se mayor que '.$this->tope);
}
//--- Procesar los datos
}
?>
En este evento, el parámetro (en este caso $datos) contiene un arreglo asociativo similar al que se necesita en la carga. La excepción hace abortar la operación que dio lugar al evento, informándole al usuario el mensaje.
Extensión Javascript
Se puede usar el mecanismo de referencia-ExtensionesJavascript extensión javascript para agregar comportamientos en el cliente. Estas extensiones necesitan ser definidas en una subclase del formulario, dentro del método toba_ei::extender_objeto_js. De todas las extensiones posibles, las siguientes se identificaron como las más comunes:
Validación general
Es posible agregar una validación general a todo el formulario, escuchando el evento validar_datos
<?php
//Valida que dos campos no tengan valor simultáneamente
echo "
{$this->objeto_js}.evt__validar_datos = function() {
if (this.ef('descripcion').get_estado() != _ && this.ef('otra_descripcion').get_estado() != _ ) {
notificacion.agregar('Sólo puede ingresar una descripción.');
return false;
}
return true;
}
";
?>
En este caso por ejemplo se quiere validar que dos editables no estén
definidos simultáneamente. Una buena medida para decidir extender este
método es preguntarse ¿Estoy detectando un error en un ef particular?
Si es así, no es el método adecuado, en cambio si son más de uno los efs
que participan de la validación, validar_datos
es el lugar correcto.
Validación de efs
Cuando se quiere restringir los valores posibles de un ef, se define el
método evt__id_ef__validar
. Por ejemplo si queremos asegurar que
el importe sea menor que un tope definido en otro ef:
<?php
echo "
{$this->objeto_js}.evt__importe__validar = function() {
if (this.ef('importe').get_estado() < 100) {
this.ef('importe').set_error('El importe debe ser mayor que 100');
return false;
}
return true;
}
";
?>
Hay una razón por la que se prefiere la validación de efs por sobre la validación general del formulario (cuando es posible) y es que este tipo de extensiones automáticamente forman parte de la validación en línea del componente, notificando al usuario inmediatamente del error sin esperar a que quiera terminar la operación.
Eventos
Hay una tercera forma de influir en el proceso de submit de un formulario, y es escuchar un evento específico. Retornando falso en el listener de este evento se aborta el mismo. Por ejemplo el evento cancelar se puede escuchar así:
<?php
//Agrega una confirmación al cancelar
echo "
{$this->objeto_js}.evt__cancelar = function() {
return confirm('¿Esta seguro?');
}
";
?>
Procesamiento de efs
Los procesamientos se lanzan cuando un ef cambia su valor en el cliente.
El procesamiento se escucha como un evento más y recibe un parámetro que
indica si el disparo es_inicial
o no. El procesamiento inicial es aquel
que se da en la carga de la pantalla, sin intervención explícita del
usuario, a partir de allí los procesamientos dependen exclusivamente de
los cambios introducidos por el usuario. Por ejemplo teniendo un
ef_checkbox
con id elige_tipo
se puede
habilitar/deshabilitar otro ef con id tipo
:
<?php
//Activa un campo en base a un checkbox
echo "
{$this->objeto_js}.evt__elige_tipo__procesar = function(es_inicial) {
if (this.ef('elige_tipo').chequeado())
this.ef('tipo').activar();
else
this.ef('tipo').desactivar();
}
";
?>
Generación de layouts
Por defecto el layout de un formulario es un ef arriba del otro, esto se
puede cambiar redefiniendo el método generar_layout
incluyendo el html
deseado. El método contiene originalmente este código:
<?php
protected function generar_layout()
{
foreach ($this->get_nombres_ef() as $ef) {
$this->generar_html_ef($ef);
}
}
?>
<div style='clear:both'> </div>
Por ejemplo si se quiere lograr un layout de dos columnas se puede redefinir el método de la siguiente manera:
<?php
protected function generar_layout()
{
echo "<table>";
$i = 0;
foreach ($this->get_nombres_ef() as $ef) {
$ultimo = ($i == count($this->get_nombres_ef()));
if ($i % 2 == 0) {
echo "<tr>";
}
echo "<td>";
$this->generar_html_ef($ef);
echo "</td>";
$i++;
if ($i % 2 == 0 || $ultimo) {
echo "</tr>";
}
}
echo "</table>";
}
?>
Ejemplos
Existe ejemplos con estas y más situaciones en el proyecto de Referencia, Carpeta Referencia/Componentes/Formularios/.