miércoles, 7 de marzo de 2012

Componente Tabla, primera parte mostrando los datos

El objetivo principal es crear un componente que me permita mostrar, actualizar y borrar  el contenido de una tabla de la base de datos en forma tabular con solo cargar sus librerías y la del componente a desarrollar y que se detecte automáticamente dentro del código html, para esto consideré 2 alternativas, crear mi propio componente desde cero :( , o usar alguno de los plugins prediseñados que muestran datos en forma tabular. Entre ellos analicé a Jqgrid, y Jtable, el primero porque ya había diseñado un componente similar para un proyecto, pero me pareció mejor experimentar con Jtable ya que lo vi muy completo por las siguientes características que voy a traducir del inglés.

JTable es un plugin de jquery que es usado para crear tablas CRUD  basadas en AJAX


- Automáticamente crea una tabla HTML y carga los registros del server usando AJAX
- Crea los dialogos automáticamente de: Crear Nuevo registro, Editar Registro, Borrar Registro. (esta es la característica que más me atrajo ya que me ahorra hacer los formularios y dialogos:) )
- No es dependiente de ninguna tecnología del servidor lo que me permite usarlo con php (codeigniter)
- etc etc el resto se puede leer aqui en inglés.




Empecemos con la intalación del plugin, el primer paso sería descargarlo de la página http://www.jtable.org/downloads/jtable.zip  y dentro /htdocs/blog creo una carpeta llamado jtable ahí extraigo todo el contenido del zip listo:), hay que tomar en cuenta los primero artículos de la estructura de mi servidor.



Siguiendo los métodos que usé en los ejemplos anteriores voy a crear una nueva etiqueta html que tendrá básicamente el siguiente formato donde los atributos serán la configuración de mi tabla, con el propósito que se cree nuestra jtable y lo reconozca tutomáticamente


<jtabla id="mi id" tabla="mi tabla"  permiso="CRUD" titulo ="mi titulo"></jtabla>

Donde:
id= id de mi jtabla
tabla= es la tabla de la bd que quiero mostrar en el componente
permiso= C por crear, R por mostrar , U por actualizar, D por borrar ... vienen de las siglas CRUD (create,read,update,delete)

A la vista la llamaremos tablademo_view.php ubicada en /views, "instalamos" el plugin (lineas 10 y 12) incluyendo la ruta de los css y javascripts,cargamos nuestro componente en la linea 13 (jtabla.js que explicaré más adelante) y creamos nuestra etiqueta linea 16 <jtabla></jtabla>

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <link type="text/css" href="../js/css/smoothness/jquery-ui-1.8.17.custom.css" rel="stylesheet" />
        <script type="text/javascript" src="../js/jquery-1.7.1.min.js"></script>
        <script type="text/javascript" src="../js/jquery-ui-1.8.17.custom.min.js"></script>
        <script language="JavaScript" type="text/javascript" src="../js/jquery.json-2.3.min.js"></script>
        <!-- Include one of jTable styles. -->
        <link href="../jtable/themes/standard/blue/jtable_blue.css" rel="stylesheet" type="text/css" />
        <!-- Include jTable script file. -->
        <script src="../jtable/jquery.jtable.min.js" type="text/javascript"></script>
        <script src="../js/jtabla.js" type="text/javascript"></script>
        <title></title>
    </head>
    <body>
    <jtabla id="tabla1" tabla="historial"  permisos="R" titulo ="Historial de visitas">
    </jtabla>

</body>
</html>


Con el tiempo se va ampliando y el código va creciendo dentro de mi controller componentes.php pondré la mayoría de funciones para mis componentes en el cual hasta ahora está el componente dataquery y jtable, así que separaré la carga de la vista en otro controller que en este caso se llama tabla.php y se muestra a continuación:
/controllers/tabla.php
1
2
3
4
5
6
7
8
<?php
class Tabla extends CI_Controller {

    public function index() {
        // cargamos nuestra vista
        $this->load->view('tablademo_view');
    }
}

Como dije solo carga la vista en codeigniter, el resto de funciones se encuentran en componntes.php, he incluido un gráfico con la parte en verde representando la estructura del componente Jtabla

La implementación de esta parte del componente fue sencilla mientras se entienda de manera clara como funciona la librería jtable, el primer paso es crear un contenedor por ejemplo:

1
<div id="PersonTableContainer"></div>


Después se llama a la función jtable  linea 3 pasándole los parámetros necesarios, en formato json, y consta de 3 partes, title : que es el titulo de la tabla, actions: son las llamadas ajax a las funciones de mostrar, crear, actualizar y borrar respectivamente, fields: es el mapeo que se le hace los campos  y deben coincidir con los de la tabla de la base de datos, por último en la línea 36 el método load carga los datos cargados.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<script type="text/javascript">
    $(document).ready(function () {
        $('#PersonTableContainer').jtable({
            title: 'Table of people',
            actions: {
                listAction: '/GettingStarted/PersonList',
                createAction: '/GettingStarted/CreatePerson',
                updateAction: '/GettingStarted/UpdatePerson',
                deleteAction: '/GettingStarted/DeletePerson'
            },
            fields: {
                PersonId: {
                    key: true,
                    create: false,
                    edit: false,
                    list: false
                },
                Name: {
                    title: 'Author Name',
                    width: '40%'
                },
                Age: {
                    title: 'Age',
                    width: '20%'
                },
                RecordDate: {
                    title: 'Record date',
                    width: '30%',
                    type: 'date',
                    create: false,
                    edit: false
                }
            }
        });
 
        $('#PersonTableContainer').jtable('load');
    });
</script>

Y por último hay que definir un action en el caso de mostrar los datos, se llama listaction que lllama  al código del servidor que trae los datos (ajax) en formato json aqui el código en php:


//Get records from database
$result = mysql_query("SELECT * FROM people;");
//Add all records to an array
$rows = array();
while($row = mysql_fetch_array($result))
{
    $rows[] = $row;
}
//Return result to jTable
$jTableResult = array();
$jTableResult['Result'] = "OK";
$jTableResult['Records'] = $rows;
print json_encode($jTableResult);



Lo primero que hice fue crear 2 funciones en jtabla.js, la primera html_jtabla() detecta las etiquetas jtabla y los atributos del mismo (lineas 9 a 14) y los convierte en un contenedor div (linea 16) , luego envía un objeto jsón (linea 17 a 22) con los atributos de la etiqueta a la función jtable(config_jtable) (linea 23) que es la que realmente se encarga de crear el jtable.
La función jtable(config_jtable), se encarga de armar los atributos en formato json que se le envía al método jtable del plugín, las lineas 32 a 53 obtiene los actions del atributo config_jtable.permisos, y en la linea 36 se asigna la url del controller(componentes) y función (listar) que obtiene los datos de la tabla de la base de datos, las lineas 54 a 67 obtienen los nombres de los campos de la tabla por medio de ajax y llena la variable campos que sería el mapeo de los campos de la tabla osea fields, por ultimo linea 69 creamos nuestro jtable con los parámetros necesarios y en la 75 cargamos los datos.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/* 
 * La lógica por parte del cliente usando jquery
 */

jQuery(document).ready(function(){
    // datepicker("#datepicker");
    html_jtabla();
    function html_jtabla(){
        var arr_jtabla = $("jtabla");
       $.each(arr_jtabla, function(key, value) {
               var id_jtabla = $(this).attr("id");
            var nombre_tabla = $(this).attr("tabla");
            var permisos = $(this).attr("permisos");
            var titulo = $(this).attr("titulo");
            var string_div = '<div id="'+ id_jtabla + '" ></div>';
            $(this).replaceWith(string_div);
         var config_jtable = {
                "id":id_jtabla,
                "tabla":nombre_tabla,
                "permisos":permisos,
                "titulo":titulo
            }
            jtable(config_jtable);
        });
    }

    function jtable(config_jtable){
        // crea las acciones
        var acciones = {};
        var campos ={};
       
        $.each(config_jtable.permisos, function(key, value) {
            if(value=="R"){
                
               
                acciones.listAction = "componentes/listar/"+config_jtable.tabla;
            }
            if(value=="C"){
                console.log("Crear activado")
                acciones.createAction = "componentes/crear";
            }
            if(value=="U"){
                console.log("Actualizar activado")
                acciones.updateAction = "componentes/actualizar";
            }
            if(value=="D"){
                console.log("Borrar activado")
                acciones.deleteAction = "componentes/borrar";
            }
            if(value==null){
                console.log("Defina las acciones");
            }
        });
        $.ajax({
            type: "POST",
            url: "componentes/listar_campos/"+config_jtable.tabla,
            async:false,
            success: function(msg){
                var datos = $.evalJSON(msg);// se convierte de json a un objeto javascript
                $.each(datos, function(key, value) {
                    campos[value] = {
                        title:value
                    };
                });
   
            }
        });
    
        $('#'+config_jtable.id).jtable({
            title: config_jtable.titulo,
            actions: acciones,
            fields:  campos
        });

        $('#'+config_jtable.id).jtable('load');
    }

});// fin de ready function

Las urls creadas en las lineas 36 "componentes/listar/"+config_jtable.tabla; y 56 url: "componentes/listar_campos/"+config_jtable.tabla, son las funciones listar y listar_campos del controller componentes, la función datos_dp pertenece a al componente datepicker de ejemplos anteriores, ya que este es un controller compartido por jtabla y datepicker.
La función listar($tabla) obtiene los datos de la tabla usando de nuevo el modelo generic_model y arma los datos en formato json que son enviados de nuevo a la vista para ser mostrados en la tabla de datos.
La función listar_campos obtiene los nombres de los campos de la tabla en cuestión.



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php

class Componentes extends CI_Controller {

    public function __construct() {
        parent::__construct();
        // cargamos nuestro base de datos ahora lo hacemos por defecto
        $this->load->database();
        // $this->load->library("firephp");
    }

    public function datos_dp() {

//        var $json_conf_dp = [{
//        tabla:'historial',
//        campo:'fecha'
//        }];
        $tabla = $this->input->post('tabla');
        $campo = $this->input->post('campo');
        $this->load->model("Generic_model");
        $datos['query'] = $this->Generic_model->get_datos($tabla, $campo);
        // codificamos el array a json usando json_encode mirar manual de php
        $data_json = json_encode($datos);
        // enviamos el json a la vista
        echo $data_json;
    }

    public function listar($tabla) {
        $this->load->model("Generic_model");
        $datos = array();
        $datos['Result'] = "OK";
        $datos['Records'] = $this->Generic_model->listar_jtable($tabla);
        // codificamos el array a json usando json_encode mirar manual de php
        $data_json = json_encode($datos);
        // enviamos el json a la vista
        echo $data_json;
    }

    public function listar_campos($tabla) {
        $this->load->model("Generic_model");
        $datos = $this->Generic_model->listar_campos($tabla);
        $data_json = json_encode($datos);
        // enviamos el json a la vista
        echo $data_json;
    }

}


Creo que el modelo no requiere mucha explicación ya que es básicamente el mismo anterior con las correspondientes consultas que vienen del controller componentes... asi que solo pondré el código.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php

class Generic_model extends CI_Model {

    function __construct() {
        // Call the Model constructor
        parent::__construct();
    }

    function get_datos($nombre_tabla, $nombre_campo) {
        // SQL equivalente a SELECT $nombrecampo FROM $nombre_tabla;
        $this->db->select($nombre_campo);
        $this->db->from($nombre_tabla);
        $query = $this->db->get();
        return $query->result();
    }

    function listar_jtable($tabla) {

        $query = $this->db->get($tabla);
        return $query->result();
    }
    function listar_campos($tabla){
        $campos = $this->db->list_fields($tabla);
        return $campos;
    }

}

El resultado:

En este primer intento por mostrar los datos, se tomaron los títulos de los campos directamente de la tabla de la base de datos, sería interesante poder definir esos títulos manualmente, he pensado añadir más "atributos" a la etiqueta jtabla para realizarlo.

1
2
3
4
    <jtabla id="tabla1" tabla="historial"  permisos="R" titulo ="Historial de visitas">
        <campo nombre="id" titulo="El id"></campo>
        <campo nombre="fecha" titulo="La fecha"></campo>
    </jtabla>

Donde la etiquetas campo representan la información del campo donde nombre sería igual al nombre del campo de la tabla y un título personalizado. También se podría definir el tipo de datos que contiene cada campo, ya sea numerico, fecha, texto etc pero eso quedará para el próximo artículo en el cual terminaré la parte de crear, borrar y actualizar.


3 comentarios:

  1. Deberías pasar el archivo completo del proyecto y el archivo sql. Si lo tienes por favor pasamé la botella.

    ResponderEliminar