El tutorial Jobeet

18.5. AJAX en las acciones

Cuando JavaScript está activado, jQuery intercepta todas las teclas pulsadas por el usuario en el cuadro de búsqueda y realiza la llamada a la acción search. Si JavaScript no se encuentra activado, se ejecuta la misma acción search cuando el usuario envía el formulario pulsando la tecla ENTER o pulsando el botón Search.

Por tanto, la acción search necesita conocer si la petición se realiza mediante AJAX o no. Cuando una petición se realiza con AJAX, el método isXmlHttpRequest() del objeto de la petición devuelve true.

Nota El método isXmlHttpRequest() funciona con todas las principales librerías de JavaScript, como por ejemplo Prototype, Mootools y jQuery.

// apps/frontend/modules/job/actions/actions.class.php
public function executeSearch(sfWebRequest $request)
{
  if (!$query = $request->getParameter('query'))
  {
    return $this->forward('job', 'index');
  }

  $this->jobs = JobeetJobPeer::getForLuceneQuery($query);

  if ($request->isXmlHttpRequest())
  {
    return $this->renderPartial('job/list', array('jobs' => $this->jobs));
  }
}

Como jQuery no recarga la página y sólo reemplaza el contenido del elemento #jobs del DOM con el contenido de la respuesta del servidor, la página devuelta no debería estar decorada por el layout. Como este caso es el habitual, Symfony deshabilita por defecto el layout cuando la petición se realiza con AJAX.

Además, en vez de devolver la plantilla completa, sólo tenemos que devolver el contenido del elemento parcial job/list. El método renderPartial() de la acción anterior devuelve como respuesta el contenido del elemento parcial y no la plantilla completa.

Si el usuario borra todos los caracteres del cuadro de búsqueda o si la búsqueda no devuelve ningún resultado, vamos a mostrar un mensaje adecuado en lugar de la pantalla vacía que se muestra actualmente. Para que la acción devuelva una simple cadena de texto, podemos utilizar el método renderText():

// apps/frontend/modules/job/actions/actions.class.php
public function executeSearch(sfWebRequest $request)
{
  if (!$query = $request->getParameter('query'))
  {
    return $this->forward('job', 'index');
  }

  $this->jobs = JobeetJobPeer::getForLuceneQuery($query);

  if ($request->isXmlHttpRequest())
  {
    if ('*' == $query || !$this->jobs)
    {
      return $this->renderText('No results.');
    }
    else
    {
      return $this->renderPartial('job/list', array('jobs' => $this->jobs));
    }
  }
}

Nota Si quieres devolver el contenido de un componente en una acción, puedes utilizar el método renderComponent().