Aplicar un theme, plantilla o template a formularios en Drupal 6
Supongamos que tenemos un formulario que creamos para que se vea en la URL
http://www.ejemplo.com/themed_form
El formulario definido en el modulo tendría una pinta como la siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
< ?php function formulario(){ $form['nombre'] = array( '#title' => t('Nombre'), '#type' => 'textfield', ); $form['apellido'] = array( '#title' => t('Apellido'), '#type' => 'textfield', ); $form['mail'] = array( '#title' => t('e-mail'), '#type' => 'textfield', ); $form['telefono'] = array( '#title' => t('Teléfono'), '#type' => 'textfield', ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Enviar'), ); return $form; } |
Y el hook_menu tendría una pinta como esta:
1 2 3 4 5 6 7 |
< ?php function theme_form_sample_menu(){ $items['themed_form'] = array( 'title' => 'Muestra de themado de un formulario', 'page callback' => 'render_formulario', 'access arguments' => array(true), 'type' => MENU_CALLBACK, ); return $items; } |
Y la función para aplicar sobre la url seria:
1 2 3 4 5 6 7 8 9 |
< ?php function render_formulario(){ //podemos agregar nuestros extras. drupal_add_js(drupal_get_path('module', 'theme_form_sample') .'/js/ejemplo.js'); drupal_add_css(drupal_get_path('module', 'theme_form_sample') .'/css/ejemplo.css'); //ya podemos generar el formulario. return drupal_get_form("formulario"); } |
El formulario se va a dibujar correctamente y lo podemos maquetar con CSS si queremos, pero, y si además de los elementos del formulario tenemos que meterle mas HTML ¿que hacemos?.
¿Modificamos la función que define al formulario metiéndole markups por todos lados?. Pues no.
¿Entonces cual es la forma en la que los formularios en drupal 6 se maquetan?:
Fácil. Agregas una linea mas en la definición del formulario como esta:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<!--?php $form['#theme'] = "theme_para_formulario";</pre> <p>La podes poner al principio o justo al final antes del return para mayor comodidad.</p> <p>Ahora bien, esto no es todo (<span style="color: #ff6600;">si la vida fuera tan simple...), además nos hace falta definir el <strong>hook_theme():</strong></p> <pre class="lang:php decode:1 " > < ?php function theme_form_sample_theme() { return array( 'theme_para_formulario' => array( 'template' => 'formulario', 'arguments' => array('form' => NULL), ), ); } </pre> <p><strong>(Noten que en el argumento paso una variable llamada "form")</strong></p> <p>Ahora <strong>creamos la plantilla <span style="color: #ff6600;">“formulario.tpl.php”</span></strong> y agregamos el siguiente código:</p> <pre class="lang:php decode:1 " >< ?php echo drupal_render($form);</pre> <p>Guardarlo, limpia la cache y probalo.</p> <p>Podes ver que el formulario ahí está, se dibuja, pero claro, seguís sin poder manosear sus elementos por separado. Solucionemos eso o mi post va a dejar de tener sentido:</p> <p>Cambiemos el anterior código de la plantilla (<span style="color: #ff6600;">echo drupal_render($form);) por este otro:</p> <pre class="lang:php decode:1 " > < ?php echo drupal_render($form["apellido"]); ?-->; < ?php echo drupal_render($form["mail"]); ?>; < ?php echo drupal_render($form["telefono"]); ?>; < ?php echo drupal_render($form["nombre"]); ?>; |
Como se puede ver, lo que estoy haciendo es renderizar uno a uno los elementos del formulario.
En el ejemplo anterior recordaras que hicimos algo así como “drupal_render($form)”. Bueno lo que pasa allí básicamente es que toma el array que definiste en la función y lo convierte en HTML, Y como nosotros queremos poder renderizar las partes del formulario por separado la teoría dice que si en lugar de mandar el array entero, mandamos un pedasito, debería funcionar, y es justamente lo que ha pasado en el segundo ejemplo.
pero falta algo acá.. el resto del formulario. Sin ir mas lejos falta el botón de envío, los token, el form_id (lo pueden ver el el código fuente de la pagina renderizada).
Eso pasa porque nosotros ya podemos controlar cuales elementos vamos a mandar a renderizar por separado, pero no le hemos dicho que hacer con el resto. Solucionemos esto agregando esta linea al justo debajo de las anteriores:
1 |
< ?php echo drupal_render($form); ?> |
Guardar, probar, Alegrarse.
Ahora solo nos queda aprovechar que estamos parados en una plantilla y agregar el HTML que nos haga falta para poder darle la forma que queramos:
[htmlphp]
< ?php echo drupal_render($form[“apellido”]); ?>
< ?php echo drupal_render($form[“mail”]); ?>
< ?php echo drupal_render($form[“nombre”]); ?>
< ?php echo drupal_render($form); ?>
[/htmlphp]
Para rematar el asunto, hice un modulito de ejemplo que podes descargar activar y probar en la url http://tuservidor.de.desarrollo.com/themed_form
Bueno espero que les sirva. Bye.
Gracias por el artículo, sencillo y útil. Añadiría un apunte, y es que dentro del theme se puede acceder también a la información que podamos haber guardado en $form_state[‘storage’], especialmente útil en formularios multipágina. Para ello, dentro de la plantilla accederemos a $form[‘#parameters’][1][‘storage’], y ¡ahí lo tenemos!
Muy bueno el articulo…..el detalle que me falto ver es, como el el codigo para guardar ese FORM dentro de una Base de datos…..Ojala me puedan ayudar.
gracias.
Muy bueno, me gusta y era lo que necesitaba, lo voy a aplicar a ver que tal, y te aviso.
Nota: me gusta el boton que dice: “Mira mama soy un boton” jajaja. 🙂
Excelente todo me funciono muy bien, gracias por el post. 🙂
Me alegro mucho XD
Te felicito. Ya me funcionó. Pero no logré un campo fieldset por ejemplo Busqueda (Libros) para un archivo template php con css. Dentro de la campo fieldset contiene el campo de texto para palabra clave, el campo de selección de opción y el botón Buscar. Ahora no me funcionó. Ayúdeme.
te ayudaría encantado, pero no entendí nada :S
Explicame un poco mas en detalle si puede ser.
Muy buen post, de los mejores que he leido, pero tengo una pregunta:
¿Como hago para que este formulario sea visto por todos los usuarios?
Ya que solo puedo verlo con el usuario admin, con el usuario anonimo no lo veo y solo sale el mensaje
“Acceso denegado
Usted no está autorizado para visitar esta página. ”
Estaré atento a mi correo!!!
De antemano muchas gracias!!!
con poner en la definición del menú el ‘access arguments’ => array(true), deberia hacer que sea visible para todo el mundo. ¿lo pusiste asi y no te funciona?