CGridView, uno de los widgets más usados del framework Yii

Hace tiempo hicimos una introducción sobre Yii Framework. Comentamos que una de sus características es que viene integrado con jQuery y con una serie de widgets Ajax que el desarrollador puede ampliar a su gusto para mejorar la usabilidad y la experiencia del usuario.

Hoy hablaremos de uno de los widgets más usados, CGridView.

Con este widget se muestra la información en forma de tabla, donde las filas representan los elementos y las columnas los atributos de éstos. Soporta paginación y ordenamiento, es totalmente personalizable y permite el filtrado de los elementos por múltiples campos.

El CGridView lo usamos fundamentalmente en los CRUD que generamos para los medelos, y lo usamos conjuntamente con un data provider, preferiblemente un CActiveDataProvider.

El siguiente código genera un CGridView con la información de todos los elementos del modelo especificado. Puesto que no se ha personalizado de ninguna manera, la tabla se mostrará con todas las columnas posibles, una por cada atributo del modelo:

 $dataProvider=new CActiveDataProvider('nombre_modelo');

 $this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider'=>$dataProvider,
 ));

Para configurar el widget con las columnas deseadas añadimos la propiedad ‘columns’ que será un array con los atributos del modelo que queremos mostrar:

 $this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider'=>$dataProvider,
    'columns'=>array(
        'titulo', // muestra el atributo "titulo"
        'categoria.nombre', // muestra el atributo 'nombre' de la relación 'categoria' declararada en el modelo
        array( // muestra el atributo 'fecha_creacion' usando una expresión para procesar el valor de éste
            'name'=>'fecha_creacion',
            'value'=>'date("M j, Y", $data->fecha_creacion)',
        ),
        array(  // muestra una columna con los botones "view", "update" y "delete"
            'class'=>'CButtonColumn',
        ),
    ),
 ));

Para personalizar los botones o añadir uno nuevo editaremos y añadiremos propiedades al array correspondiente, cuya clase es ‘CButtonColumn’:

 $this->widget('zii.widgets.grid.CGridView', array(
    'id' =>'nombre-grid', // id del grid que usamos después para actualizarlo tras borrar un registro
    'dataProvider'=>$dataProvider,
    'columns'=>array(
        'titulo',
         ...resto de atributos...
         array(
            'class' => 'CButtonColumn',
            'template'=>'{delete}{update}{accion_nueva}', // botones a mostrar
            'updateButtonUrl'=>'Yii::app()->createUrl("/nombre_modelo/update?id=$data->id" )', // url de la acción 'update'
            'deleteButtonUrl'=>'Yii::app()->createUrl("/nombre_modelo/delete?id=$data->id" )', // url de la acción 'delete'
            'deleteConfirmation'=>'Seguro que quiere eliminar el elemento?', // mensaje de confirmación de borrado
            'afterDelete'=>'$.fn.yiiGridView.update("nombre-grid");', // actualiza el grid después de borrar
            'buttons'=>array(
		'accion_nueva' => array( //botón para la acción nueva
		    'label'=>'descripción accion_nueva', // titulo del enlace del botón nuevo
		    'imageUrl'=>Yii::app()->request->baseUrl.'/ruta_carpeta/nombre_foto', //ruta icono para el botón
		    'url'=>'Yii::app()->createUrl("/nombre_modelo/accion_nueva?id=$data->id" )', //url de la acción nueva
		    ),
		),
          ),
      ),
 ));

Si queremos que los elementos de la tabla se puedan ordenar y filtrar hay que hacer lo siguiente:

Suponemos que ‘Usuario’ es el nombre de la clase del modelo con el que estamos tratando.
Vamos a usar en todo momento la variable $modelo, como si todo el código estuviera escrito de manera secuencial. Aunque poniendo el código así, todo junto por ejemplo en la vista, funcionaría, es recomendable no hacerlo. Lo codificamos de está manera a continuación para que se entienda mejor el orden de los pasos, pero indicaremos la ubicación en la que debería estar cada bloque.

-MODELO-
Antes de nada, lo que hay que hacer para poder filtrar por los atributos deseados es declarar en la función ‘rules()’ del modelo una regla que indique que en el escenario ‘search’ (se podría definir con otro nombre) los valores de los atributos pasados (por $_POST o $_GET) son seguros y se deben tener en cuenta cuando se asignen al objeto.

 array('id, nombre, apellidos', 'safe', 'on'=>'search'),

-CONTROLADOR-
Creamos un Objeto de la clase ‘Usuario’ en el escenario ‘search’ para que se tenga en cuenta la reglada declarada anteriormente en el modelo. Y recibimos, en caso de existir, los atributos que nos lleguen por GET (esto sucederá en caso de que se esté filtrando en el Grid).
El código correspondiente a esto se debería ubicar en el controlador dentro del Action en el que estemos.

 $model = new Usuario('search'); //crea  usuario en escenario 'search'
 $model->unsetAttributes();  // limpia valores por defecto

 //recibimos datos cuando se esté filtrando en el Grid y modificamos el usuario
 if(isset($_GET['Usuario']))
	$model->attributes=$_GET['Usuario']; //asociamos a los atributos del modelo los valores que nos llegan del filtro

-MODELO-
Cuando decidimos por qué atributos queremos permitir filtrar se configura la propiedad ‘criteria’ del CActiveDataProvider. La propiedad ‘criteria’ sirve para especificar diferentes opciones de la consulta .
Con la propiedad ‘sort’ indicaremos el orden por defecto que queremos que tengan los elementos de la tabla.
Para el grid del admin del CRUD que se puede generar automáticamente a partir de una tabla de una base de datos el código correspondiente a esto se ubica en la función search().

 /*se realizan las comparaciones de los atributos aquí indicados (id, nombre, apellidos)
 con los valores de los mismos atributos del modelo $model que se ha modificado por el GET anteriormente en el controlador */
 $criteria=new CDbCriteria;
 $criteria->compare('id',$model->id);
 $criteria->compare('nombre',$model->nombre,true);
 $criteria->compare('apellidos',$model->apellidos,true);

 $dataProvider = new CActiveDataProvider($model, array(
    'criteria'=>$criteria,
    'sort'=>array('defaultOrder'=>'nombre ASC'), // orden por defecto según el atributo nombre
    'pagination'=>array('pageSize'=>4), // personalizamos la paginación

  ));

-VISTA-
En el widget, para que se muestren los campos de filtrado en las columnas correspondientes hay que añadir la propiedad ‘filter’. Y el dataProvider será el generado anteriormente con la propiedad ‘criteria’. Si el código anterior estuviera ubicado en la función search() del controlador, en lugar de asignarle la variable $dataProvider se le asignaría $model->search() que es lo que por defecto viene en los CRUD generados automáticamente.

 $this->widget('zii.widgets.grid.CGridView', array(
   'dataProvider'=>$dataProvider,
   'filter'=>$model,
    'columns'=>array(
        'id',
        'nombre',
        'apellidos',
         array(
             'name' => 'direccion',
             'filter' => false, // para que no se muestre el campo de filtrar para el atributo direccion
             ),
         array(
            'class' => 'CButtonColumn',
         ),
      ),
 ));

El grid resultante se vería de la siguiente manera:

Teresa García

Comments: 22

  • osbel
    24th febrero 2013 10:54 pm

    Genial el post, estoy tratando de mostrar en un cgridview los datos obtenidos de una consulta que relaciona varios modelos. Cómo tendría que programar el search()?. Podrían ayudarme??

  • Yarita
    11th abril 2013 3:16 pm

    Hola necesito saber como puedo mostrar una tabla en una vista utilizando yii como framework

  • Silverio
    6th junio 2013 7:48 pm

    No abre el link que le enviaste a osbel, tmb tengo la misma duda. Gracias buen post.

  • Julio Luna
    14th noviembre 2013 7:52 pm

    Como podria filtrar datos del grid estando dentro de un modal?
    Desde ya gracias por tu respuesta y que buen post.

  • carito
    24th enero 2014 6:28 pm

    hola, muy bueno el tutorial, me gustaria saber si es posible que el crud generado tenga un scroll horiontal, ya que mi tabla tiene muchos atributos y al mostrarlos todos por pantalla se ve desordenado. Gracias

  • nemias
    28th enero 2014 8:33 pm

    Hola, buen post, me gustaría saber como puedo imprimir un enlace (ejm. un texto que diga “ver” y me linkee a una dirección dada), hago esta pregunta xq de las maneras q e intentado (Yii::app:createUrl, CHtml::link) terminan mostrandome el código html como texto, es decir en el casillero se muestra “…”

  • Julian
    4th marzo 2014 7:38 pm

    Pues tienes que colocar dentro de la columna la propiedad “type”=>”raw”, o “type”=>”html”

  • Lucas
    25th abril 2014 12:54 pm

    Buenas, muchas gracias por el post, varias cosas me sirvieron, sin embargo hay algo que pareciera ser de poca importancia pero no puedo encontrar el como cambiar el idioma ya sea del paginado y la cantidad de resultados que se muestran, bueno gracias por el post!

      • Lucas
        6th mayo 2014 6:04 pm

        Muchisimas gracias!!! me re sirvio

    • RBK
      26th octubre 2017 8:58 pm

      Para cambiar el idioma , ingresa a protected/config/main.php y escribe ” ‘language’=>’es’, ” como se muestra en el siguiente ejemplo:
      return array(
      ‘basePath’=>dirname(__FILE__).DIRECTORY_SEPARATOR.’..’,
      ‘name’=>’Mi proyecto’,
      ‘language’=>’es’,

      De esta manera los mensajes de error, el paginado,etc. Se mostraran en español, espero les sirva

  • leonardo
    29th abril 2014 10:04 pm

    quisiera hacer una dos filtros con listData pero uno dependiente del otro (departamentos-ciudades)en el cual ciudades depende de la elección del departamento

  • yolao
    20th mayo 2014 6:37 pm

    hola nencesito pasar valores de un m modelo a otro esto con la finalidad de crear un boton y al darle click me mande los valores de ese mismo modelo a otro qya tengo creado como puedo realizarlo??

  • Mela
    30th mayo 2014 8:02 pm

    Hola, tengo dos campos en la base de datos, nombre y apellido y quiero concatenarlos y en el momento de filtrar me busque.

  • esteban
    11th marzo 2015 8:35 pm

    Hola, buenisima la expliación…. tienes alguna idea de como quitar uno de los botones que trae por defecto el cgrid view, específicamente la x, para no dejar q el usuario borre registros?

  • ruben
    7th septiembre 2017 12:24 pm

    Hola muy bueno el tuotial una consulta quisiera hacer una dos filtros con listData pero uno dependiente del otro (departamentos-ciudades)en el cual ciudades depende de la elección del departamento
    Saludos

  • Ellis
    11th octubre 2017 10:30 am

    Buenas, estoy mostrando un TbGridView por ajax, muestra la primera pagina correctamente pero cuando selecciono otra pagina, se recarga la pagina entera.
    Sabes cual puede ser el problema

    Gracias de antemano

Post a Comment

*