Entradas EtiquetadasAJAX
AJAX en CakePHP mediante jQuery
Hace poco hemos visto cómo utilizar AJAX en un formulario con CakePHP y hemos hablado en varias ocasiones de jQuery. Ahora vamos a ver cómo utilizar jQuery a través de CakePHP.
Dean Sofer comenta en Serving up actions as AJAX with jQuery in a few simple steps (
en inglés) que él no cree necesario un helper AJAX para jQuery (recordemos que el helper AJAX de CakePHP utiliza script.aculo.us) ya que un helper se utiliza para crear HTML y el javaScript debería estar lo más separado del HTML como sea posible (separación de funciones).
En este ejemplo vamos a modificar el código de nuestra aplicación de gestión de enlaces tal y como lo dejamos tras utilizar el formulario AJAX para insertar nuevos enlaces. Quitaremos todas las referencias al Helper de AJAX y le daremos la misma funcionalidad mediante jQuery.
Vamos a ver primero el controlador, explicando los cambios.
<?php
class LinksController extends AppController {
var $name = 'Links';
var $helpers = array('Html', 'Form', 'Javascript');
var $components = array('RequestHandler');
function add() {
if (!empty($this->data)) {
if ($this->Link->save($this->data)) {
//$this->flash('Enlace añadido.','/links',3);
}
}
$this->set('links', $this->Link->findAll());
//$this->render('index', 'ajax');
$this->render('list');
}
function index() {
$this->set('links', $this->Link->findAll());
}
}
?>
- Eliminamos el helper de AJAX, aunque mantenemos el de JavaScript.
- Añadimos el componente
RequestHandler. Este componente identifica las peticiones vía AJAX para poder responder con el layout AJAX (por defecto vacío). Como ahora sólo vamos a hacer llamadas aadd()mediante AJAX podríamos omitir este componente y realizar la llamada a la vista mediante$this->render('list','ajax');(hemos añadido el parámetro que indica el layout a utilizar). - Hemos cambiado la vista a mostrar por
list, que veremos a continuación.
Ahora vemos la vista principal (/app/views/links/index.ctp):
<?php
echo $javascript->link('jquery-1.3.1.min.js',false);
echo $javascript->link('jquery.form.js',false);
?>
<script type="text/javascript">
$(document).ready(function() {
var options = {
target:'#links',
clearForm: true
};
$('#newLinkForm').ajaxForm(options);
});
</script>
<h1>Enlaces disponibles</h1>
<div id="links">
<?php echo $this->element('linksList', array('links' => $links)); ?>
</div>
<h2>Añadir enlace</h2>
<?php
echo $form->create('Link', array('action' => 'add', 'id' => 'newLinkForm'));
echo $form->input('title', array('label' => 'Nombre', 'error' => __('Titulo no valido', true)));
echo $form->input('url');
echo $form->submit('Añadir',array('escape'=>false));
echo $form->end();
?>
- Lógicamente he sustituido los links a script.aculo.us por los de jQuery. Utilizo el plugin jQuery Form Plugin que me facilita la introducción de AJAX en el formulario.
- Añado el código JavaScript prácticamente como aparece en la página de jQuery Form Plugin. En
targetse le indica el div en el que se va a introducir la respuesta (en este caso el que tenga id “links”). Al final le aplicamos el métodoajaxFormal formulario con id “newLinkForm”. - He sustituido todo el listado de links por una llamada a un elemento CakePHP pasándole unos datos (
$this->element('linkslist', array('links' => $links));). Luego explicaré el por qué de este cambio. - La creación del formulario la hago como inicialmente mediante el helper de formularios (ya no mediante el de AJAX). Le pongo el id como parámetro.
Vamos a ver ahora el elemento al que hacíamos referencia en la vista. Lo encontraremos en /app/views/elements/linksList.ctp.
<?php foreach ($links as $link): ?>
<p>
<a href="<?php echo $link['Link']['url']; ?>"><?php echo $link['Link']['title']; ?></a></p>
<p>Añadido: <?php echo $link['Link']['created']; ?></p>
<ul>
<?php foreach ($link['Comment'] as $comment): ?>
<li><?php echo $comment['comment'] . ' (' . $comment['created'] . ')'; ?></li>
<?php endforeach; ?>
<li><?php echo $html->link('Añadir comentario', '/comments/add/' . $link['Link']['id']);?></li>
</ul>
<?php endforeach; ?>
Como podemos ver es exactamente el mismo código que teníamos en la página principal y que generaba el listado de enlaces. Lo que hemos hecho es crear un elemento de CakePHP, es decir, una porción reutilizable. Y la reutilizamos en la página principal y en la nueva vista que hemos creado para la respuesta AJAX, que sólo tiene que contener el listado. Vemos dicha vista (/app/views/links/list.ctp) a continuación:
<?php echo $this->element('linkslist', array('links' => $links)); ?>
Y con esto ya tenemos funcionando el formulario AJAX mediante jQuery.
3 comments 1 Junio 2009
Formulario AJAX en CakePHP
En esta nueva entrada dedicada a CakePHP voy a explicar cómo utilizar un poco de AJAX en nuestra aplicación. AJAX realiza peticiones al servidor en segundo plano, por lo que partes de la página se pueden ir refrescando sin tener que recargar la página entera.
Voy a utilizar el ejemplo del gestor de enlaces que ya tenía en marcha en anteriores entradas de CakePHP en Tus Ceros Y Mis Unos. En concreto voy a facilitar el agregar nuevos enlaces pasando el formulario de añadir enlace a la página principal, de forma que al completar dicho formulario se refresque en el listado sin recargar la página completa.
El ayudante (“helper”) de AJAX en CakePHP utiliza las librerías JavaScript script.aculo.us y Prototype. Nos descargamos la última versión estable de script.aculo.us (la 1.8.2 en el momento de escribir esta entrada) ya que incluye Prototype. Copiamos tanto el fichero de Prototype (en lib dentro de la carpeta de script.aculo.us) como todos los ficheros propios de script.aculo.us (en src) a la carpeta de JavaScript de nuestra aplicación CakePHP: /app/webroot/js.
Insertamos en la plantilla por defecto de nuestro sitio web (/app/views/layouts/default.thtml) una línea para que CakePHP sepa dónde insertar los scripts posteriormente. La línea es <?php echo $scripts_for_layout ?> al igual que teníamos <?php echo $content_for_layout ?> que indicaba dónde insertar el contenido:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>TCYMU CakePHP Gestión de Enlaces</title> <?php echo $scripts_for_layout ?> </head> <body> <h1>Tus ceros y mis unos</h1> <h2>Gestión de enlaces</h2> <?php echo $content_for_layout ?> <h3>TCYMU por Miguel Orbegozo</h3> </body> </html>
Ahora es el momento de modificar el controlador de nuestra aplicación. Primero enumero los cambios y luego muestro el código completo. Las modificaciones son las siguientes:
- Definimos la variable
helperscon los ayudantes que se utilizan. Si no sobrescribimos la variable se incluyen el de HTML y el de formularios. Además queremos añadir el de JavaScript y el de AJAX.
var $helpers = array('Html', 'Form', 'Javascript', 'Ajax'); - Modificamos la función
add, ya que ahora responderá a una petición AJAX. Lo que hacemos tras insertar el contenido del formulario (exactamente igual que antes) es obtener la lista de enlaces (igual que en la funciónindex) y mostrar la vistaindex, con la particularidad de que le pasamos el parámetro'ajax'para que sepa que es una respuesta a una petición AJAX.
<?php
class LinksController extends AppController {
var $name = 'Links';
var $helpers = array('Html', 'Form', 'Javascript', 'Ajax');
function add() {
if (!empty($this->data)) {
if ($this->Link->save($this->data)) {
//$this->flash('Enlace añadido.','/links',3);
}
}
$this->set('links', $this->Link->findAll());
$this->render('index', 'ajax');
}
function index() {
$this->set('links', $this->Link->findAll());
}
}
?>
Ahora modificaremos la vista de nuestra página de inicio (/app/views/links/index.thtml). Como antes primero se enumeran los cambios para después ver el código en su totalidad.
- Añado las librerías JavaScript mediante el método de AjaxHelper
link.
<?php
echo $javascript->link('prototype.js',false);
echo $javascript->link('scriptaculous.js?load=effects',false);
?>
Dos pequeños detalles. El segundo parámetro hace que se añadan en la cabecera (en$scripts_for_layoutque definimos antes). Al ponerscriptaculous.js?load=effectshacemos que sólo se carguen los scripts de efectos, ya que si sólo hubiéramos puestoscriptaculouscarga todos los ficheros de script.aculo.us - La lista de enlaces la vamos a situar en un
divcon un identificador determinado, ya que esta será la parte que se refresque tras la petición AJAX. Lo creamos mediante el ayudante de AJAX y sus métodosdivydivEnd.
<?php echo $ajax->div('links'); ?>
...
<?php echo $ajax->divEnd('links'); ?> - Sustituimos el enlace que nos llevaba a la página de añadir enlace por el formulario que aparecía en esta página.
- Sustituimos la creación del formulario. En lugar de utilizar el método
formdel ayudante de formularios utilizaremos el métodoformpero del ayudante de AJAX. A este método se le pasa la función del controlador, el tipo de envío (“get” o “post”) y un array de opciones en el que enupdatele indicamos eldivque debe refrescar.
echo $ajax->form('/add', 'post', array('update' => 'links'));
<?php
echo $javascript->link('prototype.js',false);
echo $javascript->link('scriptaculous.js?load=effects',false);
?>
<h1>Enlaces disponibles</h1>
<?php echo $ajax->div('links'); ?>
<?php foreach ($links as $link): ?>
<p>
<a href="<?php echo $link['Link']['url']; ?>"><?php echo $link['Link']['title']; ?></a></p>
<p>Añadido: <?php echo $link['Link']['created']; ?></p>
<ul>
<?php foreach ($link['Comment'] as $comment): ?>
<li><?php echo $comment['comment'] . ' (' . $comment['created'] . ')'; ?></li>
<?php endforeach; ?>
<li><?php echo $html->link('Añadir comentario', '/comments/add/' . $link['Link']['id']);?></li>
</ul>
<?php endforeach; ?>
<?php echo $ajax->divEnd('links'); ?>
<h2>Añadir enlace</h2>
<?php
echo $ajax->form('/add', 'post', array('update' => 'links'));
echo $form->input('title', array('label' => 'Nombre', 'error' => __('Titulo no valido', true)));
echo $form->input('url');
echo $form->submit('Añadir',array('escape'=>false));
echo $form->end();
?>
Con estos cambios ya se actualizará nuestra lista de enlaces tras rellenar el formulario y sin recargar la página. Misión cumplida.
3 comments 5 Mayo 2009




