En este punto vamos a hablar de dos componentes que se salen de los básicos para diseñar una pantalla genérica y que nos ayudarán a la hora de trabajar con grupos de datos, tanto para seleccionar como para agrupar.
Las ventanas de selección es una particularización de las listas, siendo las siguientes características las que las diferencian:
Se pueden filtrar los valores posibles mediante unas búsquedas sencillas. Lo que las hace aconsejables cuando el número de elementos posibles es superior a 100 aprox.
Se puede visualizar más información complementaria que nos ayude a la selección de un registro, es decir, en la ventana de selección se mostrarán tantas columnas como se necesiten para la mejor comprensión del registro.
Del registro seleccionado podemos recuperar otra información que nos interese para llevárnosla a otros campos del panel origen. Esta información puede ser visible o no en la ventana de selección.
Nos permite tener diferentes fuentes de datos, los datos pueden venir de un web service, de base de datos, de una clase...
Se puede crear una ventana de selección de imágenes.
Para definir una ventana de selección tenemos que definirla en la clase manejadora. Creamos una instancia de la clase gvHidraSelectionWindow() pasándole el nombre de campo de la tpl, campo del que dependerá la ventana de selección, y como segundo parámetro, un identificador (p.ej. USUARIOS) del origen de los datos, opcionalmente, podemos indicar una conexión alternativa como tercer parámetro, para ello debemos indicar pasar un DSN de conexión. Después tendremos que ir relacionando los campos del panel que van a ser actualizados con el campo correspondiente de la base de datos, con el método addMatching(), como mínimo habrá una relación ya que de lo contrario no actualizaríamos ningún campo de la ventana orígen. Por último añadimos esta definición de la ventana al panel con addSelectionWindow().
$usuarios = new gvHidraSelectionWindow('filUsuario','USUARIOS'); $usuarios->addMatching('filId','id'); $usuarios->addMatching('filUsuario','usuario'); $usuarios->addMatching('filNombre','nombre'); $this->addSelectionWindow($usuarios);
Además de esta definición básica la ventana tiene dos métodos que nos permitirán customizarla:
setSize(): este método permite fijar el tamaño de la ventana emergente.
$usuarios = new gvHidraSelectionWindow('usuario','USUARIOS');
...
$usuarios->setSize(800,600);
...
setLimit(): este método fija el número máximo de elementos que mostrará. Si el resultado de la consulta excede este número, mostrará un mensaje advirtiendo al usuario de que no se mostrarán todos los resultados obtenidos.
$usuarios = new gvHidraSelectionWindow('usuario','USUARIOS');
...
$usuarios->setLimit(10);
...
setRowsNumber(): este método fija el número de filas que se mostrarán por pantalla simultaneamente.
$usuarios = new gvHidraSelectionWindow('usuario','USUARIOS');
...
$usuarios->setRowsNumber(4);
...
setTemplate(): nos permite diseñar nuestra propio contenido de la ventana de selección, es decir, tendrá una tpl particular en la que podremos seleccionar el tipo de componente (CampoTexto, List, Imagen, ), el nombre de la columna, el ancho de las mismas, ...
$usuarios = new gvHidraSelectionWindow('usuario','USUARIOS');
...
$usuarios->setTemplate('ventanaSeleccion/incUsuarios.tpl');
...
Si utilizamos este método significa que tenemos una plantilla (tpl) que dará formato a la ventana de selección. En caso contrario, el framework dibuja una ventana de selección sencilla, en la que su contenido no es configurable.
Siguiendo el caso del ejemplo, debemos tener un directorio dentro del directorio plantillas, llamado "ventanaSeleccion", y dentro tendremos las tpl que correspondan a las ventanas de selección de la aplicación. En esa plantilla se crearán los campos que queremos que nos sean necesarios, tanto visibles como ocultos.
{CWImagen nombre="fichero" rutaAbs="yes" textoAsociado="Fichero" width="40" height="50"} {CWCampoTexto nombre="nombre" size="15" textoAsociado="Nombre"} {CWCampoTexto nombre="descripcion" size="40" textoAsociado="Descripción"} {CWCampoTexto nombre="id" oculto="true"}
Una vez definida la ventana sólo nos queda introducir en la tpl un componente CWBotonTooltip que haga referencia a una ventana de selección. Para ello se parametriza indicando el campo sobre el que actua (en nuestro ejemplo usuario), el form y el panel. Aqui tenemos un ejemplo:
{CWCampoTexto nombre="filUsuarios" size="8" textoAsociado="Usuario"} {CWBotonTooltip imagen="13" titulo="Busqueda de Usuarios" funcion="abrirVS" actuaSobre="filUsuarios" claseManejadora="TpqmVehiculosPorUsuario"}
Al pulsar en el botón tooltip de la ventana nos aparecerá una ventana emergente como la siguiente:
Las definiciones particulares a la aplicación, se realizarán, al igual que en el caso de las listas, se definirán en el arranque de la aplicación. Para ello debemos de añadir su definición en la clase que controle el panel principal de la aplicación, fichero AppMainWindow.php. Ya que el origen de los datos puede ser diferente, tenemos dos formas de indicarlo:
setSelectionWindow_DBSource($key, $query, $fields=null):
Método para introducir fuente de datos con consulta SQL.
El primer parámetro será el identificador que nos es necesario cuando definimos la ventana en la clase manejadora. El segundo parámetro es la propia consulta que nos devolverá los datos a mostrar. El tercer parámetro, opcional, nos permite añadir campos a los que ya aparecen en la consulta, sobre ellos también se aplicará el filtro de búsqueda.
En la consulta también podemos usar subconsultas. En el caso de postgres, estas han de tener siempre alias en el from (aunque no se vaya a usar) por lo que conviene ponerlo siempre (para cualquier tipo de base de datos). Notar también que en la subconsulta sólo pondremos alias para los campos que queramos renombrar, no afectan las mayúsculas / minúsculas.
$conf->setSelectionWindow_DBSource('USUARIOS','select id, usuario, nombre from usuarios');
setSelectionWindow_ClassSource($key, $query):
Método para introducir fuente de datos con una clase. Esta clase debe implementar la interfaz gvHidraSelectionWindow_Source.php.
$conf->setSelectionWindow_ClassSource('PERSONAS',"PersonasSource");
La búsqueda, por defecto, busca el texto introducido en cualquiera de los campos que se visualizan, y si obtenemos los datos de una consulta a bd también buscará en el array de campos añadidos. Podemos cambiar este comportamiento de forma similar a los filtros en paneles. Veamos un ejemplo:
$usuarios = new gvHidraSelectionWindow('filUsuario','USUARIOS'); $usuarios->addMatching('filId','id'); $usuarios->addMatching('filUsuario','usuario'); $usuarios->addMatching('filNombre','nombre'); $usuarios->setQueryMode(2); // valor por defecto es 1 $this->addSelectionWindow($usuarios);
Por defecto, cuando el usuario introduce un texto para buscar, busca por todos los campos que aparecen en la consulta concatenados y separados por un espacio: concat(concat(col1,' '),col2)... De esta forma el usuario puede hacer una búsqueda que coincida con el final de un campo y el principio del siguiente. Es importante que para las dos fuentes de datos, los parámetros del matching son los que recogerán los valores y los introducirán en la ventana destino.
Al igual que en las listas, tenemos la posibilidad de crear ventanas de selección dependientes de otros controles, aunque, en este caso, podemos definir dos tipos de dependencia (fuerte o débil). La fuerte añade a la WHERE de la consulta que se genere en la ventana una clausula con el valor del campo del que depende sin tener en cuenta si este tiene valor o no. La débil, sólo lo hace si el campo tiene valor. Para indicar la dependencia tenemos que hacer uso del método setDependence indicando los campos de la tpl, su correspondencia en la BD y el tipo de dependencia deseado :0-> fuerte(valor por defecto) o 1-> débil. En nuestro ejemplo, sería:
$usuarios = new gvHidraSelectionWindow('filUsuario','USUARIOS'); $usuarios->addMatching('filId','id'); $usuarios->addMatching('filUsuario','usuario'); $usuarios->addMatching('filNombre','nombre'); $usuarios->setDependence(array('esDePersonal'),array('tper_ocupacion.esPersonal'),0); $this->addSelectionWindow($usuarios);
El selector corresponde con el plugin CWSelector, es un plugin que aún está poco elaborado, se creó para representar relaciones 1:N dentro de un mismo panel. De todos modos, la implementación es manual, es decir. el programador será el que realice las operaciones.
Aquí vemos el aspecto que nos dará el selector en una pantalla.
Vamos a explicar como hacer uso de él:
En la plantilla (tpl):
El plugin CWSelector solamente aparecerá dentro de una ficha (CWFicha). CWSelector es un plugin block, dentro del cual podremos definir otros componentes, como CWCampoTexto y CWLista.
{CWSelector titulo="TituloDelGrupo" botones=$smty_botones nombre="listaBienes" editable="true" separador="."} {CWCampoTexto nombre="CampoTexto1" editable="false" size="6" textoAsociado="CampoTexto1"} {CWCampoTexto nombre="CampoTexto2" editable="false" size="6" textoAsociado="CampoTexto1"} {CWCampoTexto nombre="CampoTexto3" editable="false" size="6" textoAsociado="CampoTexto1"} {/CWSelector}
Los valores introducidos en estos campos serán copiados,
cuando pulsamos el botón , a la lista múltiple que tenemos en la parte
izquierda, separando los valores por el caracter introducido en el
parámetro separador, en nuestro ejemplo el
punto.
Con el botón , copiaremos los valores que estén
seleccionados en la lista múltiple a los campos que hayamos definido
dentro del selector.
Finalmente, el botón nos servirá para eliminar el registro que
tengamos seleccionado en la lista múltiple.
En el views:
En el views tenemos que indicar qué botones del selector tendremos activos, para ello asignamos la variable smarty smty_botones.
$botones = array('insertar','modificar','eliminar'); $s->assign("smty_botones",$botones);
En la clase manejadora:
Finalmente, ¿como recuperamos el contenido del Selector en la clase manejadora? Recordemos que el contenido del selector devolverá una lista, ya que podemos tener N items, pero al recibirlo en la clase manejadora, sólo recibimos un string de elementos separados por separador. Por esta razón, para obtener un array podemos utilizar el siguiente código:
public function postInsertar($objDatos) { $m_datos = $objDatos->getAllTuplas(); foreach($m_datos as $tupla) { if($tupla['listaBienes']!='') { echo 'El resultado es: '; print_r($tupla['listaBienes']);die; } ... }
Si hubiéramos introducido los siguientes valores en nuestro ejemplo:
El resultado sería:
Array ( [0] => 1.2.3 [1] => 4.5.6 )