<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog cakephp en español por Hospedaxes &#187; ajax</title>
	<atom:link href="http://cakephp.hospedaxes.com/category/ajax/feed" rel="self" type="application/rss+xml" />
	<link>http://cakephp.hospedaxes.com</link>
	<description>Blog sobre desarrollo web con cakephp en español por Hospedaxes</description>
	<lastBuildDate>Mon, 26 Apr 2010 07:11:23 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Tree Behavior o cómo crear una estructura jerárquica</title>
		<link>http://cakephp.hospedaxes.com/tree-behavior-o-como-crear-una-estructura-jerarquica</link>
		<comments>http://cakephp.hospedaxes.com/tree-behavior-o-como-crear-una-estructura-jerarquica#comments</comments>
		<pubDate>Wed, 14 Oct 2009 08:42:33 +0000</pubDate>
		<dc:creator>nuria</dc:creator>
				<category><![CDATA[Noticias]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[árbol]]></category>
		<category><![CDATA[cakephp 1.2]]></category>
		<category><![CDATA[organización jerárquica]]></category>
		<category><![CDATA[tree behavior]]></category>

		<guid isPermaLink="false">http://cakephp.hospedaxes.com/?p=237</guid>
		<description><![CDATA[En esta ocasión hablaremos de cómo crear una estructura jerárquica utilizando el Tree Behavior de CakePHP. Este comportamiento facilita muchísimo las cosas a la hora de manipular árboles jerárquicos de datos.
Utilizaremos también la librería de Javascript Ext JS para poder manipular el árbol gráficamente de manera sencilla, utilizando drag and drop.
Lo primero que tendremos que [...]]]></description>
			<content:encoded><![CDATA[<p>En esta ocasión hablaremos de cómo crear una estructura jerárquica utilizando el <a title="CakePHP: Tree Behavior" href="http://api.cakephp.org/class/tree-behavior">Tree Behavior</a> de CakePHP. Este comportamiento facilita muchísimo las cosas a la hora de manipular árboles jerárquicos de datos.</p>
<p>Utilizaremos también la librería de Javascript <a title="Ext JS" href="http://www.extjs.com/">Ext JS</a> para poder manipular el árbol gráficamente de manera sencilla, utilizando <a title="Wikipedia: Arrastrar y soltar" href="http://es.wikipedia.org/wiki/Arrastrar_y_soltar"><em>drag and drop</em></a>.</p>
<p>Lo primero que tendremos que hacer será añadir en la tabla de la base de datos de la entidad. Utilizando los nombres por defecto de Cake, serían los siguientes campos:</p>
<ul>
<li><em>parent_id</em>: hace referencia al padre del elemento.</li>
<li><em>lft</em>: almacena el identificador del elemento de la izquierda en el mismo nivel.</li>
<li><em>rght</em>: almacena el identificador del elemento de la derecha en el mismo nivel.</li>
</ul>
<p>Incluiremos también los campos <em>id</em> y <em>nombre</em>, en una entidad denominada, por ejemplo, Categoria.</p>
<p>El modelo lo haríamos de la siguiente manera:</p>
<p>Este comportamiento tiene funciones muy útiles para la manipulación del árbol. Las más utilizadas quizás sean las siguientes:</p>
<ul>
<li><strong><em>children</em></strong>: devuelve los hijos de un nodo concreto, pudiendo seleccionar si deseamos obtener sólo los hijos directos o todos los hijos en el árbol.</li>
<li><strong><em>generatetreelist</em></strong>: función muy útil para obtener los elementos a introducir en un select de HTML.</li>
<li><strong>getpath</strong>: devuelve todo el path hasta el nodo especificado en un array.</li>
<li><strong>movedown</strong> y <strong>moveup</strong>: sirven para bajar o subir un nivel de un nodo del árbol.</li>
<li><strong>removefromtree</strong>: elimina un nodo del árbol sin perder la estructura, es decir, modificando el padre de sus hijos.</li>
<li><strong>reorder</strong>: reordena un nodo (arrastrando también a sus hijos) en función de los parámetros especificados.</li>
</ul>
<p>Para realizar la manipulación visual del árbol de categorías crearemos las siguientes funciones en el controlador <em>app/controllers/categorias_controller.php</em> sería:</p>
<pre class="prettyprint"><code>&lt;?php

class CategoriasController extends AppController{

var $helpers = array( 'Javascript');

// Función para organizar las categorías
function organizar() {}

function getnodes() {
   Configure::write('debug', 0);
   // obtener el identificador del padre que se envío por POST vía Ajax
   $parent = intval($this-&gt;params['form']['node']);
   // encontrar los hijos directos del nodo anterior
   $nodes = $this-&gt;Categoria-&gt;children($parent, true, null, 'Categoria.lft ASC');

   $this-&gt;set(compact('nodes'));

   $this-&gt;render('getnodes', 'ajax');
}

function reorder()
{
   Configure::write('debug', 0);

   // delta es la diferencia en la posición (1 = nodo siguiente, -1 = nod anterior)
   $node = intval($this-&gt;params['form']['node']);
   $delta = intval($this-&gt;params['form']['delta']);

   if ($delta &gt; 0) {
      $this-&gt;Categoria-&gt;movedown($node, abs($delta));
   } elseif ($delta &lt; 0) {
      $this-&gt;Categoria-&gt;moveup($node, abs($delta));
   }

   exit('1');
}

function reparent()
{
   Configure::write('debug', 0);

   $node = intval($this-&gt;params['form']['node']);
   $parent = intval($this-&gt;params['form']['parent']);
   $position = intval($this-&gt;params['form']['position']);

   // guardamos el nuevo padre de la categoría
   $this-&gt;Categoria-&gt;id = $node;
   $this-&gt;Categoria-&gt;saveField('parent_id', $parent);

   // Si position == 0, nos movemos al inicio.
   // En otro caso, calculamos la distancia que nos moveremos ($delta).
   if ($position == 0) {
      $this-&gt;Categoria-&gt;moveup($node, true);
   } else {
      $count = $this-&gt;Categoria-&gt;childcount($parent, true);
      $delta = $count - $position - 1;
      if ($delta &gt; 0) {
         $this-&gt;Categoria-&gt;moveup($node, $delta);
      }
   }

   exit('1');
}
}
?&gt;</code></pre>
<p>Sólo nos quedaría hacer las vistas. En este caso, necesitamos crear 2 vistas: organizar.ctp y getnodes.ctp.</p>
<pre class="prettyprint"><code>// app/views/categorias/organizar.ctp

&lt;?php echo $html-&gt;css('/js/ext-2.0.1/resources/css/ext-custom.css'); ?&gt;
&lt;?php echo $javascript-&gt;link('/js/ext-2.0.1/ext-custom.js'); ?&gt;

&lt;script type="text/javascript"&gt;
Ext.BLANK_IMAGE_URL = '&lt;?php echo $html-&gt;url('/js/ext-2.0.1/resources/images/default/s.gif') ?&gt;';

Ext.onReady(function(){

   var getnodesUrl = '&lt;?php echo $html-&gt;url('/categorias/getnodes') ?&gt;';
   var reorderUrl = '&lt;?php echo $html-&gt;url('/categorias/reorder') ?&gt;';
   var reparentUrl = '&lt;?php echo $html-&gt;url('/categorias/reparent') ?&gt;';

   var Tree = Ext.tree;

   var tree = new Tree.TreePanel({
      el:'tree-div',
      autoScroll:true,
      animate:true,
      enableDD:true,
      containerScroll: true,
      rootVisible: true,
      loader: new Ext.tree.TreeLoader({
         dataUrl:getnodesUrl
      })
    });

   var root = new Tree.AsyncTreeNode({
      text:'Categorías',
      draggable:false,
      id:'root'
   });

   tree.setRootNode(root);
   tree.setHeight('auto');

   var oldPosition = null;
   var oldNextSibling = null;

   tree.on('startdrag', function(tree, node, event){
      oldPosition = node.parentNode.indexOf(node);
      oldNextSibling = node.nextSibling;
   });

   tree.on('movenode', function(tree, node, oldParent, newParent, position){

   if (oldParent == newParent){
      var url = reorderUrl;
      var params = {'node':node.id, 'delta':(position-oldPosition)};
   } else {
      var url = reparentUrl;
      var params = {'node':node.id, 'parent':newParent.id, 'position':position};
   }

tree.disable();

Ext.Ajax.request({
   url:url,
   params:params,
   success:function(response, request) {
      // if the first char of our response is zero, then we fail the operation,
      // otherwise we re-enable the tree
      if (response.responseText.charAt(0) != 1){
         request.failure();
      } else {
         tree.enable();
      }
   },
   failure:function() {
      // we move the node back to where it was beforehand and
      // we suspendEvents() so that we don't get stuck in a possible infinite loop
      tree.suspendEvents();
      oldParent.appendChild(node);
      if (oldNextSibling){
         oldParent.insertBefore(node, oldNextSibling);
      }
      tree.resumeEvents();
      tree.enable();
      alert("Oh no! Your changes could not be saved!");
   }
});
});

tree.render();
root.expand();
});
&lt;/script&gt;

&lt;div id="tree-div"&gt;&lt;/div&gt;</code></pre>
<p>Y la última vista:</p>
<pre class="prettyprint"><code>&lt;?php
// app/views/categorias/getnodes.ctp
$data = array();
foreach ($nodes as $node)
{</code>   <code>$data[] = array(</code>      <code>"text" =&gt; $node['Categoria']['nombre'],</code>      <code>"id" =&gt; $node['Categoria']['id']</code>   <code>);
}
echo $javascript-&gt;object($data);
?&gt;</code></pre>
<p>Ya sólo nos quedaría descargarnos la librería <a title="Ext JS" href="http://www.extjs.com/" target="_blank">ExtJS</a> y copiarla en la carpeta /app/webroot/js. En el <a title="Demostración de funcionamiento de Ext JS" href="http://cakephp.hospedaxes.com/pruebas/tree_behavior">ejemplo</a>, se ha utilizado la versión 2.0.1.</p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 289px; width: 1px; height: 1px;">
<pre style="display: block;">Categoria</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://cakephp.hospedaxes.com/tree-behavior-o-como-crear-una-estructura-jerarquica/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Autocompletar ajax</title>
		<link>http://cakephp.hospedaxes.com/autocompletar-ajax</link>
		<comments>http://cakephp.hospedaxes.com/autocompletar-ajax#comments</comments>
		<pubDate>Thu, 07 Aug 2008 10:20:32 +0000</pubDate>
		<dc:creator>bernal</dc:creator>
				<category><![CDATA[ajax]]></category>
		<category><![CDATA[cakephp-1.2]]></category>

		<guid isPermaLink="false">http://www.hospedaxes.com/blog-cakephp/?p=10</guid>
		<description><![CDATA[En la entrada semanal de nuestro blog relacionado con cakephp, vamos a hablar sobre autocompletar los campos mediante ajax, una opción que puede simplificar bastante la inserción de datos por parte de los usuarios y que a su vez resulta bastante elegante.
El funcionamiento es sencillo, al introducir una letra en un campo de entrada se [...]]]></description>
			<content:encoded><![CDATA[<p>En la entrada semanal de nuestro blog relacionado con <a href="http://cakephp.hospedaxes.com/">cakephp</a>, vamos a hablar sobre autocompletar los campos mediante ajax, una opción que puede simplificar bastante la inserción de datos por parte de los usuarios y que a su vez resulta bastante elegante.</p>
<p>El funcionamiento es sencillo, al introducir una letra en un campo de entrada se buscarán en la base de datos las coincidencias con el texto que hemos insertado, mostrándolas como una lista y dándonos la opción de elegir entre todos los resultados.</p>
<p>Esta opción se usa habitualmente con los listados de paises, en nuestro ejemplo utilizaremos, como en el ejemplo de <a href="http://cakephp.hospedaxes.com/actualizar-el-contenido-de-un-select-con-ajax">actualizar un select con ajax</a>, las provincias españolas.</p>
<p>En <a href="http://cakephp.hospedaxes.com/pruebas/ejemplo_complete" target="_blank">este enlace</a> se puede comprobar el funcionamiento.</p>
<p>Añadirlo en nuestro proyecto es realmente sencillo, supongamos que tenemos un modelo, cuyo controlador tiene una operación y una vista asociada, que será donde queremos utilizarlo.</p>
<p>Para ello en la vista, añadimos este trozo de código dentro de un formulario:</p>
<pre class="prettyprint">
 echo $form->label('provincias','Provincias');
 echo $ajax->autoComplete('nombre','autocomplete');
</pre>
<p>Añadimos un label que tendrá el texto Provincias y un campo de entrada autocomplete, este recibe como parámetros, el nombre del campo y como segundo parámetro la url donde se encuentra la función a la que se va a llamar cuando se introduzca una letra, en nuestro caso, la vamos a añadir en el mismo controlador que estamos utilizando, si no fuese así la dirección sería &#8216;/nombre_del_controlador/función&#8217;.</p>
<p>En segundo lugar, creamos la función autocomplete, dentro del controlador utilizado añadimos el siguiente código:</p>
<pre class="prettyprint">
  function autocomplete()
  {
 	$str = trim($this->data['Provincia']['nombre']);
	$str = str_replace("á","a",$str);
	$str = str_replace("é","e",$str);
	$str = str_replace("í","i",$str);
	$str = str_replace("ó","o",$str);
	$str = str_replace("ú","u",$str);
	$str = str_replace("Á","A",$str);
	$str = str_replace("É","E",$str);
	$str = str_replace("Í","I",$str);
	$str = str_replace("Ó","O",$str);
	$str = str_replace("Ú","U",$str);
	$str = str_replace("Ñ","ñ",$str);
	$condicion = "REPLACE (REPLACE( REPLACE( REPLACE( REPLACE( REPLACE ( Provincia.nombre,'á','a'), 'é','e'),'í','i'),'ó','o'),'ú','u'),'Ñ','ñ') LIKE "$str%"";
	$this->set('provincias', Set::combine($this->Provincia->findAll($condicion,array('Provincia.nombre','Provincia.id'),'Provincia.nombre'), "{n}.Provincia.id","{n}.Provincia.nombre"));
	$this->render('autocomplete','ajax');
 }
</pre>
<p>La función es muy sencilla, realiza la búsqueda en la base de datos de todas las provincias cuyo nombre coincida con el texto introducido, pasado en $this->data con el nombre que se indica en el primer parámetro de la función autocomplete utilizada en la vista, para eso se añade en la condición la opción LIKE cadena% de sql.</p>
<p>Todas las opciones que añadimos anteriormente sirven para ignorar los acentos, tanto en la cadena que introducimos como en los nombres de las provincias almacenadas en la base de datos, con esto al realizar la búsqueda funcionará aunque cometamos fallos ortográficos.</p>
<p>Crearemos una vista para esta función, con una única línea de código, que crea una lista con todas las entradas del array.</p>
<pre class="prettyprint">
 echo $html->nestedList($provincias);
</pre>
<p>Y por último añadiremos al css que estemos utilizando, dos clases que modificarán el aspecto del listado que hemos creado:</p>
<pre class="prettyprint">
  div.auto_complete {
 	position :absolute;
 	width :250px;
 	background-color :white;
 	border :1px solid #888;
 	margin :0px;
 	padding :0px;
  }

 div.auto_complete ul{
	list-style: none;
	margin: 0px;
 }

 li.selected{
	background-color: #ffb;
 }
</pre>
<p>Con esto ya tendremos un campo de texto en el que al añadir texto se generará un listado con todas las entradas de la base de datos que coincidan con el texto introducido.</p>
]]></content:encoded>
			<wfw:commentRss>http://cakephp.hospedaxes.com/autocompletar-ajax/feed</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Calendario en CakePHP</title>
		<link>http://cakephp.hospedaxes.com/calendario-en-cakephp</link>
		<comments>http://cakephp.hospedaxes.com/calendario-en-cakephp#comments</comments>
		<pubDate>Mon, 28 Jul 2008 12:20:04 +0000</pubDate>
		<dc:creator>nuria</dc:creator>
				<category><![CDATA[Noticias]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[cakephp-1.2]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[cakephp 1.2]]></category>
		<category><![CDATA[calendario]]></category>
		<category><![CDATA[helper]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.hospedaxes.com/blog-cakephp/?p=12</guid>
		<description><![CDATA[Cuando estamos desarrollando una página web, a menudo necesitamos introducir un calendario que nos permita seleccionar las fechas sin tener que escribirlas a mano.
En este post vamos a explicar cómo hacer esto, utilizando para ello el calendario DHTML Calendar desarrollado por Dynarch. Es un calendario con licencia GNU y que cubre perfectamente todas las funcionalidades [...]]]></description>
			<content:encoded><![CDATA[<p>Cuando estamos <a href="http://www.hospedaxes.com">desarrollando una página web</a>, a menudo necesitamos introducir un calendario que nos permita seleccionar las fechas sin tener que escribirlas a mano.</p>
<p>En este post vamos a explicar cómo hacer esto, utilizando para ello el calendario <a href="http://www.dynarch.com/projects/calendar/">DHTML Calendar</a> desarrollado por <a href="http://www.dynarch.com/">Dynarch</a>. Es un calendario con licencia <a href="http://es.wikipedia.org/wiki/Licencia_p%C3%BAblica_general_de_GNU">GNU</a> y que cubre perfectamente todas las funcionalidades que necesitamos.</p>
<p>Todos los ficheros necesarios para introducir el calendario en nuestra página web, junto con la estructura como se organizan en CakePHP 1.2, pueden descargarse <a href="http://cakephp.hospedaxes.com/wp-content/uploads/2008/07/calendariotar.gz">calendario</a>. Lo explicaremos paso a paso.</p>
<p>Lo primero que tenemos que hacer es descargarnos el calendario (podemos hacerlo directamente de la página web de Dynarch, o bien mediante el enlace del párrafo anterior) y descomprimirlo en la carpeta <em>app/webroot/js</em>. Necesitamos también otro fichero javascript, <em>common.js</em>, que también meteremos en esa carpeta. En el <em>body</em>, incluiremos estos ficheros escribiendo:</p>
<pre class="prettyprint">// Calendar includes
echo $javascript->link('jscalendar-1.0/calendar.js');
echo $javascript->link('jscalendar-1.0/lang/calendar-es.js');
echo $javascript->link('common.js');
// CSS Theme
echo $html->css('../js/jscalendar-1.0/skins/aqua/theme');</pre>
<p>Necesitamos ahora implementar un helper para que nos sea mucho más fácil la utilización de este calendario. Lo descargamos del enlace anterior y lo metemos en la carpeta <em>app/views/helpers</em>. Si miramos el código de este helper vemos que tenemos dos funciones, <strong>picker</strong> y <strong>flat</strong>, que nos permiten hacer que este calendario aparezca al pulsar un botón o que esté siempre visible en nuestra página.</p>
<p>Ya sólo nos falta introducir este calendario en nuestras páginas.</p>
<p>En el controlador, importamos el helper:</p>
<pre class="prettyprint">var $helpers = array('DatePicker');</pre>
<p>Y en la vista mostramos el calendario:</p>
<pre class="prettyprint">echo $datePicker->flat('fechaCalendarioFlat', array('id'=>'fechaCalendarioFlat'));
echo $datePicker->picker('fechaCalendarioPicker', array('id'=>'fechaCalendarioPicker'));</pre>
<p>Podemos ver una demostración del funcionamiento del calendario en este <a title="Calendario en CakePHP 1.2" href="http://cakephp.hospedaxes.com/pruebas/calendario">enlace</a>.</p>
<p>A partir del código proporcionado, podríamos añadir muchas funcionalidades. Por ejemplo, podremos editar el código del helper, para añadirle un observador de javascript al calendario tipo flat y que al pulsar en una fecha nos lleve a otra url, o podríamos hacer que ciertas fechas especiales se coloreen de manera distinta al resto.</p>
<p><em>NOTA:</em> Tras el comentario de Hijal, hemos comprobado que la versión del helper enlazada en este post es para la versión 1.1 de CakePHP, para la versión 1.2 únicamente habría que modificar las funciones <strong>flat</strong> y <strong>picker</strong>, de la manera que se muestra a continuación:</p>
<p>function picker($fieldName, $options = array()) {<br />
$this-&gt;_setup();<br />
$htmlAttributes = $this-&gt;domId($options);<br />
$divOptions['class'] = &#8216;date&#8217;;<br />
$options['type'] = &#8216;text&#8217;;<br />
$options['div']['class'] = &#8216;date&#8217;;<br />
$options['after'] = $this-&gt;Html-&gt;link($this-&gt;Html-&gt;image(&#8217;../js/jscalendar-1.0/img.gif&#8217;), &#8216;#&#8217;, array(&#8217;onClick&#8217;=&gt;&#8221;return showCalendar(&#8217;&#8221;.$htmlAttributes['id'].&#8221;&#8216;, &#8216;&#8221;.$this-&gt;format.&#8221;&#8216;); return false;&#8221;), null, false);<br />
$output = $this-&gt;input($fieldName, $options);<br />
return $output;<br />
}</p>
<p>function flat($fieldName, $options = array()){<br />
$this-&gt;_setup();<br />
$htmlAttributes = $this-&gt;domId($options);<br />
$divOptions['class'] = &#8216;date&#8217;;<br />
$options['type'] = &#8216;hidden&#8217;;<br />
$options['div']['class'] = &#8216;date&#8217;;<br />
$hoder = &#8216;&lt;div id=&#8221;&#8216;.$htmlAttributes['id'].&#8217;_cal&#8217;.'&#8221;&gt;&lt;/div&gt;&lt;script type=&#8221;text/javascript&#8221;&gt;showFlatCalendar(&#8221;&#8216;.$htmlAttributes['id'].&#8217;&#8221;, &#8220;&#8216;.$htmlAttributes['id'].&#8217;_cal&#8217;.'&#8221;, &#8220;&#8216;.$this-&gt;format.&#8217;&#8221;, function(cal, date){document.getElementById(\&#8221;.$htmlAttributes['id'].&#8221;.&#8217;\').value = date});&lt;/script&gt;&#8217;;<br />
$output = $this-&gt;input($fieldName, $options).$hoder;<br />
return $output;<br />
}</p>
<p>Estas dos funciones se encuentran ya modificadas en el fichero tar.gz que se adjunta en el post. Junto con otra modificación surgida tras el siguiente comentario en el foro <a href="http://cakephp.hospedaxes.com/dudas/topic/calendario-en-cakephp" target="_blank">http://cakephp.hospedaxes.com/dudas/topic/calendario-en-cakephp</a></p>
]]></content:encoded>
			<wfw:commentRss>http://cakephp.hospedaxes.com/calendario-en-cakephp/feed</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Actualizar el contenido de un select con ajax.</title>
		<link>http://cakephp.hospedaxes.com/actualizar-el-contenido-de-un-select-con-ajax</link>
		<comments>http://cakephp.hospedaxes.com/actualizar-el-contenido-de-un-select-con-ajax#comments</comments>
		<pubDate>Wed, 11 Jun 2008 07:44:11 +0000</pubDate>
		<dc:creator>bernal</dc:creator>
				<category><![CDATA[ajax]]></category>
		<category><![CDATA[cakephp-1.2]]></category>
		<category><![CDATA[actualizar selects]]></category>
		<category><![CDATA[cakephp]]></category>

		<guid isPermaLink="false">http://www.hospedaxes.com/blog-cakephp/?p=5</guid>
		<description><![CDATA[En esta entrada vamos a explicar como asociar dos selects mediante ajax y al modificar el elemento seleccionado en uno de ellos  cambie el contenido del otro.
Podemos ver el ejemplo de funcionamiento aquí.
Un ejemplo muy claro para esta situación sería dos selects, uno con provincias y el otro con localidades, lo que queremos es [...]]]></description>
			<content:encoded><![CDATA[<p>En esta entrada vamos a explicar como asociar dos selects mediante ajax y al modificar el elemento seleccionado en uno de ellos  cambie el contenido del otro.</p>
<p>Podemos ver el ejemplo de funcionamiento <a href="http://www.hospedaxes.com/blog-cakephp/pruebas" target="_blank">aquí.</a></p>
<p>Un ejemplo muy claro para esta situación sería dos selects, uno con provincias y el otro con localidades, lo que queremos es que al cambiar de provincia varíe la lista de localidades y muestre las que están en la provincia seleccionada.</p>
<p>Lo haremos utilizando el ajaxHelper, para que no sea necesario la recarga de la página y quede más atractivo.</p>
<p>Lo primero que haremos será definir los modelos de provincias ,localidades y un tercer modelo en el que usaremos los selects, por ejemplo podría ser un modelo de cliente, en el que al insertar un nuevo cliente tendríamos que elegir la provincia y localidad a la que pertenece.</p>
<h1><span style="text-decoration: underline;">Modelos</span></h1>
<p><strong>Modelo de provincia.</strong></p>
<pre class="prettyprint">/app/models/provincia.php

class Provincia extends AppModel
{
    var $name = 'Provincia';
}</pre>
<p><strong>Modelo de localidad.</strong></p>
<pre class="prettyprint">/app/models/localidade.php

class Localidade extends AppModel
{
    var $name = 'localidade';
}</pre>
<p><strong>Modelo de cliente.</strong></p>
<pre class="prettyprint">/app/models/cliente.php

class Cliente extends AppModel
{
    var $name = 'Cliente';
}</pre>
<h1><span style="text-decoration: underline;">Controladores</span></h1>
<p>Después de esto tendremos que definir los controladores.</p>
<p><strong>Controlador de localidad.</strong></p>
<pre class="prettyprint">/app/controllers/localidades_controller.php

class LocalidadesController extends AppController
{
	var $name = 'Localidades';
}</pre>
<p><strong>Controlador de provincia.</strong></p>
<pre class="prettyprint">/app/controllers/provincias_controller.php

class ProvinciasController extends AppController
{
	var $name = 'Provincias';
}</pre>
<p>Y por últino el controlador de clientes que será el que implementará la funcionalidad.</p>
<p><strong>Controlador de cliente.</strong></p>
<pre class="prettyprint">/app/controllers/clientes_controller.php

class ClientesController extends AppController
{
	var $name = 'Clientes';
	var $helpers = array('Ajax');
	var $uses = array('Cliente','Provincia','Localidade');

	function insertar()
	{
		$listadoProvincias = $this->Provincia->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC'));
		$this->set('provincias', Set::combine($listadoProvincias, "{n}.Provincia.id","{n}.Provincia.nombre"));
		$primera_provincia = $this->Provincia->find(null,null,'nombre ASC');
		$listadoLocalidades = $this->Localidade->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC','conditions'=>'Localidade.provincia_id='.$primera_provincia['Provincia']['id']));
		$this->set('localidades', Set::combine($listadoLocalidades, "{n}.Localidade.id","{n}.Localidade.nombre"));

		// RESTO DE LA FUNCIONALIDAD DE INSERCIÓN DE CLIENTES
	}

	function update_select()
	{
		if (!empty($this->data['Localidade']['provincia_id']))
		{
			$provincia_id = $this->data['Localidade']['provincia_id'];
			$localidades = $this->Localidade->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC','conditions'=>array('provincia_id'=>$provincia_id)));
		}
		else
		{
			$localidades = $this->Localidade->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC'));
		}
		$this->set('options', Set::combine($localidades, "{n}.Localidade.id","{n}.Localidade.nombre"));
		$this->render('/elements/update_select', 'ajax');
	}
}</pre>
<p>Por un lado tenemos la <strong>función insertar</strong>, que será una función genérica de inserción de clientes. La parte que a nosotros nos interesa es en la que se inicializan las variables que después utilizaremos en los selects, estas deberán ser arrays en los que cada elemento tenda un identificador y su valor, para que el select pueda utilizarlos en la vista.</p>
<p>En la versión 1.1 de cakephp, esto se podía hacer mediante la función generateList del modelo, función que se ha eliminado en la 1.2.<br />
Por ello ahora es necesario hacerlo en dos pasos, por un lado realizar la búsqueda con un findAll y después utilizar la función combine de la clase Set que genera un array con la estructura deseada, que será el que le pasemos a la vista.</p>
<pre class="prettyprint">$listadoProvincias = $this->Provincia->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC'));
$this->set('provincias', Set::combine($listadoProvincias, "{n}.Provincia.id","{n}.Provincia.nombre"));</pre>
<p>La segunda función <strong>update_select</strong>, es a la que llamará el ajax para actualizar el listado de localidades a partir de un identificador de provincia.</p>
<p>Como se puede ver en el código, la función coge el identificador de provincia del select y envía a la vista los arrays actualizados de provincias y localidades.</p>
<h1><span style="text-decoration: underline;">Vistas</span></h1>
<p>Localidades y provincias no tendrán vistas asociadas, ya que no hay ninguna operación en el controlador.</p>
<p>En clientes tendremos que crear la vista para la operación insertar del controlador, esta podría ser algo como esto:</p>
<pre class="prettyprint">/app/views/clientes/insertar.ctp

echo $form->create('Inscripcione',array('action'=>'insertar'));
echo $form->inputs(array('legend'=>'Actualizar Provincias',
		'Localidade.provincia_id' => array('label'=> 'Provincia','showEmpty'=>'false','id'=>'provincias'),
		'Alumno.localidade_id' => array('label'=> 'Localidad','showEmpty'=>'false','id'=>'localidades'),
			));
echo $form->end();

$options = array('url' => 'update_select','update' => 'localidades');
echo $ajax->observeField('provincias',$options);</pre>
<p>La vista será muy sencilla, un formulario con dos selects, uno de localidades y otro de provincias y una llamada al ajaxHelper en la que se indica que cada vez que se modifique el valor del select provincias, se llame a la función update_select y actualice el select de localidades.</p>
<p>Este select se actualizará con los valores devueltos por la vista de update_select, que lo único que hace es imprimir todos los nombres de localidades devueltos por la función del controlador.</p>
<pre class="prettyprint">/app/views/elements/update_select.ctp
if(!empty($options)) {
  foreach($options as $k => $v) {
    echo <code >"&lt;option value='$k'&gt;$v&lt;/option&gt;";</code>
  }
 }</pre>
<p>En este enlace se puede ver un ejemplo de <a href="http://www.hospedaxes.com/blog-cakephp/pruebas" target="_blank">funcionamiento</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://cakephp.hospedaxes.com/actualizar-el-contenido-de-un-select-con-ajax/feed</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
	</channel>
</rss>

