ENGLISH'S TRADUCTION
Introduction:
Designing the structure of an Intranet with multiple modules, i came across the
"Dynamic Grid's Problem". I really needed a customizable Grid , easy to apply
and to use, and the most important thing, with AJAX's technology .
Looking for one in the Web, codeproject, and so many other pages, i didn't find one that satisfied my expectations.
The only thing I found
were tiny things which, properly combined, conform what it is today the "LeleGrid"
Links:
http://www.prototypejs.org
Requirements:
1) Have installed SQL Server Express 2005.
2) As usual, nowadays we need the Prototype
JS Framework, because I use it as much for AJAX, as for the DOM handling.
In addition, it has one new method and a modified one. Both here describe :
Added method:
I create this new method so as avoid the "up and down" effect when using the functions (toogle, show or hide).
It is
used by:
Element.invisible('nombrecontrol','visible') o Element.invisible('nombrecontrol','hidden')
invisible: function(type) {
$(arguments[0]).style.visibility = arguments[1];<br />},
Modified method:
I modified it because if when using the Grid with MasterPages, the
ID's control will be rendered by the form: ctl00_contentPagina + ControlName
function $() {<br /> var results = [], element;<br /> for (var i = 0; i < arguments.length; i++) {<br /> element = arguments[i];<br /> if (typeof element == 'string'){<br /> if (document.getElementById(element) != null)<br /> element = document.getElementById(element);<br /> else<br /> element = document.getElementById("ctl00_contentPagina_"+element);<br /> }<br /> results.push(Element.extend(element));<br /> }<br /> return results.length < 2 ? results[0] : results;<br /> }
Operation:
The Grid uses HttpHandler to obtain XML (by using its information) or to
eliminate some element of the grid.
These are two archives: DatosGrilla.ashx and
EliminarFilaGrilla.ashx.
The XML's format of the DatosGrilla.ashx file is the
following:
<Contenido><br /> <Cantidad></Cantidad> Cantidad de Filas devueltas.<br /> <Filas><br /> <Fila> Fila 1<br /> <Celda></Celda> campo 1..<br /> <Celda></Celda> campo 2..<br /> ...<br /> <Celda></Celda> campo N..<br /> </Fila><br /> <Fila> Fila 2<br /> <Celda></Celda><br /> <Celda></Celda><br /> <Celda></Celda><br /> </Fila><br /> ...<br /> <Fila> Fila N<br /> <Celda></Celda><br /> <Celda></Celda><br /> <Celda></Celda><br /> </Fila><br /> <Filas><br /> </Contenido>
In the different examples you will found it interacts against a data base SQL Express,
but it can also interact against other data bases.
The Code:
You will found a great variety of examples
with differents configurations.
In the web.config:
<add
name="ConnectionString" connectionString="Data
Source=.\SQLEXPRESS;AttachDbFilename=C:\Desarrollo\NET\LeleGrid\App_Data\Database.mdf;Integrated
Security=True;User Instance=True"
providerName="System.Data.SqlClient"/>
You must modify the path of "AttachDbFilename" according to where you
have downloaded the ZIP
In the file .aspx we must have this:
In the head section:
<script type="text/javascript" src="../JavaScripts/protoype.js"></script><br /> <script type="text/javascript" src="../JavaScripts/grillaV2.js"></script>
In the body section or content:
<CNC:Grilla runat="server" ID="grillaCategorias" NombreSector="COT"
NombreGrilla="Categorias" NombreTabla="tblCategorias" />
This control shows the searching fields through which the data will be filtered. It is formed by several "Fields", through which the value will be searched, and another field, that is the value itself.
The mandatory parameters are:
NombreSector: As said in the Introduction of the articule I
needed a grid for an Intranet with multiple modules . The, This field is for it.
NombreGrilla: The Grid's name
NombreTabla: The Table's name.
Important:
None of these 3 parameters should be the same.
They ID must
be by the form "grilla" + NombreGrilla.
The optional parameters are:
OpcionesAvanzadas: Whether
it has advanced options or not. TRUE/FALSE.
By default TRUE
OpcionesBasicas: Whether
it has basic options or not. TRUE/FALSE. By
default TRUE
CantRegistros: Amount of registries shown
per page. By
default 10
Oculto: Whether
to show the search fields or not. TRUE/FALSE. By default
FALSE
Paginacion: Whether
it has pagination or not. TRUE/FALSE. By default
TRUE
In thead of the table which becomes it is to put the head of the
Grid. The Width assigned to each column it's your own choice.
In
addition, if one would like to sort the table by that particular column the event
onclick should be added to every td.
The parameters received
by the
OrdenarTabla's function receives are: Index of the Column, Name of the Table,
and Type of Ordering (0=Numbers, 1=String and 2=$) respectively.
<table id="tblCategorias" class="grilla" cellspacing="0"><br /> <thead><br /> <tr><br /> <td style="width: 90px; display: block;">Opciones</td><br />
<td style="cursor: pointer; width: 50%;" title="Ordenar por Nombre"
onclick="OrdenarTabla(1,'tblCategorias', 1);">Nombre</td><br />
<td style="cursor: pointer; width: 50%;" title="Ordenar por
Traducción" onclick="OrdenarTabla(2,'tblCategorias',
1);">Traducción</td><br /> <td style="width: 10px;">Activo</td><br /> </tr><br /> </thead><br /> <tbody id="trFilasCategorias"><br /> <tr><br /> <td colspan="4">No se han encontrado resultados.</td><br /> </tr><br /> </tbody><br /> <tfoot id="trCargandoCategorias" style="display:none;"><br /> <tr><br /> <td colspan="4" style="background-color:#fff;"><br /> <CNC:Cargando ID="CargandoCategorias" runat="server" /><br /> </td><br /> </tr><br /> </tfoot><br /> </table>
Important:
Id of the TBody must be:
"trFilas" + NombreGrilla.
Id of the TFoot must be: "trCargando" + NombreGrilla
Id of the control loading must be: "Cargando" +
NombreGrilla.
In the
foot a row using the "Loading" control is usually added. This is just a
graphical detail but it looks really pretty! You will realize this once the
Grid is working. JA!
<asp:HiddenField runat="server" ID="hidVuelveDeEdicion" /><br /> <asp:HiddenField runat="server" ID="hidValorPagina" />
These two hidden fields
are used when redirected by the Grid to another page and from this one back to
the Grid. Theese fields will assure you the Grid will be loaded with it previous information.
In the file .aspx.cs or similar:
protected void Page_Load(object sender, EventArgs e) {<br /><br /> if(!IsPostBack) {<br /><br /> CargarBusqueda();<br />
Page.ClientScript.RegisterStartupScript(this.GetType(), "Load",
"RecuperarBusqueda('COT','Categorias','tblCategorias', 10 ,true, true,
true);",true);<br /> grillaCategorias.ValoresBusqueda.Items.Add(new ListItem("Nombre", "Nombre"));<br /> grillaCategorias.ValoresBusqueda.Items.Add(new ListItem("Traducción", "Traduccion"));<br /> }<br /><br /> grillaCategorias.ValorBusqueda.Focus();<br /> }<br /><br /> private void CargarBusqueda() {<br /><br /> string valorPagina = Request.QueryString["valorPagina"];<br /> string valorCampo = Request.QueryString["valorCampo"];<br /> string valorBusqueda = Request.QueryString["valorBusqueda"];<br /><br /> if(string.IsNullOrEmpty(valorPagina) || string.IsNullOrEmpty(valorCampo) || string.IsNullOrEmpty(valorBusqueda)) {<br /> hidVuelveDeEdicion.Value = "FALSE";<br /> }<br /> else {<br /> hidVuelveDeEdicion.Value = "TRUE";<br /> hidValorPagina.Value = valorPagina;<br /> grillaCategorias.ValorBusqueda.Text = valorBusqueda;<br /> grillaCategorias.ValoresBusqueda.SelectedValue = valorCampo;<br /> }<br /> }
In the file grillaV2.js :
It is the Grid's main file. It may have global variables:
var indiceColAnt = 0;<br /> var classAnt;<br /><br />
var _imgPath = "../Imagenes/Grilla/"; This is the only variable that you can modifiy.<br /><br /> var _tipoGrilla = null;<br /> var _sector = null;<br /> var _table = null;<br /> var _opcionesBasicas = null;<br /> var _opcionesAvanzadas = null;<br /> var _paginaActual = null;<br /> var _valorCantReg = null;<br /> var _valorCampo = null;<br /> var _valorBusqueda = null;<br /> var _realizaPaginacion = null;
Apart from containing all the pertinent functions, it contains a EjecutarAccion
function.
This function is used for the advanced options of grid.
Styles:
We can have these CSS in the Themes or just in a .css file.
Remind yourself to change the
references of the images !
.grilla {<br /> background:Window;<br /> border:Solid 1px #c4bdb0;<br /> color:WindowText;<br /> font:Icon;<br /> width:100%;<br /> }<br /> .grilla thead{<br /> BACKGROUND: url(../../Imagenes/menuBg.gif) repeat-x;<br /> color:black;<br /> }<br /> .grilla td {<br /> padding:2px 5px;<br /> }<br /> .grilla thead td {<br /> border:1px solid; <br /> border-color:ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;<br /> }<br /> .grilla select {<br /> font-family:Verdana;<br /> font-size:7pt;<br /> }<br /> .descendente {/* columna de ordenamiento descendente */<br /> font-weight:bold;<br /> height:11px;<br /> width:11px;<br /> }<br /> .ascendente{ /* columna de ordenamiento ascendente */<br /> font-weight:bold; <br /> height:11px;<br /> width:11px;<br /> }<br /> .AlternatingItemTemplate {/* filas pares */<br /> background-color:#fff;<br /> background-position:center center;<br /> }<br /> .ItemTemplate{/* filas impares */<br /> background-color:#fff;<br /> background-position:center center;<br /> }<br /> #cmbCantFilas{<br /> font-family:Verdana;<br /> font-size:8pt;<br /> }
Testing
The correct operation oF the LeleGrid was proved in
IE 6+ and Mozilla 1.5+
TRADUCCION AL ESPAÑOL
Introduccion:
Diseñando la estructura de una Intranet con multiples modulos, se me presento el problema de las Grillas Dinamicas.
Necesitaba una Grilla altamente customizable, facil de aplicar y de usar, y lo mas importante, con tecnologia AJAX.
Buscando por la web, por codeproject, y por tantas otras paginas, no encontre ninguna que satisfaciera mis espectativas.
Lo unico que encontraba eran pequeñas cosas, que todas juntas, conforman lo que hoy es la "LeleGrid".
Links Utiles:
http://www.prototypejs.org
Requisitos:
1) Tener instalado SQL Server Express 2005.
2) Como es usual en estos tiempos la Grilla necesita de la Libreria Prototype, ya que la uso tanto para AJAX, como para el manejo de DOM
Ademas, tiene 1 metodo nuevo y otro modificado que describo a continuacion:
Metodo agregado:
Lo cree para que no se produzca el efecto de subir y bajar al usar las funciones (toogle, show o hide).
Se usa de la forma:
Element.invisible('nombrecontrol','visible') o Element.invisible('nombrecontrol','hidden')
invisible: function(type) {<br /> $(arguments[0]).style.visibility = arguments[1];<br /> },
Metodo Modificado:
Lo modifique ya que si usamos la Grilla con MasterPages, los ID de los controles se renderean de la forma: ctl00_contentPagina + NombreDelControl
function $() {<br /> var results = [], element;<br /> for (var i = 0; i < arguments.length; i++) {<br /> element = arguments[i];<br /> if (typeof element == 'string'){<br /> if (document.getElementById(element) != null)<br /> element = document.getElementById(element);<br /> else<br /> element = document.getElementById("ctl00_contentPagina_"+element);<br /> }<br /> results.push(Element.extend(element));<br /> }<br /> return results.length < 2 ? results[0] : results;<br /> }
Funcionamiento:
La Grilla usa HttpHandler para obtener el XML con los datos de la misma o para Eliminar algun elemento de la misma.
Estos archivos son 2: DatosGrilla.ashx y EliminarFilaGrilla.ashx.
El formato del XML del archivo DatosGrilla.ashx es de la siguiente forma:
<Contenido><br /> <Cantidad></Cantidad> Cantidad de Filas devueltas.<br /> <Filas><br /> <Fila> Fila 1<br /> <Celda></Celda> campo 1..<br /> <Celda></Celda> campo 2..<br /> ...<br /> <Celda></Celda> campo N..<br /> </Fila><br /> <Fila> Fila 2<br /> <Celda></Celda><br /> <Celda></Celda><br /> <Celda></Celda><br /> </Fila><br /> ...<br /> <Fila> Fila N<br /> <Celda></Celda><br /> <Celda></Celda><br /> <Celda></Celda><br /> </Fila><br /> <Filas><br /> </Contenido>
En los ejemplos encontraran que interactua contra una base de datos SQL Express, pero puede interactuar tmb contra otras bases de datos.
El Codigo:
Encontraran una gran variedad de ejemplos con distintos tipos de configuraciones.
En el web.config:
<add name="ConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Desarrollo\NET\LeleGrid\App_Data\Database.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient"/>
Modifiiquen el path de "AttachDbFilename" de acuerdo a donde hayan bajado el ZIP.
En el archivo .aspx deberemos tener esto:
En el head:
<script type="text/javascript" src="../JavaScripts/protoype.js"></script><br /> <script type="text/javascript" src="../JavaScripts/grillaV2.js"></script>
En el body o el content:
<CNC:Grilla runat="server" ID="grillaCategorias" NombreSector="COT" NombreGrilla="Categorias" NombreTabla="tblCategorias" />
Este control lo que hace es Mostrar los Campos de Busqueda por los cuales se van a filtrar los datos en la grilla.
Consta de un combo de "Campos" , que es el campo por el que se va a buscar el valor.
Y Otro de "Valor", que es el valor propiamente dicho.
Los parametros obligatorios que necesita son:
NombreSector: Como dije en la Introduccion del articulo, necesitaba una grilla para una intranet con multiples modulos/sectores. Este campo es para ello.
NombreGrilla: El nombre de la Grilla
NombreTabla: El nombre de la tabla.
Importante: No deben ser iguales ninguno de estos 3 parametros. El ID debe ser de la forma "grilla" + NombreGrilla.
Los parametros opcionales son:
OpcionesAvanzadas: Si tiene opciones avanzadas o no. TRUE/FALSE. Por default TRUE
OpcionesBasicas: Si tiene opciones basicas o no. TRUE/FALSE. Por default TRUE
CantRegistros: Cantidad de registros que se muestran por pagina. Por default 10
Oculto: Si se muestran los campos de busqueda o no. TRUE/FALSE. Por default FALSE
Paginacion: Si tiene paginacion o no. TRUE/FALSE. Por default TRUE
En el thead de la tabla lo que se hace es poner la cabecera de la Grilla. El width que se le asigna a cada columna es a su eleccion.
Si ademas se quiere que se puedan ordenar la tabla por esa columna, se le debe agregar el evento onclick a cada td.
Los parametros que recibe la funcion OrdenarTabla son: Indice de la Columna, Nombre de la Tabla, y Tipo de Ordenamiento (0=Numeros, 1=String y 2=Monedas) respectivamente.
<table id="tblCategorias" class="grilla" cellspacing="0"><br /> <thead><br /> <tr><br /> <td style="width: 90px; display: block;">Opciones</td><br /> <td style="cursor: pointer; width: 50%;" title="Ordenar por Nombre" onclick="OrdenarTabla(1,'tblCategorias', 1);">Nombre</td><br /> <td style="cursor: pointer; width: 50%;" title="Ordenar por Traducción" onclick="OrdenarTabla(2,'tblCategorias', 1);">Traducción</td><br /> <td style="width: 10px;">Activo</td><br /> </tr><br /> </thead><br /> <tbody id="trFilasCategorias"><br /> <tr><br /> <td colspan="4">No se han encontrado resultados.</td><br /> </tr><br /> </tbody><br /> <tfoot id="trCargandoCategorias" style="display:none;"><br /> <tr><br /> <td colspan="4" style="background-color:#fff;"><br /> <CNC:Cargando ID="CargandoCategorias" runat="server" /><br /> </td><br /> </tr><br /> </tfoot><br /> </table>
Importante: El Id del TBody debe ser de la forma "trFilas" + NombreGrilla.
El Id del TFoot debe ser de la forma "trCargando" + NombreGrilla
El Id del control cargando debe ser de la forma "Cargando" + NombreGrilla.
En el foot lo que se hace es poner una fila con el control de Cargando, es un detalle grafico nomas pero que queda muy Lindo !
Cuando vean la Grilla en funcionamiento entenderan mejor..JA !
<asp:HiddenField runat="server" ID="hidVuelveDeEdicion" /><br /> <asp:HiddenField runat="server" ID="hidValorPagina" />
Estos 2 campos ocultos sirven para que cuando la Grilla te redirecciona a otra pagina, y desde esa pagina se vuelva a la Grilla,
la Grilla se cargue devuelta con los valores con los que estaba
En el .aspx.cs o similar:
protected void Page_Load(object sender, EventArgs e) {<br /><br /> if(!IsPostBack) {<br /><br /> CargarBusqueda();<br /> Page.ClientScript.RegisterStartupScript(this.GetType(), "Load", "RecuperarBusqueda('COT','Categorias','tblCategorias', 10 ,true, true, true);",true);<br /> grillaCategorias.ValoresBusqueda.Items.Add(new ListItem("Nombre", "Nombre"));<br /> grillaCategorias.ValoresBusqueda.Items.Add(new ListItem("Traducción", "Traduccion"));<br /> }<br /><br /> grillaCategorias.ValorBusqueda.Focus();<br /> }<br /><br /> private void CargarBusqueda() {<br /><br /> string valorPagina = Request.QueryString["valorPagina"];<br /> string valorCampo = Request.QueryString["valorCampo"];<br /> string valorBusqueda = Request.QueryString["valorBusqueda"];<br /><br /> if(string.IsNullOrEmpty(valorPagina) || string.IsNullOrEmpty(valorCampo) || string.IsNullOrEmpty(valorBusqueda)) {<br /> hidVuelveDeEdicion.Value = "FALSE";<br /> }<br /> else {<br /> hidVuelveDeEdicion.Value = "TRUE";<br /> hidValorPagina.Value = valorPagina;<br /> grillaCategorias.ValorBusqueda.Text = valorBusqueda;<br /> grillaCategorias.ValoresBusqueda.SelectedValue = valorCampo;<br /> }<br /> }
En grillaV2.js :
Es el archivo principal de la Grilla.
Las variables globales que contiene son las siguientes:
var indiceColAnt = 0;<br /> var classAnt;<br /><br /> var _imgPath = "../Imagenes/Grilla/"; Esta es la unica que se debe modificar. Es el path de la carpeta donde se encuentran las imagenes<br /><br /> var _tipoGrilla = null;<br /> var _sector = null;<br /> var _table = null;<br /> var _opcionesBasicas = null;<br /> var _opcionesAvanzadas = null;<br /> var _paginaActual = null;<br /> var _valorCantReg = null;<br /> var _valorCampo = null;<br /> var _valorBusqueda = null;<br /> var _realizaPaginacion = null;
Ademas de contener todas las funciones pertinentes, contiene una llamada EjecutarAccion .
Esta funcion se usa para las opciones avanzadas de la grilla.
Estilos:
Podemos tener estos CSS en los Themes o simplemente en un .css
Acordarse de cambiar las referencias a las imagenes.
.grilla {<br /> background:Window;<br /> border:Solid 1px #c4bdb0;<br /> color:WindowText;<br /> font:Icon;<br /> width:100%;<br /> }<br /> .grilla thead{<br /> BACKGROUND: url(../../Imagenes/menuBg.gif) repeat-x;<br /> color:black;<br /> }<br /> .grilla td {<br /> padding:2px 5px;<br /> }<br /> .grilla thead td {<br /> border:1px solid; <br /> border-color:ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;<br /> }<br /> .grilla select {<br /> font-family:Verdana;<br /> font-size:7pt;<br /> }<br /> .descendente {/* columna de ordenamiento descendente */<br /> font-weight:bold;<br /> height:11px;<br /> width:11px;<br /> }<br /> .ascendente{ /* columna de ordenamiento ascendente */<br /> font-weight:bold; <br /> height:11px;<br /> width:11px;<br /> }<br /> .AlternatingItemTemplate {/* filas pares */<br /> background-color:#fff;<br /> background-position:center center;<br /> }<br /> .ItemTemplate{/* filas impares */<br /> background-color:#fff;<br /> background-position:center center;<br /> }<br /> #cmbCantFilas{<br /> font-family:Verdana;<br /> font-size:8pt;<br /> }
Testing
Se comprobo su correcto funcionamiento es IE 6+ y Mozilla 1.5+