La web 2.0:
Retos y tecnologías para la Internet de nueva generación


Taller: "Programa una aplicación web 2.0 Ajax"


Parte 5. Modificando nuestro blog (II)



Del 21/07/2008 al 25/07/2008

Foro del taller:
http://estiu20.ning.com/forum/topic/show?id=2018352%3ATopic%3A1647





Imparten:
Sergio Gisbert Ribes
http://www.univerano.ua.es/es/curriculum.asp?id=2204

Ignacio Iborra Baeza
http://www.univerano.ua.es/es/curriculum.asp?id=2079

Universidad de Verano "Rafael Altamira"
http://www.univerano.ua.es/es/curso.asp?id=112

Universidad de Alicante
http://www.ua.es

Aplicación del taller.


1. Parte 1. Introducción


2. Enfrentándonos a Ajax sin ayudas

    1. El objeto XmlHttpRequest
    2. Controlarlo todo desde Javascript
    3. Ejemplo de uso: autocompletar

3. Parte 2: Primeros pasos con Prototype

    1. Qué es prototype
    2. Algunos aspectos básicos
    3. Despreocuparnos de la comunicación asíncrona: Ajax.Updater
    4. Ejemplo de uso: autocompletar con prototype

4. Parte 3: Primeros pasos con Script.aculo.us

    1. Qué es script.aculo.us
    2. Posibilidades que ofrece
    3. Ejemplo de uso: tienda de libros

5. Parte 4. Modificando nuestro blog

    1. Borrado de comentarios arrastrando con script.aculo.us
    2. Ordenación de comentarios

6. Parte 5. Modificando nuestro blog (II)

    1. Prototype en Ruby on Rails
    2. Mostrar un formulario sobre el listado de categorías
    3. Actualizar el listado de posts desde el formulario

7. Parte 6. La guinda final

    1. Efectos de animación con Script.aculo.us
    2. Formularios animados
    3. Menús animados

6. Parte 5. Modificando nuestro blog (II)


Prototype en Ruby on Rails

A pesar de que utilizar Prototype es tan sencillo a veces como incluir una sola línea de código para, a la vez, enviar una petición al servidor y actualizar una parte de nuestra página, Ruby on Rails ofrece una serie de helpers que nos ayudan a encapsular aún más las llamadas a Prototype. De esta forma podremos mostrar/ocultar formularios, enviar formularios de forma asíncrona, o actualizar partes de la página desde comandos de RoR.

Lo que vamos a hacer en esta parte es mostrar el formulario de inserción de comentarios al pinchar un enlace, y al rellenar el comentario actualizaremos de forma asíncrona (sin recargar la página) el listado de comentarios del post.


Mostrar un formulario sobre el listado de categorías

Lo primero que vamos a hacer es modificar el listado de categorías (parte administrador), para sacarlo desde una vista parcial (partial), y poderla reutilizar después. Para ello vamos al archivo /app/views/admin/categorias/index.html.erb, y sacamos la tabla de categorías:

<table class="admin">
  <tr class="impar">
    <th>Nombre</th>
    <th>Posts</th>
    <th colspan="2">Acciones</th>
  </tr>

  <% for categoria in @categorias %>
    <tr class="<%= cycle('', 'impar') %>">
      <td><%= link_to h(categoria.nombre), [:admin, categoria] %></td>
      <td class="centrado"><%=h categoria.posts.count %></td>
      <td class="centrado">
        <%= link_to 'Editar', edit_admin_categoria_path(categoria) %>
      </td>
      <td class="centrado">
        <%= link_to 'Eliminar', [:admin, categoria],
            :confirm => '¿Está seguro?', :method => :delete %>
      </td>
    </tr>
  <% end %>
</table>


a un archivo que llamaremos /app/views/admin/categorias/_alta_ajax.erb. En su lugar, en el archivo index.html.erb pondremos un div y una llamada para renderizar este nuevo partial.

<div id="tabla_categorias">
   <%= render :partial => "alta_ajax", :object => @categorias %>
</div>

Después vamos a cambiar, en el listado de categorías, el enlace de "Nueva categoría" por otro que, al pincharlo, nos saque un formulario para dar de alta la categoría en esa misma página. Para eso quitamos ese enlace de la página (tanto arriba como debajo del listado):

   <%= link_to 'Nueva categoria', new_admin_categoria_path %>

y añadimos en su lugar otro como éste (sólo debajo del listado de categorías):

   <p id="add_link"><%= link_to_function("Nueva Categoria",
   "Element.remove('add_link'); Element.show('add_subject')")%></p>
   <div id="add_subject" style="display:none;">
   </div>

Lo que hacemos es poner un enlace "Nueva Categoría" que, al pinchar sobre él, quitará el enlace y mostrará el contenido del div add_subject. Ahora lo que tenemos que hacer es poner el formulario de insertar categoría dentro de ese div, para mostrarlo sólo al pinchar el enlace.

    <div id="add_subject" style="display:none;">
        <%= render  :partial => "formulario",
                    :object => @categoria=Categoria.new,
                    :locals => {:cabecera=> "Nueva categoria",
                                :nombre_boton =>"Crear",
                                :modo => "",
                                :modo_form => "ajax" }
        %>
    </div>

Con lo que hemos hecho hasta ahora, la página funciona igual que antes, pero el formulario sólo se muestra cuando nosotros queremos. Ahora lo que vamos a hacer es que al enviar el formulario con la categoría sólo se actualice la lista de categorías, y no se vaya a otra página. Para eso, añadimos antes y después de renderizar el formulario (seguimos en /app/views/admin/categorias/index.html.erb) las siguientes líneas en negrita:

       <% form_remote_tag(    :url => {:action => 'create_ajax'},
              :update => "tabla_categorias",
              :html => {:id => 'subject_form'}) do %>

       <%= render  :partial => "formulario",
                    :object => @categoria=Categoria.new,
                    :locals => {:cabecera=> "Nueva categoria",
                                :nombre_boton =>"Crear",
                                :modo => "",
                                :modo_form => "ajax" }
       %>
       <%= submit_tag 'Crear AJAX' %>
       <% end %>

El comando form_remote_tag sirve para definir un formulario que va a llamar de forma remota a una acción (en este caso una acción llamada create_ajax que crearemos ahora). A este formulario le pasamos un atributo update con el id del objeto que vamos a actualizar (la tabla de categorías).

Al formulario de categoría le pasamos un nuevo parámetro modo_form = ajax, para que omita el botón de enviar en este caso. Esto lo hacemos porque le pasamos un botón de envío especial después, con el comando submit_tag, y si no quitamos el botón del formulario habría dos botones de envío.

Lo siguiente que vamos a hacer es modificar el formulario de inserción de categoría para que omita el botón de enviar el formulario en caso de recibir el parámetro modo_form = ajax. Para ello editamos el archivo /app/views/admin/categorias/_formulario.html.erb, y añadimos estas líneas en negrita:

     <% if not modo_form == "ajax" %>
     <p>
       <%= f.submit nombre_boton %>
     </p>
     <% end %>
 
     ...

     <% if not modo_form == "ajax" %>

       <% if modo == 'edicion' %>
         <%= link_to 'Mostrar', [:admin, @categoria] %> |
       <% end %>
       <%= link_to 'Volver', admin_categorias_path %>
     <% end %>

Lo que nos queda por hacer es definir la nueva acción create_ajax, en el controlador de categorías /app/controllers/admin/categorias_controller.rb (justo debajo de la acción create):

  # POST /categorias
  # POST /categorias.xml
  def create_ajax

    @categoria = Categoria.new(params[:categoria])

    if @categoria.save
        @categorias = Categoria.find(:all)
        flash[:notice] = 'Categoria was successfully created.'
        render :partial => "alta_ajax", :object => @categorias
    end
 
  end

Ya podemos probar nuestro nuevo gestor de categorías.