#234 SimpleForm
- Download:
- source codeProject Files in Zip (108 KB)
- mp4Full Size H.264 Video (14.9 MB)
- m4vSmaller H.264 Video (9.32 MB)
- webmFull Size VP8 Video (22.4 MB)
- ogvFull Size Theora Video (20.5 MB)
Hace algunos meses dedicamos un par de episodios a la gema Formstastic [ver, leer], que ofrece una forma muy cómoda de generar el código de las vistas de formularios en Rails. En este episodio veremos una gema alternativa llamada SimpleForm. Al igual que Formtastic, SimpleForm hace que sea más fácil generar el código de las vistas (en comparación con el código estándar de Rails) Los métodos de SimpleForm son muy parecidos a los de Formtastic, por lo que nos resultarán familiares si ya hemos trabajado con esta gema.
Por supuesto, la clave aquí es: si las dos gemas son tan parecidas, ¿por qué usar SimpleForm en lugar de Formtastic? La primera razón es que SimpleForm es más ligera. No trae una hoja de estilos por defecto, sino que se centra en generar el marcado HTML. También es más personalizable y extensible que Formtastic. Si ya conocemos Formtastic y nos parece que a veces se hace notar demasiado, obligándonos a usar un marcado concreto, tal vez nos merezca la pena usar SimpleForm.
Cómo integrar SimpleForm en una aplicación
Como demostración de SimpleForm vamos a modificar un formulario escrito con el código de vista estándar de Rails para que utilice SimpleForm. Se trata de una aplicación sencilla de comercio electrónico que muestra varios productos, cada uno de los cuales pertenece a una categoría. El formulario que vamos a modificar es el de creación de un nuevo producto. Este formulario tiene campos de varios tipos diferentes por lo que será un buen ejemplo.
Para usar SimpleForm tan sólo tenemos que añadir la gema al Gemfile
de la aplicación.
gem "simple_form"
Y para asegurarnos de que está instalada:
$ bundle install
Con la gema ya instalada tenemos que ejecutar un generador que añadirá algunos archivos necesarios para el funcionamiento de SimpleForm
$ rails g simple_form:install <span class="passed">create</span> config/initializers/simple_form.rb <span class="passed">create</span> config/locales/simple_form.en.yml <span class="passed">create</span> lib/templates/erb/scaffold/_form.html.erb
Estos archivos generados se utilizan sobre todo para personalizar el comportamiento de SimpleForm. Antes de verlos actualizaremos el código de la vista del formulario, que ahora mismo tiene este aspecto:
<%= form_for @product do |f| %> <%= f.error_messages %> <p> <%= f.label :name %> <%= f.text_field :name %> </p> <p> <%= f.label :price %> <%= f.text_field :price %> </p> <p> <%= f.label :released_on %> <%= f.date_select :released_on %> </p> <p> <%= f.label :category_id %> <%= f.collection_select :category_id, Category.all, :id, :name %> </p> <p> <%= f.label :rating %> <%= f.select :rating, 1..5 %> </p> <p> <%= f.label :discontinued %> <%= f.check_box :discontinued %> </p> <p><%= f.submit %></p> <% end %>
Los cambios principales que hemos de hacer en el formulario consisten en cambiar form_for
por simple_form_for
y cambiar cada par de elementos input
y su etiqueta por uno de los métodos de SimpleForm:
<%= simple_form_for @product do |f| %> <%= f.error_messages %> <%= f.input :name %> <%= f.input :price %> <%= f.input :released_on %> <%= f.association :category %> <%= f.input :rating %> <%= f.input :discontinued %> <%= f.button :submit %> <% end %>
Bastará con usar f.input
para la mayoría de los controles del formulario pero para el campo category
tenemos que usar un método difernte. En el formulario original este campo utilizaba collection_select
para mostrar un menú desplegable que contenía todas las categorías.
<%= f.collection_select :category_id, Category.all, :id, :name %>
Con SimpleForm podemos usar f.association
con el mismo resultado. Ya podemos recargar la página para ver cómo la muestra SimpleForm.
El formulario tiene un aspecto diferente porque ya no tiene aplicados los estilos anteriores, pero podemos modificar fácilmente la hoja de estilos para añadir estilos conforme a los nombres de clases que utiliza SimpleForm en los formularios.
.simple_form label { float: left; width: 100px; text-align: right; margin: 2px 10px; } .simple_form div.input { margin-bottom: 10px; } .simple_form div.boolean, .simple_form input[type='submit'] { margin-left: 120px; } .simple_form div.boolean label { float: none; margin: 0; }
En nuestras aplicaciones con SimpleForm tendremos que personalizar estos estilos para adaptarlos al aspecto general pero a nosotros nos bastará con la CSS anterior para hacernos con una idea de los nombres de clases utilizados en los elementos HTML generados por SimpleForm. Con los estilos anteriores, el formulario presenta ahora mejor aspecto.
Personalización de los campos
SimpleForm ha deducido en aquellos campos en los que hemos usado f.input
el tipo exacto de columna, por lo que “Released on” se muestra como una columna de fecha y “Discontinued” se muestra como un checkbox dado que representa un valor booleano. Al ser una asociación, el campo “Category” se muestra como un menú desplegable con una opción vacía. El funcionamiento de estos campos se puede modificar añadiendo opciones. Por ejemplo, si queremos eliminar la opción vacía de “Category” podemos añadir la opción :include_blank
.
<%= f.association :category, :include_blank => false %>
El formulario original tenía una lista desplegable para el campo de valoración que ha sido reemplazada por un campo de texto. Podemos recuperar de nuevo el menú desplegable pasándole un rango a la opción :collection
.
<%= f.input :rating, :collection => 1..5 %>
Si quremos que la lista se muestre como botones de radio, podemos usar la opcion :as
.
<%= f.input :rating, :collection => 1..5, :as => :radio %>
Si ahora recargamos el fomulario veremos que ha desaparecido la opción vacía del desplegable de categoría y que los campos de valoración se muestran como botones de radio.
Otra gran funcionalidad de SimpleForm es la detección automática de los campos requeridos. Podemos demostrarlo haciendo que los campos de nombre y precio sea obligatorios:
class Product < ActiveRecord::Base attr_accessible :name, :price, :released_on, :category_id, :rating, :discontinued belongs_to :category validates_presence_of :name, :price end
Esto es todo lo que hay que hacer. Si recargamos el formulario veremos que estos campos ahora aparecen marcados con asterisco y si intentamos enviar el formulario sin rellenar dichos campos veremos cómo se muestran sendos mensajes de error:
Podemos añadir fácilmente un mensaje para dar una pista en cada campo. Digamos que queremos sugerir que los precios se deberían introducir en libras esterlinas. Sólo tenemos que añadir la opción :hint
en cada formulario.
<%= f.input :price, :hint => "prices should be in UKP." %>
Con esto aparecerá la siguiente pista después del campo en el formulario:
En la documentación README de SimpleForm están documentadas las opciones que se pueden pasar en estos campos. Merece la pena mirar también la documentación de Formtastic porque muchas de esas opciones también sirven con SimpleForm.
Personalización de SimpleForm
Cuando antes ejecutamos el generador de SimpleForm, vimos que éste generó tres archivos:
$ rails g simple_form:install <span class="passed">create</span> config/initializers/simple_form.rb <span class="passed">create</span> config/locales/simple_form.en.yml <span class="passed">create</span> lib/templates/erb/scaffold/_form.html.erb
Si queremos personalizar el funcionamiento de SimpleForm en toda la aplicación podemos modificar uno o varios de estos archivos. El primer fichero contiene varias opciones de configuración comentadas, donde podemos cambiar muchas cosas. Por ejemplo, podemos modificar el orden en que se muestran los componentes de los campos; podemos cambiar la etiqueta que rodea los campos de cada formulario y podemos cambiar el tamaño de fuente por defecto en los campos de texto. Como queremos que los campos de texto en nuestra aplicación sean más estrechos podemos cambiar el valor por defecto de 50
a 30
.
# Use this setup block to configure all options available in SimpleForm. SimpleForm.setup do |config| # Other options removed... # Default size for text inputs. config.default_input_size = 30 end
El siguiente fichero es el de localización, que es donde podemos modificar el idioma de los formularios.
en: simple_form: "yes": 'Yes' "no": 'No' required: text: 'required' mark: '*' # You can uncomment the line below if you need to overwrite the whole required html. # When using html, text and mark won't be used. # html: '<abbr title="required">*</abbr>' error_notification: default_message: "Some errors were found, please take a look:" # Labels and hints examples # labels: # password: 'Password' # user: # new: # email: 'E-mail para efetuar o sign in.' # edit: # email: 'E-mail.' # hints: # username: 'User name to sign in.' # password: 'No special characters, please.'
Este archivo nos resultará útil aunque la aplicación no tenga que aparecer en idiomas diferentes porque aquí se pueden modificar algunas de las opciones de SimpleForm como el texto que se muestra después de cada campo obligatorio.
El útlimo archivo genera el parcial de formulario para el generador de andamiajes.
<%%= simple_form_for(@<%= singular_name %>) do |f| %> <%% if @<%= singular_name %>.errors.any? %> <div id="error_explanation"> <h2><%%= pluralize(@<%= singular_name %>.errors.count, "error") %> prohibited this <%= singular_name %> from being saved:</h2> <ul> <%% @<%= singular_name %>.errors.full_messages.each do |msg| %> <li><%%= msg %></li> <%% end %> </ul> </div> <%% end %> <div class="inputs"> <%- attributes.each do |attribute| -%> <%%= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> %> <%- end -%> </div> <div class="actions"> <%%= f.button :submit %> </div> <%% end %>
En Rails 3 se puede puentear cualquier fichero de plantillas usado por un generador añadiéndolo a nuestra aplicación por lo que si queremos personalizar la forma en que funciona un generador podemos simplemente crear una nueva plantilla. Esto es lo que ha hecho para nosotros el generador de SimpleForm.
Eso es todo por este episodio: con SimpleForm es más fácil crear formularios en nuestras aplicaciones Rails.