Inici > Programació, Web > Paginación Ajax con historial del navegador utilizando jQuery y CakePHP 1.3.x

Paginación Ajax con historial del navegador utilizando jQuery y CakePHP 1.3.x

dissabte, 11 de setembre de 2010 Imprimir

Voy a explicaros una manera sencilla de hacer la paginación de vuestras webs y aplicaciones hechas con CakePHP en Ajax utilizando jQuery y un plugin para que el historial del navegador funcione correctamente.

Para mi ejemplo he utilizado CakePHP 1.3.3 y jQuery 1.4.2. El plugin que comentaba anteriormente se llama jQuery History Plugin y lo podéis descargar de gitHub.

Bien pues vamos a ello. Empecemos por el controlador. Simplemente tenéis que tener en cuenta que vamos a utilizar el helper de JavaScript, así que debemos activarlo:

<?php
class PagsController extends AppController
{
    var $helpers = array('Javascript');

    public function index()
    {
        $this->set('pags', $this->paginate());
    }
}

Ya veis que no tiene ninguna complicación. La vista tampoco es nada del otro mundo:

<table id="pags">
    <thead>
        <tr>
            <th><?php echo $paginator->sort('id') ?></th>
            <th><?php echo $paginator->sort('title') ?></th>
            <th><?php echo $paginator->sort('conent') ?></th>
            <th><?php echo $paginator->sort('created') ?></th>
            <th><?php echo $paginator->sort('modified') ?></th>
        </tr>
    </thead>
    <tbody>
        <?php foreach ( $pags as $pag ): ?>
        <tr>
            <td><?php echo $pag['Pag']['id'] ?></td>
            <td><?php echo $pag['Pag']['title'] ?></td>
            <td><?php echo $pag['Pag']['conent'] ?></td>
            <td><?php echo $pag['Pag']['created'] ?></td>
            <td><?php echo $pag['Pag']['modified'] ?></td>
        </tr>
        <?php endforeach ?>
        <tr>
            <td><?php echo $paginator->prev('« Anterior') ?></td>
            <td colspan="3"><?php echo $paginator->numbers() ?></td>
            <td><?php echo $paginator->next('Siguiente »') ?></td>
        </tr>
    </tbody>
</table>
<div class="ajax-loader">
	<?php echo $this->Html->image('loader.gif', array('alt' => 'Cargando...','style' => 'display: none')) ?>
</div>

Bien, ya tenemos la parte sencilla. Vamos al intríngulis de la cuestión: el JavaScript (o el jQuery, mejor dicho..).

En la vista que tenemos creada, vamos a cargar jQuery y el plugin de historial, que debéis tener ya descargados en vuestra carpeta js:

<?php
$this->Javascript->link(array('jquery-1.4.2.min', 'jquery.history'), false);

Y ahora, la paginación con Ajax. Debajo de la línea que acabamos de añadir para cargar jQuery y el History plugin añadid lo siguiente:

$script = '
jQuery(function($) { // paso $ para no tener problemas con otros frameworks JS
	$.history.init(function(url){
		if ( url == "" ) url = "'.$this->Html->url(array('controller' => 'pags', 'action' => 'index')).'"; // si no recibimos URL tenemos que cargar el índice
                $(".ajax-loader img").fadeIn(); // mostramos el gif animado
		$.ajax({
			type: "GET",
			url: url,
			dataType: "html",
			success: function(data) {
				$("#pags").html($(data).find("#pags"));
		                $(".ajax-loader img").fadeOut(); // ocultamos el gif animado
			}
		});
	});

	$("a[href*=/page:]").live("click", function(e) {
		$.history.load($(this).attr("href"));
		e.preventDefault(); // return false;
	});
});
';
$this->Javascript->codeBlock($script, array('inline' => false));

Bien, ¿qué estamos haciendo aquí? Voy a explicarlo paso por paso.

Hay que tener en cuenta que el plugin de historial hace que el código sea un poco distinto a si no lo tuviéramos con dicho plugin, ya que el método $.history.init() es el que se encarga de cargar la página mediante Ajax cuando $.history.load() es instanciado.

Por esto, dentro del método $.history.init() ejecutamos nuestro método de carga mediante Ajax. En la primera línea le indicamos que si no recibe url ésta debe ser el índice de nuestra paginación. Sin esta línea cada vez que entraseis a la página raíz (sin hash) tendríais un error de JavaScript, además de que no funcionaría el historial con la primera página nunca.

Después de eso, llamamos al método $.ajax() para hacer nuestra petición Ajax. De aquí todo está explicado en la documentación, salvo esta línea:

$("#pags").html($(data).find("#pags"));

Aquí indicamos que queremos reemplazar todo el contenido de la tabla #pags con ese mismo contenido de nuestra petición Ajax (de ahí el $(data).find("#pags") donde filtramos “#pags” de “data” [nuestra respuesta Ajax]).

Por último, en este trozo de código:

$("a[href*=/page:]").live("click", function(e) {
        $.history.load($(this).attr("href"));
        e.preventDefault(); // return false;
    });

Estamos indicando que siempre que se pulse un enlace que contenga en su ruta (href) “/page:” se dispare el método $.history.load(), al que le pasamos la url del enlace que estemos pulsando.

Utilizamos el método “live” de jQuery, ya que al reemplazar los botones de la tabla, sin live, éstos no funcionarían.

El e.preventDefault(); equivale al típico return false; que utilizamos para evitar que el botón ejecute su método por defecto (cargar la página sin Ajax).

Pues ya está, de esta manera tan sencilla tenemos paginación Ajax con historial del navegador gracias a jQuery en nuestra aplicación CakePHP.

Podéis ver un ejemplo en la siguiente dirección: http://racotecnic.com/tutorials/cake13/pags.

El problema de éste método de paginación es que, aunque le ahorramos tiempo de carga al cliente, nuestro servidor carga toda la página igualmente. Si quisierais reducir la carga de vuestro servidor con Ajax quizás deberíais ingeniároslas para cargar sólo esa parte de la vista y devolverla en formato XHTML en un JSON (o en un JSON directamente) y repoblar vuestra tabla con dicho resultado.

Algún día trataré de hacer un tutorial explicando esto con detalle 😉

Enlaces:

Edit: Cuando escribí esto no recordaba que la nueva versión de CakePHP lleva helpers para jQuery y para todo lo relacionado con Ajax. En cuanto pueda investigo cómo va el asunto y creo un tutorial con ello, pero mientras tanto…

http://book.cakephp.org/view/1592/Js
hhttp://book.cakephp.org/view/1434/HTML

Podéis ir echando un vistazo por vuestra cuenta 😀

  1. losobrinos
    divendres, 30 de març de 2012 a les 14:30 | #1

    Hermano, te felicito que detallazo. que buen aporte…

  2. dilluns, 2 d'abril de 2012 a les 14:55 | #2

    Esta entrada está muy desactualizada. Hoy en día puedes hacer esto mismo sin jQuery, utilizando las nuevas funciones para navegar por el historial de HTML5. Espero sacar pronto un update de esta entrada con esto que estoy mencionando.

    https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history

Comentaris tancats.