martes, 25 de enero de 2011

ASP.NET MVC3: Razor Templates

Muy buenas!

En este post quiero comentaros una característica de Razor que yo considero que es una auténtica pasada: los templates.

Básicamente el meollo de todo está en la posibilidad de guardar el resultado de un parseo de Razor en un Func<T, HelperResult> siendo T el tipo del modelo que renderiza el template.

Veámoslo con código:

@{
Func<string, HelperResult> h =
@<h2>Esto es un template al que se le han pasado los datos: @item</h2>
;
}
<p>
Renderizamos el template: @h("datos")
</p>





Fijaos como nos guardamos en una Func<string, HelperResult> el resultado de renderizar un template razor (en este caso el template <h2>…</h2>). Fijaos en tres detalles:




  1. Dado que la variable h está declarada como Func<string, HelperResult> el tipo del modelo en este template es “string”


  2. Para acceder al modelo que se pasa al template se usa @item


  3. Al final del template Razor ponemos un ; (eso es una declaración C# y como tal debe terminar en punto y coma).



Luego más adelante renderizamos el template, con el código: @h("datos")



Eh!! Eso no es lo mismo que @helper?



Si conoces @helper te puede parecer que esto no es muy novedoso. Con @helper podemos crear helpers inline de la siguiente manera:




@helper h2(string s) {<h2>Esto es un helper: @s</h2>}





Y lo podíamos invocar con:




@h2("ufo")





Por lo que parece que viene a ser lo mismo. Y es que, en el fondo, ambas construcciones devuelven un HelperResult.




Nota: Si quieres más información sobre @helper, léete el post que hizo el maestro hace algún tiempecillo: http://www.variablenotfound.com/2010/11/y-mas-sobre-helpers-en-razor.html




Lo interesante no es que ambas construccione se parezcan, lo que quiero recalcar es que…



… Los templates son Func<T, HelperResult>!



Lo pongo así en negrita porque eso es importante, y a la vez me sirve de título. Si los templates Razor son Func<T, HelperResult>… cualquier método que reciba un Fun<T, HelperResult> puede recibir un template Razor



… Incluídos los helpers!




@helper Repeater(int count,Func<dynamic, HelperResult> template, string data) {
<ul>
@for (int idx=0; idx<count; idx++)
{
<li>@template(new { Text = data, Index = idx })</li>
}
</ul>
}

@Repeater(10, @<span>@item.Text (item: #@item.Index)</span>, "Ufo")





En este código:




  1. Declaramos un helper, llamado Repeater que acepta tres parámetros:

    1. Un entero


    2. Un Func<dynamic, HelperResult> que por lo tanto podrá ser un template Razor


    3. Una cadena




  2. El helper se limita a crear una lista y luego:

    1. Crea tantos <li> como indica el paràmetro count y en cada id

      1. Evalúa el segundo parámetro (que es el Func) y le pasa como parámetro un objeto anonimo con dos propiedades (Text e Index), donde Text es el tercer parámetro que recibe (y index el valor de la iteración actual).






  3. Cuando invocamos al helper, le pasamos como primer parámetro el número de repeticiones, como segundo parámetro un template de Razor. Fijaos que dentro de dicho template:


    1. Accedemos a las propiedades @item.Text y @item.Index. Eso podemos hacerlo porque hemos declarado el tipo del modelo de dicho template como dynamic y por eso nos compila (y nos funciona porque el helper cuando invoca el template crea esas propiedades en el objeto anónimo).





El código HTML generado por dicha llamada al helper Repeater es:




<ul>
<li> <span>Ufo (item: #0)</span></li>
<li> <span>Ufo (item: #1)</span></li>
<li> <span>Ufo (item: #2)</span></li>
<li> <span>Ufo (item: #3)</span></li>
<li> <span>Ufo (item: #4)</span></li>
<li> <span>Ufo (item: #5)</span></li>
<li> <span>Ufo (item: #6)</span></li>
<li> <span>Ufo (item: #7)</span></li>
<li> <span>Ufo (item: #8)</span></li>
<li> <span>Ufo (item: #9)</span></li>
</ul>





Espero que el post os haya resultado interesante!!! ;-)



Saludos!



PD: Como siempre… otro crosspost desde mi blog en geeks.ms!

No hay comentarios: