Formulario AJAX en CakePHP

5 mayo 2009 at 9:40 pm 4 comentarios

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:

  1. Definimos la variable helpers con 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');
  2. 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ón index) y mostrar la vista index, 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.

  1. 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_layout que definimos antes). Al poner scriptaculous.js?load=effects hacemos que sólo se carguen los scripts de efectos, ya que si sólo hubiéramos puesto scriptaculous carga todos los ficheros de script.aculo.us
  2. La lista de enlaces la vamos a situar en un div con 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étodos div y divEnd.
    <?php echo $ajax->div('links'); ?>
    ...
    <?php echo $ajax->divEnd('links'); ?>
  3. Sustituimos el enlace que nos llevaba a la página de añadir enlace por el formulario que aparecía en esta página.
  4. Sustituimos la creación del formulario. En lugar de utilizar el método form del ayudante de formularios utilizaremos el método form pero 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 en update le indicamos el div que 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&#91;'Link'&#93;&#91;'url'&#93;; ?>"><?php echo $link&#91;'Link'&#93;&#91;'title'&#93;; ?></a></p>
<p>Añadido: <?php echo $link&#91;'Link'&#93;&#91;'created'&#93;; ?></p>
<ul>
<?php foreach ($link&#91;'Comment'&#93; as $comment): ?>
<li><?php echo $comment&#91;'comment'&#93; . ' (' . $comment&#91;'created'&#93; . ')'; ?></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.

Anuncios

Entry filed under: PHP. Tags: , , .

Linux para niños ¡¡Cumplimos un añito!!

4 comentarios Add your own

  • […] Junio 2009 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 […]

  • 2. Gonzalo  |  15 julio 2009 en 9:11 pm

    Hola! Muchas gracias por el post! Me anduvo de maravillas :)… Ahora quisiera hacerte una consulta de cake que no tiene nada que ver con esto.
    Yo ejecuto el ajax en un popUp y cuando termino de cargar quiero que cierre el popup y vuelva a la ventana opener. El problema que tengo es que en el onclose de la ventana popup, me cierra la sesión por lo que cuando vuelvo a la opener, caducó mi sesión 😦
    Hay alguna manera de sacarle esa configuración??

    Muchas gracias!
    Gracias por compartir tus conocimientos con principiantes 🙂

  • 3. Miguel  |  16 julio 2009 en 8:15 am

    Hola Gonzalo, gracias por tu comentario.

    La verdad es que no tengo ni idea del tema de la sesión y es que yo soy también bastante principiante…

    De todas maneras si veo algo te lo pondré.

    Un saludo y gracias.

  • 4. ceamha  |  30 mayo 2011 en 7:10 pm

    Hola Miguel,

    Esta muy bien tu post. Dado que está publicado ya hace algunos años es probable que me puedas colaborar con esta pregunta.

    ¿Cómo puedo hacer para que me envie al index, pero pasándole un ID como filtro?

    Yo tengo lo siguiente:

    function index($perfil=null) {
    $this->Contacto->recursive = 0;
    $this->set('contactos', $this->paginate('Contacto', array('Contacto.perfile_id'=>$perfil)));
    $this->set('perfile_id',$perfil);
    }

    function add() {
    if (!empty($this->data)) {
    if ($this->Contacto->save($this->data)) {

    }
    }
    $perfiles = $this->Contacto->Perfile->find('list');
    $this->set(compact('perfiles'));
    $this->autoRender=NULL;
    $this->layout = 'ajax';
    $this->render("index/".$this->data['perfile_id']);
    }

    ¿Cuál es el problema? Que cuando voy a guardar me genera este error:

    Error: The view for ContactosController::add() was not found.
    Error: Confirm you have created the file: \app\views\contactos\index\1.ctp

    Es claro que no tengo esa vista, solo estoy intentando guardar con ese ID para volver a ver el index con el filtro que le hice.

    Espero me haya hecho entender. Te agradecería si me puedes responder y colaborar con esto.

    Saludos.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Trackback this post  |  Subscribe to the comments via RSS Feed


Mi perfil

View Miguel Orbegozo's profile on LinkedIn

Feedjit

Feeds

Otros…

BlogESfera Directorio de Blogs Hispanos - Agrega tu Blog

Bitacoras.com

Add to Technorati Favorites


A %d blogueros les gusta esto: