Servicio de Informática | Universidad de Alicante ASP.NET MVC 4 ELEMENTOS GRÁFICOS Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es/ ÚLTIMA ACTUALIZACIÓN: 17 DE OCTUBRE DE 2013 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS GUÍA DE ESTILO Con el objetivo de conseguir un diseño de aplicaciones común, se ha preparado una guía de estilo con los elementos básicos para el desarrollo de aplicaciones. Actualmente sólo está disponible en nuestras máquinas de desarrollo y lo podemos encontrar en nuestra carpeta compartida del aula. El ejemplo de un listado con su gestión lo podemos ver en la imagen siguiente La guía dispone de documentación de los elementos gráficos más comunes; avisos, botones, calendarios, listados, etc. Con el desarrollo de nuevas aplicaciones en este entorno se irán incorporando nuevas funcionalidades o elementos. SEGUIDAD Se han incorporado ejemplos de identificación con LDAP y en breve como integrarlo con el Sistema de Identifiación Único (CAS). Se apoya en las librerías desarrolladas en el Servicio de Informática. No sólo permite identificarse sino que permite personalizar a dónde puede acceder ese usuario o el rol al que pertenece. Igualmente se ha implementado un sistema para obligar a la identificación en entornos SSL. Hasta el momento se dejaba al programador esta tarea, que en muchas ocasiones se nos olvidaba o no le dábamos poca importancia. Ahora está completamente integrado con lo que su uso se hace obligatorio a la hora de identificarse. Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 2 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS DISEÑO SENSIBLE Cada vez es más frecuente encontrar Webs que se adaptan al dispositivo que se conectan sin tener que crear plantillas diferentes para cada uno, a eso se le llama diseño sensible (responsive design). Nuestra plantilla se ve correctamente en un navegador de escritorio Como en un móvil Cada vez es más frecuente el acceso a nuestra web desde dispositivos móviles o tabletas. Permitir el acceso y uso de nuestras aplicaciones desde estos dispositivos las hacen más atractivas. Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 3 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS RAZOR EN DETALLE MODELO En la mayoría de los casos la vista trabaja con los datos de un modelo. Por eso nos podemos encontrar con dos casos, que le enviemos un único registro (por ejemplo para operaciones de creación o edición) o con un conjunto de datos (por ejemplo listados). Modelo con un único registro Por ejemplo para ver los detalles de un libro. Incluiremos @model RutaModelo al principio de la vista. @model MvcAnuncio3.Models.CSI_CATEGORIA Luego para usarlo dentro del código haremos referencia directamente al objeto model @Html.EditorFor(model => model.NOMBRE_ES) Modelo con un conjunto de datos Por ejemplo para ver el listado de libros. Incluiremos @model IEnumerable <RutaModelo> al principio de la vista. @model IEnumerable<MvcAnuncio3.Models.CSI_CATEGORIA> Luego para usarlo, por ejemplo en un bucle @foreach (var item in Model) { .. @Html.DisplayFor(modelItem => item.NOMBRE_ES) .. } Layout Es el equivalente a las MasterPages en WebPages, es decir la plantilla común para todas las páginas de nuestro sitio. Por defecto al crear un proyecto MVC nos crea en la carpeta Views > Shared el fichero _Layout.cshtml. Esta página es la plantilla que usará el asistente de las vistas cuando no seleccionamos ninguna. Se puede seleccionar cualquier otra en el momento que creamos la vista Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 4 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS o accediendo al código de la vista generado y añadido la línea Layout = “Fichero con la plantilla para la vista” @{ Layout = "~/Views/Shared/_Layout.cshtml"; } @RenderBody() Se utiliza en _layout.cshtml para indicar que en ese punto se incluirá el código generado por la vista. Todos los layouts deben incluirla. En caso de no hacerlo obtendremos el siguiente mensaje de error. Error de servidor en la aplicación '/'. No se ha llamado al método "RenderBody" para la página de diseño "~/Views/Shared/_layout.cshtml". Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 5 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS @section Definimos una sección de código Razor / HTML que se insertará en el layout en caso de que se llame a @rendersection con el nombre de la sección que hayamos declarado. @section NombreSección { … } Si queremos definir una sección cabecera, en cada vista la definiríamos del siguiente modo. @section cabecera { <h1>Ejemplo de sección</h1> } @RenderSection Incluimos en nuestra plantilla secciones o bloques de código Razor / HTML que se ha definido en la vista. Podemos indicar además si es obligatorio o no definirla. @RenderSection("NombreSección ", required: false / true) Por defecto toma el valor true, con lo que en caso de que no la incluyamos en nuestra vista, dará un mensaje de error. Sección no definida: "cabecera". Descripción: Excepción no controlada al ejecutar la solicitud Web actual. Revise el seguimiento de la pila para obtener más información acerca del error y dónde se originó en el código. @RenderSection("cabecera", required:false) IsSectionDefined Por último para controlar si se ha definido la sección, disponemos de la función IsSectionDefined(). Siguiendo con el ejemplo de la cabecera podríamos comprobar si se ha definido para darle un formato y sino le damos otro formato. @if (IsSectionDefined("cabecera")) { <div id="title"> @RenderSection("cabecera") </div> } else { <div id="titledefalt"><h1 class="generico">Título genérico</h1></div> } Etiquetas avanzadas @() En caso de que una variable, dentro del código, pueda provocar confusión, podemos usar @(variable). Por ejemplo Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 6 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS <img src="images/"@model.foto.jpg" /> No podríamos afimar si está llamando a @model.foto y luego incorpora la extensión .jpg o que interprete que .jpg es una propiedad de @model.foto. Deberíamos utilizar <img src="images/"@(model.foto).jpg" /> Para evitar este conflicto. @: Aunque ya lo vimos ayer, lo vuelvo a remarcar. Aquel texto HTML que no incluya etiquetas puede provocar que se interprete como código Razor. <span> @if(true){ La hora es: @DateTime.Now } else { Aquí no se debería acceder nunca } </span> No sabe si es código HTML o código C#. Para definírselo anteponemos @: (si sólo es una línea) para decirle que es HTML <span> @if(true){ @:La hora es: @DateTime.Now } else { @:Aquí no se debería acceder nunca } </span> Es equivalente a incluir el texto entre las etiquetas <text></text> Html.Raw Escribe el contenido que le pasemos sin codificar (que es lo que hace por defecto ASP.NET MVC 3). Puede que en ocasiones necesitemos que sea así (por ejemplo porque incluye etiquetas de formato), aunque debemos tener mucho cuidado con el contendido para que no nos produzcan XSS Injection. <h2>@Html.Raw(ViewBag.Message)</h2> Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 7 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS Partial Views Como conocemos las vistas hasta ahora genera una página web en cada llamada. Con un layout por defecto o personalizado, pasando por el código generado por la vista y terminando con secciones opcionales o no. Esto no lo hace muy complicado de mantener y sobre todo poco flexible. Por eso existen las vistas parciales que permiten dividir la página en bloques más pequeños lo que las hace más fácil de gestionar. Puede ser muy útil en llamada AJAX porque el código generado es el que le indiquemos en la vista parcial sin elementos como layout que se supone que se ha llamada anteriormente desde una vista. Con un ejemplo lo vamos a ver muy claro. Queremos hacer la suma de dos números es un método del controlador Home. Pasamos dos parámetros y cambiamos return View(); por return PartialView(); public ActionResult Suma(int numero1, int numero2) { ViewBag.Suma = numero1 + numero2; return PartialView(); } Ahora creamos la vista y la marcamos como parcial Escribimos el resultado en la vista vacía (que no tiene ni model, ni layout) @ViewBag.Suma ¿Cómo la llamamos? Lo normal es hacerlo como hasta ahora http://servidor/home/suma?numero1=5&numero2=7 Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 8 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS pero como es lógico el propósito no era éste. Nosotros queremos incluirlo dentro de otra vista y lo vamos a hacer con AJAX, es decir se cargará una vista inicial y ante un evento modificaremos el contenido de algún elemento de la vista inicial con el contenido de la vista parcial. Incluimos el siguiente código en algún método de home La suma de 5 y 7 es: <span id="operacion"></span> <script type="text/javascript"> $(function(){ $("#operacion").load("/home/Suma?numero1=5&numero2=7"); }); </script> La primera línea pone un texto y prepara una etiqueta donde luego mostrar el resultado. Las siguientes líneas son javascript y JQuery. Esta librería está muy integrada en Visual Studio con lo que debemos aprovechar que la disponemos. Lo que hace es llamar a nuestro controlador con load y poner el resultado en aquella etiqueta que tenga como id operacion ($(“#idetiqueta”)). Visualmente vemos el resultado de la operación, pero internamente ha hecho una segunda llamada para obtener el resultado de la suma y luego ha modificado el contenido de la etiqueta. No es obligatorio llamarlo desde javascript y con AJAX, podemos llamarlo desde nuestras propias vistas. El ejemplo de ayer que mostrábamos un listado de alumnos. Usamos el siguiente código <p>Listado de alumnos</p> <ul> @foreach (var item in Model) { <li>@item.Nombre @item.Apellidos</li> } </ul> Si el formato de la ficha del alumno fuera muy amplia, sería una buena solución convertirla en una vista parcial y llamarla desde nuestra propia vista <p>Listado de libros (Vistas parciales)</p> @foreach (var item in Model) { @RenderPage("~/Views/Home/Formato.cshtml", new {alumno = item}); } Para recoger los parámetros tenemos que usar el objeto Page y como propiedad lo que hayamos pasado, en este caso libro y trabaríamos con las propiedades de éste como si fuera el modelo. @{ var Model = Page.alumno; } <div> <strong>Nombre: </strong> @Model.Nombre </div> <div style="margin-bottom: 20px;"> <strong>Apellidos: </strong> @Model.Apellidos </div> Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 9 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS En este segundo caso no se hace una llamada por cada libro, ya que se hace internamente antes de devolver la página completa. HELPERS Los Helpers podríamos entenderlo como una forma de facilitar de reutilizar código que escribimos en muchas ocasiones. MVC nos ofrece de dos tipos: HTMLHelpers orientados a escribir código HTML. La mayoría de métodos que nos ofrece son para trabajar con formularios, simplificando y unificando enormemente este proceso. URLHelpers orientada a simplificar el trabajo con direcciones y conversiones de caracteres. En el día de hoy nos centraremos en los segundos porque son muy pocos y los necesitamos para poder crear nuestro primer layout / plantilla. URLHelper Para poder usar este Helper dentro del motor Razor antepondremos @Url al método que queramos llamar. Por ejemplo si queremos poner la ruta de nuestro fichero css, en el layout por defecto hace uso del método Content de URLHelper. <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" /> La integración es muy sencilla porque no debemos hacer ninguna referencia externa y dispone de intellisense lo que facilita su escritura. Los 4 métodos que lo forman son Action(s:action, s:controller, …) Genera la dirección completa de la llamada a un método / acción de un controlador. Por ejemplo si queremos crear un enlace a Acerca de, podríamos usar el siguiente código HTML <a href="@Url.Action("About", "Home")">Acerca de</a> Si queremos hacer una llamada a un método Buscar al que le pasemos el término de búsqueda, incluiríamos un tercer campo, con los parámetros que queramos personalizar. <a href="@Url.Action("Buscar", "Home", new { busqueda = "Servicio de Informática" })">Buscar por "Servicio de Informática"</a> Si el método permite la recepción del parámetro “busqueda”, entonces lo podríamos usar. public ActionResult Buscar(string busqueda) { ViewBag.Search = busqueda; return View(); } Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 10 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS Content(s:path) Convierte una dirección virtual / relativa en su correspondiente dirección absoluta de la aplicación. Es muy útil cuando hacemos referencia a ficheros como hojas de estilo o javascript <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" /> Encode(s:url) Codifica los caracteres especiales de una URL por sus equivalentes caracteres estándar. Se usa para evitar problemas con ciertos navegadores que no interpretan los caracteres especiales. En el ejemplo anterior el envío de “Servicio de Informática” sería uno de los casos que nos podrían dar errores por os espacios y acento. <a href="@Url.Action("Buscar", "Home", new { busqueda = Url.Encode("Servicio de Informática") })">Buscar por "Servicio de Informática"</a> La dirección que nos genera es http://servidor/Home/Buscar?busqueda=Servicio%2Bde%2BInform%25c3%25a1tica RouteUrl(s:route) Muy parecido al primero pero todo en uno, es decir pasamos los parámetros que queramos en un único parámetro, de la siguiente manera new { Controller = “…”, Action = “…”, …} La misma llamada Acerca de pero con RouteUrl sería. <a href="@Url.RouteUrl(new {Controller = "Home", Action = "About"})">Acerca de</a> Si queremos pasar también el campo de búsqueda (o el id) <a href="@Url.RouteUrl(new {Controller = "Home", Action = "Buscar", Informática" })">Buscar por "Servicio de Informática"</a> busqueda = "Servicio de Mañana nos centraremos en los HTMLHelpers y veremos como crear los nuestros propios. HTMLHelpers Ayer vimos las funciones relacionadas con las direcciones. Hoy nos centramos en las que realmente nos van a ayudar en el trabajo diario, las que nos generan código HTML. Aunque el listado es mucho más amplio que el de URLHelpers, lo cierto es que todos son muy parecidos. Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 11 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS Vamos a comenzar con el elemento básico que es el formulario que recoge todos los campos con los que trabajamos. Nos creamos una método / acción en nuestro controlador para ir jugando. Le podemos llamar helpers. No le vamos a pasar ningún modelo por el momento. Editamos su vista y lo básico para un formulario en HTML es <form …></form>. La idea es que no lo escribamos directamente sino que usemos los helpers. BeginForm(s:action, s:controller, o:values) Si escribimos @using (Html.BeginForm()) { } Nos generaría el siguiente código <form action="/Home/helpers" method="post"></form> Por defecto nos genera una acción a nosotros mismos y hace la llamada con método post Con los parámetros podemos indicar que controlador / acción del action y el método Html.BeginForm("Create", "Alumno", FormMethod.Get) Y generaría <form action="/Alumno/Create" method="get"></form> Todos los HTMLHelpers incluyen un último parámetro abierto a añadir cualquier atributo HTML, por ejemplo id, class, etc. En el caso de que queramos indicar el id Html.BeginForm("Create", "Alumno", FormMethod.Get, new {id="fTest"})) Si además quisiéramos añadir el estilo con class al ser una palabra reservadas del sistema debemos escribir la propiedad con @class. Html.BeginForm("Create", "Alumno", FormMethod.Get, new {id="fTest", @class="formulario-ua"}) El resultado final sería <form action="/Alumno/Create" class="formulario-ua" id="fTest" method="get"></form> En caso de que no usemos using en la declaración de beginform deberemos usar endform para indicar donde acaba. @{ Html.BeginForm("Create", "Alumno", FormMethod.Get, new {id = "fTest", @class = "formulario-ua"}); } … @{ Html.EndForm();} Yo usaré en todos los ejemplos using porque queda el código más agrupado. Ahora es el momento de incluir elementos en el formulario Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 12 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS Label(s:name, o:text) Un etiqueta con texto que hace referencia a un campo (name). En caso de que no se indique el texto pondrá por defecto el nombre del campo que hayamos indicado en el primer parámetro. @using(Html.BeginForm("Create", "Alumno", FormMethod.Get, new {id = "fTest", @class = "formularioua"})) { @Html.Label("Nombre", "Nombre:") … } En este ejemplo mostrará una etiqueta “Nombre:” que hace referencia a un campo “Nombre”. <label for="Nombre">Nombre:</label> TextBox(s:name, o:value) Crea una caja de texto con el nombre que le indiquemos y con un valor por defecto en el segundo parámetro. @Html.TextBox("Nombre", "Alberto") genera <input id="Nombre" name="Nombre" type="text" value="Alberto" /> Todo el contenido que se asigne en el valor por defecto (en cualquier HTMLHelper) se codifica automáticamente para evitar que se produzcan ataques XSS injection. CheckBox(s:name, b:checked) Genera una elemento checkbox. DropDownList(s:name, list:selectlistitems) Genera una lista desplegable en la que podemos seleccionar un único elemento. @Html.Label("Sexo") @Html.DropDownList("Sexo", new MultiSelectList(new[] {"Hombre", "Mujer"})) Genera Hidden(s:name, o:value) Genera un campo oculto. Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 13 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS ListBox(s:name, list:selectlistitems) Genera una lista de valores en la que podemos seleccionar más de un elemento. @using(Html.BeginForm("Create", "Alumno", FormMethod.Get, new {id = "fTest", @class = "formularioua"})) { @Html.Label("Unidad") @Html.ListBox("Unidad", new MultiSelectList(new[] {"Servicio de Informática", "Selección y Formación", "Servicio de Personal"})) } Genera RadioButton(s:name, o:value, b:checked) Genera una elemento radiobutton TextArea(s:name, s:value) Crea una caja de texto de tipo textarea. ValidationSummary([Exclude property -level error]) Muestra una lista no ordenada de todos los errores que se producen al validar el formulario. Se puede validar todo o excluir los errores a nivel de las propiedades del modelo Los errores se pueden lanzar en tiempo de ejecución con la propiedad AddModelError(campo, mensaje de error) del objeto ModelState. En caso de que el campo lo dejemos vacío estamos lanzando un error a nivel de modelo ModelState.AddModelError("", "Prueba de un error general"); y si indicamos el campo lo hacemos a nivel de propiedad. ModelState.AddModelError("Nombre", "El nombre no cumple con los requisitos"); Añadimos a la vista un sumario de validación @using(Html.BeginForm()) { @Html.ValidationSummary(false) } Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 14 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS El resultado Por defecto asigna el estilo "validation-summary-errors”. ValidationMessage (s:[Nombre del campo], o:[Mensaje de error]) En caso de que no queramos que sea un sumario el que recoja todos los mensajes, si no que cada mensaje aparezca en el punto que indiquemos (normalmente a la derecha del campo), usaremos este Helper. Si no se especifica el mensaje de error, todos aquellos errores que se produzcan (o provoquemos) se visualizarán en este punto. @Html.ValidationMessage("Nombre") Se visualizará de la siguiente manera Por defecto asigna el estilo “field-validation-error”. Action(s: [nombre acción]) Nos permite llamar a un método / acción de un controlador. Puede parecerse mucho a las vistas parciales que vimos ayer y que recordaremos luego, pero lo cierto es que mientras las vistas parciales están pensadas para escribir bloques de código, action está orientada a ejecutar el proceso completo de la acción de un controlador (que incluye la generación del código con la Vista). El resultado es una cadena de texto con todo el contenido generado. @Html.Action("Cabecera") ActionLink(s: [descripción], s: [acción], s: [controlador]) Permite generar enlaces a acciones determinadas de un controlador. Por ejemplo si queremos poner un enlace a la acción Index del Home usaríamos Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 15 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS @Html.ActionLink("Página principal", "Index", "Home") Se usa en las plantillas para realizar cualquier acción con el modelo del controlador, alta, baja, edición o borrado. Dispone de muchas sobrecargas este Helper, permitiendo desde indicar protocolor, servidor y ancla, hasta definir los atributos HTML. RouteLink(s: [descripción], d: [valores ruta]) Es parecido alterior, porque genera un enlace a una ruta o una acción de un controlador. Es algo más artesanal ya que no dispone de tantas sobrecargas y todos los valores se meten en un campo o se llama a la routa por su nombre (en caso que se haya definido previamente). Si queremos enlazar con la acción “Acerca de” usaríamos @Html.RouteLink("Acerca de", new { controller = "Home", action="About"}) RenderAction(s: [nombre acción]) Es idéntica a Action con la diferencia de que no almacena el contenido en una cadena de texto si no que la escribe directamente al objeto Response, con lo que se visualiza por el navegador. Si deseamos que una acción sea sólo llamada desde Action o RenderAction pero no directamente como una dirección más en el navegador podemos usar la anotación ChildActionOnly antes de la declaración [ChildActionOnly] public ActionResult Cabecera() { } Aunque puede parecer que crear un Helper es lo mismo que llamar a vistas parciales (que vimos ayer) porque ambas se usan para reaprovechar código o dejarlo más estructurado, si que es cierto que cada uno tiene su uso. Helpers personalizado está pensado para pequeños trozos de código, que generan una programación sencilla y que se comparte con diferentes vistas de tu proyecto o incluso entre varios. Partial views están orientadas a secciones de código, con el objetivo de hacer más clara la estructura. Puede contener una programación tan complicada como la vista que les llama. Disponemos de dos HTMLHelpers dedicados a trabajar con Partial views (ayer usamos el comando RenderPage). Partial(s: nombrevista) Genera una cadena de texto con la ejecución de la vista parcial Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 16 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS @Html.Partial("_Cabecera") RenderPartial(s: nombrevista) Es idéntica a Partial con la diferencia de que no almacena el contenido en una cadena de texto si no que la escribe directamente al objeto Response, con lo que se visualiza por el navegador. @{ Html.RenderPartial("_Cabecera"); } Personalizados Como es lógico MVC nos permite crear nuestros propios Helpers para darle mayor potencia a éstos. Se comportan como una función a la que se pasan parámetros si los necesita, y dentro genera el código que queremos mostrar. Helpers locales declarativos (inline helpers) El formato es @Helper [Nombre Función]( [parámetros] ) @helper BreadCumb(string[] elementos) { <div> for(int i=0; i < elementos.Count(); i++) { <span>@elementos[i]</span> if (i < elementos.Count() - 1) { <text>></text> } } </div> } Luego para llamarla @NombreFunción(parámetros) @BreadCumb(new[] {"Inicio", "Administración", "Secciones"}) El resultado es el siguiente Es costumbre a la hora de poner los parámetros, anteponer el nombre de cada parámetro y luego : (dos puntos). @BreadCumb(elementos: new[] {"Inicio", "Administración", "Secciones"}) Si deseamos que es helper sea reutilizables desde cualquier vista, añadimos la carpeta App_Code a nuestro proyecto (no aparece como opción en las carpetas de ASP.NET) y creamos el fichero BreadCumbHelpers.cshtml. Copiamos el código del Helper y lo guardamos. Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 17 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS Ahora para hacerle referencia desde la vista llamaremos al helper de la siguiente manera @[Nombre fichero (sin extensión)].[Nombre del helper o función]( [parámetros]) @BreadcumbHelpers.BreadCumb(elementos: new[] { "Inicio", "Administración", "Secciones" }) Como resumen de los helpers locales: Se declaran en la propia vista en un bloque @helper No pueden devuelven ningún tipo de dato. En realidad devuelven un HelperResult pero para nosotros es totalmente transparente. Su código se escribe directamente en la vista Sirven exclusivamente para generar HTML (a diferencia de los helpers locales normales que podían devolver cualquier tipo de dato). Helpers globales (external helper) Hay otra forma de crear Helpers personalizados en el que “construimos el contenido” que queremos generar. Será una clase, con métodos que no generan HTML directamente como una vista parcial, si no que devuelve un objeto de tipo IHtmlString. Las etiquetas se generan con TagBuildery los atributos se añaden con MergeAttribute. Un ejemplo muy útil, y que encontramos en muchas páginas, es crear nuestro propio ActionLink para trabajar con imágenes. using using using using System.Web; System.Web.Mvc; System.Web.Mvc.Html; System.Web.Routing; namespace _3_MVCHelpers.Helpers { public static class HtmlImageActionLinkHelper { public static IHtmlString ImageActionLink( this HtmlHelper helper, string imageUrl, string actionName, object routeValues, object htmlAttributes ) { var builder = new TagBuilder("img"); builder.MergeAttribute("src", imageUrl); builder.MergeAttributes(new RouteValueDictionary(htmlAttributes)); var link = helper.ActionLink("[replaceme]", actionName, routeValues); var html = link.ToHtmlString().Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing)); return new HtmlString(html); } } } Para referenciarlo en nuestra propia vista, usaremos @Html.[Método] ([Parámetros]). Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 18 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS Si queremos añadir una imagen 012.jpg que al pulsar sobre ella vaya a la acción Index usaríamos: @Html.ImageActionLink( Url.Content("~/Fotos/012.jpg"), "Index", new { id = 5 }, new { id = "imgnb", width = "100px", height = "150px", alt = "Foto playa de Alicante" } ) Como resumen de los helpers globales: Método de extensión de la clase HtmlHelper. Devuelve una instancia de HtmlString. o En cualquier caso, no es obligatorio que un helper devuelve siempre código HTML, también podría devolver cualquier otro tipo de datos, por ejemplo un bool o simplemente no devolver nada (void). Además incluso podría devolver directamente un string y entonces Razor codificaría en HTML la salida (con HtmlString, Razor confía en los helpers y no codifica en HTML la salida). o Utilizar la clase TagBuilder para construir el DOM. Accesible por cualquier vista que importe el espacio de nombres donde esté declarado el helper (también pueden incluir el espacio de nombres en el fichero Views/Web.config y estará automáticamente disponibles para todas las vistas). GENERACIÓN DE VERSIONES IDIOMÁTICAS CONFIGURAR Y DETECTAR EL IDIOMA POR DEFECTO La plantilla que disponemos como guía dispone de una gestión para detectar el idioma. Dispone de un la parte superior derecha un menú para cambiar de idioma Seleccionando otro idioma veremos que los elementos comunes han cambiado. La lógica se gestiona desde Application_AcquireRequestState en el fichero Global.asax.cs. Analiza si ya la tenemos guardada en Session[“idioma”]. En caso de que no la encuentre la extrae de la configuración del navegador. Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 19 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS Dentro de la carpeta Controller disponemos de la lógica básica para cambiar de idioma y retornar a la página que nos llamó. RECURSOS El elemento base para gestionar las traducciones son los recursos. Una buena práctica es crearnos una carpeta Resources y meter todos aquellos ficheros que necesitemos. Se pueden crear a nivel de controlador o modelo o a nivel de aplicación si nuestro proyecto es muy básico. Sobre el proyectos pulsamos botón derecho Agregar > Nueva carpeta y le ponemos el nombre Resources. Ahora sobre esta nueva carpeta Agregar > Nuevo elemento … y seleccionamos (o filtramos) Archivo de recursos. Le llamamos modelos.resx Añadimos las descripciones que queremos que estén en varios idiomas Es importante que marquemos el fichero como público para que se pueda acceder desde el resto de los elementos de MVC Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 20 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS Para crear la versión de recursos para otro idioma, copiamos y pegamos el que usemos de base y luego le añadimo .[dos digitos del idioma] antes de la extensión del fichero. Es nuestro caso para crear el fichero de recursos en inglés renombraríamos copia de modelos.resx por modelo.en.resx y traduciríamos los valores de cada una de las etiquetas. VISTAS La manera más cómoda de pasar textos traducidos a las vistas, en caso de que sean pocos, es usar el controlador y el objeto ViewBag. Para acceder a un recurso escribimos el [nombre carpeta de recursos].[ nombre recurso (sin extensión].etiqueta. ViewBag.Titulo = Resources.modelos.tituloLabel; Luego en la propia vista lo referenciamos Texto del fichero de recursos: @ViewBag.Titulo<br /> Si la vista contiene muchos elementos a traducir, lo más sencillo es crear dos versiones de la vista de la misma manera que lo hemos hecho con el fichero de recursos. Cogemos la vista base index.cshtml la copiamos y la pegamos y renombramos por index.en.cshml. Hacemos los cambios que corresponda Creamos una clase para gestionar los idiomas CultureHelper. La variable Cultures almacena los idiomas con los que trabajemos. El primero de ellos será el que se usará por defecto en caso de que detectemos otro que no se corresponda con nuestro listado. using System; using System.Collections.Generic; using System.Linq; namespace _3_MvcGlobalization.Helpers { public static class CultureHelper { // Include ONLY cultures you are implementing as views private static readonly Dictionary<String, bool> Cultures = new Dictionary<string, bool> { {"es", true}, // first culture is the DEFAULT {"en", true}, {"ca", true} }; /// <summary> /// Returns a valid culture name based on "name" parameter. If "name" is not valid, it returns the default culture "en-US" /// </summary> /// <param name="name">Culture's name (e.g. en-US)</param> public static string GetValidCulture(string name) { if (string.IsNullOrEmpty(name)) return GetDefaultCulture(); // return Default culture if (Cultures.ContainsKey(name)) return name; Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 21 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS // Find a close match. For example, if you have "en-US" defined and the user requests "enGB", // the function will return closes match that is "en-US" because at least the language is the same (ie English) foreach (var c in Cultures.Keys) if (c.StartsWith(name.Substring(0, 2))) return c; // else return GetDefaultCulture(); // return Default culture as no match found } /// <summary> /// Returns default culture name which is the first name decalared (e.g. en-US) /// </summary> /// <returns></returns> public static string GetDefaultCulture() { return Cultures.Keys.ElementAt(0); // return Default culture } /// <summary> /// Returns "true" if view is implemented separatley, and "false" if not. /// For example, if "es-CL" is true, then separate views must exist e.g. Index.es-cl.cshtml, About.es-cl.cshtml /// </summary> /// <param name="name">Culture's name</param> /// <returns></returns> public static bool IsViewSeparate(string name) { if (Cultures.ContainsKey(name)) return Cultures[name]; return false; } } } El siguiente paso es crear nuestro propio controlador que detectará el idioma y personalizará la vista. Requerimos hacer uso de dos métodos de la clase Controller: ExecuteCore y OnActionExecuted. El primero normaliza el idioma, lo almacena en una variable sesión y establece CurrentCulture. En Session[“idioma”] vamos a almacenar el idioma que se haya detectado o el que se seleccione (lo veremos luego). De esa manera lo podremos usar en cualquier vista o controlador. El segundo establece la vista que debe abrir el controlador dependiendo del idioma que se haya seleccionado. using using using using System.Globalization; System.Threading; System.Web.Mvc; _3_MvcGlobalization.Helpers; namespace _3_MvcGlobalization.Controllers { public class UaController : Controller { protected override void OnActionExecuted(ActionExecutedContext filterContext) { // Detectamos si llamamos desde una vista var view = filterContext.Result as ViewResultBase; Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 22 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS if (view == null) // En caso de que no sea, salims return; string cultureName = Thread.CurrentThread.CurrentCulture.Name; // Buscamos si if (cultureName == CultureHelper.GetDefaultCulture()) return; // Are views implemented separately for this culture? if not exit bool viewImplemented = CultureHelper.IsViewSeparate(cultureName); if (viewImplemented == false) return; string viewName = view.ViewName; int i; if (string.IsNullOrEmpty(viewName)) viewName = filterContext.RouteData.Values["action"] + "." + cultureName; // Index.en-US else if ((i = viewName.IndexOf('.')) > 0) { // contains . like "Index.cshtml" viewName = viewName.Substring(0, i + 1) + cultureName + viewName.Substring(i); } else viewName += "." + cultureName; // e.g. "Index" ==> "Index.en-Us" view.ViewName = viewName; filterContext.Controller.ViewBag._culture = "." + cultureName; base.OnActionExecuted(filterContext); } protected override void ExecuteCore() { var idioma = Session["idioma"]; string cultureName; if (idioma != null) cultureName = idioma.ToString(); else { cultureName = (Request.UserLanguages == null ? CultureHelper.GetDefaultCulture() : Request.UserLanguages[0]); if (cultureName.IndexOf("-") > 0) cultureName = cultureName.Substring(0, cultureName.IndexOf("-")); Session["idioma"] = cultureName; } // Normalizamos var normalizedCultureName = CultureHelper.GetValidCulture(cultureName); if (normalizedCultureName != cultureName) { cultureName = normalizedCultureName; Session["idioma"] = cultureName; } // Actualizamos el idioma Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName); Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultureName); base.ExecuteCore(); } Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 23 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS } } Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 24 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS PLANTILLA Por defecto la plantilla que se usa es la que se configure en /Views/ _ViewStart.cshtml. Por seguir con este criterio, si modificamos este fichero y usamos la variable Session[“idioma”] tendremos la plantilla que se debe usar. @{ Layout = "~/Views/Shared/_Layout." + @Session["idioma"] + ".cshtml"; } En clase lo optimizaremos para que no se produzcan errores cuando no esté definida esta variable. CAMBIAR DE IDIOMA Nuestra plantilla permite cambiar el icioma public ActionResult ChangeLanguage(string language) { Session["idioma"] = language; if (Request.UrlReferrer != null) return Redirect(Request.UrlReferrer.ToString()); return Redirect("Index"); } [ @Html.ActionLink("English", "ChangeLanguage", "Home", new { language = "en" }, null) ] [ @Html.ActionLink("Español", "ChangeLanguage", "Home", new { language = "es" }, null) ] [ @Html.ActionLink("Valencià", "ChangeLanguage", "Home", new { language = "ca" }, null) ] En caso de que nos envíen un idioma que no se corresponda con el listado admitido, no habrá problemas porque en la siguiente llamada a Index (o la página desde donde se llamó) se detectará que no se corresponde con uno de los admitidos y se asignará el que tengamos por defecto. MODELO Siguiendo el ejemplo del libro de antes, si queremos que la descripción del título salga del fichero de recursos remplazamos [Display(Name = "Título del libro")] public string Titulo { get; set; } por [Display(Name = "tituloLabel", ResourceType = typeof(Resources.modelos))] public string Titulo { get; set; } En caso de que nos de un error de que no se encuentra un recurso público con ese nombre, recordar lo de marcar Public en el fichero de recursos. Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 25 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS BOOTSTRAP Es un framework diseñado para simplificar el proceso de creación de diseños web. Para ello nos ofrece una serie de plantillas CSS y de ficheros JavaScript, los cuales nos permiten conseguir: Interfaces que funcionen de manera brillante en los navegadores actuales, y correcta en los no tan actuales. Un diseño que pueda ser visualizado de forma correcta en distintos dispositivos y a distintas escalas y resoluciones. Una mejor integración con tus las librerías que sueles usar habitualmente, como por ejemplo jQuery. Un diseño sólido basado en herramientas actuales y potentes como LESS o estándares como CSS3/HTML5 Vamos a trabajar durante el curso con la versión 2.3.2 aunque ya está disponible la versión 3. En el momento que sea más estable y la mayoría de los componentes que usamos sean compatibles haremos el salto a la nueva versión. Nada mejor que acceder a su página web y ver lo que nos ofrece http://getbootstrap.com/2.3.2/ De todos los elementos nos vamos a centrar en los básicos para comenzar a trabajar: Grid (http://getbootstrap.com/2.3.2/scaffolding.html#fluidGridSystem) Botones (http://getbootstrap.com/2.3.2/base-css.html#buttons) Formularios (http://getbootstrap.com/2.3.2/base-css.html#forms) Iconos (http://getbootstrap.com/2.3.2/base-css.html#icons) Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 26 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS JQUERY jQuery es una biblioteca de JavaScript, que permite simplificar la manera de interactuar con los documentos HTML, manipular el árbol DOM, manejar eventos, desarrollar animaciones (FLV) y agregar interacción con la técnica AJAX a páginas web. Es la biblioteca de JavaScript más utilizada. ASP.NET MVC usa esta librería de base (la podemos encontrar en la carpeta Scripts) y la mayoría de los plugins que encontramos por Internet hace uso de ella. La plantilla que tiene por defecto ASP.NET MVC la incluye con lo que podemos utilizarla en nuestras vistas sin ningún problema. La tarea más común en JQuery es acceder a algún elemento de nuestra página modificar sus propiedades o contenido y que se actualice antes de que se visualice la página al usuario. Nos vamos a centrar en estos puntos y cada día iremos incorporando nuevas características. SELECTORES Jquery dispone de varios métodos para acceder a los elementos de nuestra página. Vamos a analizar los más comunes. Todos ellos utilizan la función $(“[selector]”). Si nunca se ha programado con JQuery o Mootools nos llamará la atención que se use el $ como función para acceder a los elementos de nuestra página. En caso de que trabajemos con JQuery y Mootools, y hagamos referencia a ambas librerías desde nuestras páginas, se producirá un conflicto por la función $ que ambas usan. Para solucionarlo JQuery ofrece una solución muy sencilla. Incluimos la instrucción jQuery.noConflict(); para indicar que desde este momento para hacer uso del selector en JQuery vamos a utilizar jQuery (“[selector]”) en vez de $(“[selector]”). De esa manera ya no interfiere con Mootools que lo sigue utilizando sin problemas. Vamos a analizar los selectores más comunes $(“#id”) Seleccionamos un elemento HTML por el id que tenga. Es muy normal usarlo en elementos muy comunes de nuestra página cabecera, cuerpo, noticias o pie, aunque si somos cuidadosos con los ids, podemos usarlo en cualquier elemento que queramos. Por ejemplo si tenemos una capa div con id igual a capa_1 <div id="capa_1"></div> Para acceder a este elemento usamos var el = $("#capa_1"); Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 27 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS Ahora podríamos hacer cualquier operación con este elemento, que es un objeto que dispone de métodos / funciones que iremos viendo. $(“elemento”) En ocasiones nos interesa que todos los elementos HTML de un tipo (por ejemplo los enlaces) cambien alguna propiedad que no es accesible (el ejemplo más claro es que se abran en un nueva ventana). Tenemos un listado de enlaces <div id="capa_2"> <a href="1">Enlace <a href="2">Enlace <a href="3">Enlace <a href="4">Enlace </div> 1</a><br 2</a><br 3</a><br 4</a><br /> /> /> /> Para acceder al listado de enlaces usamos el selector por elemento var els = $("a"); y para recorrer todos los elementos para actualizar alguna propiedad els.each(function () { var el = $(this); el.attr("target", "_blank"); }); Un error común cuando comenzamos con JQuery es que creemos que el elemento “el” es el propio elemento HTML y que por tanto accedo a sus atributos con el.target = "_blank";. Si lo probáis veréis que no es así, porque “el” es un objeto JQuery y no un enlace. Debemos usar los métodos que nos ofrece JQuery para estas tareas. $(“.clase”) o $(“elemento.clase”) Un paso más en la selección es que no accedamos a elementos tan genéricos si no a aquellos que nosotros marquemos con un estilo determinado. El ejemplo anterior sería mejor si sólo lo aplicáramos a aquellos enlaces que pertenezcan a la clase “externo”. Modificamos el listado anterior para indicar que dos son externos y otros dos no. <div id="capa_2"> <a class="externo" <a href="2">Enlace <a class="externo" <a href="4">Enlace </div> href="1">Enlace 1</a><br /> 2</a><br /> href="3">Enlace 3</a><br /> 4</a><br /> Para acceder a estos dos enlaces no podemos usar el genérico de elementos porque cogeríamos los 4, usamos: var els = $("a.externo"); o en caso de que sólo se use esta clase con enlaces y no haya confusión con otros elementos var els = $(".externo"); Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 28 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS Otro ejemplo muy común es crearnos un estilo “obligatorio” que realice determinadas operaciones sobre los elementos (cambiar color, poner en negrita, añadir un asterisco para indicar que es obligatorio, etc.). var els = $(".obligatorio"); y luego los recorremos els.each(function () { var el = $(this); // Operaciones sobre cada elemento }); Hijos o descendente Ahora es el momento de combinar selectores $(“#cabecera a”) Selecciona todos los enlaces que hay dentro de el elemento con id igual a “cabecera” da lo mismo que estén en el siguiente nivel de “cabecera” o dentro de otros elementos. En <div id="cabecera" style="margin-top: 20px;"> <a href="1">Enlace 1</a><br /> <a href="2">Enlace 2</a><br /> <div id="subcabecera" style="margin-top: 10px;"> <a href="3">Enlace 3</a><br /> <a href="4">Enlace 4</a><br /> </div> </div> Cambiaría el color a los 4 enlaces var els = $("#cabecera a"); els.each(function () { var el = $(this); el.attr("style", "color: red"); }); $(“#cabecera > a”) Si solo queremos modificar los 2 enlaces hijo y descartar otros descendientes que pertenecen a otro elemento. var els = $("#cabecera > a"); els.each(function () { var el = $(this); el.attr("style", "color: red"); }); Sólo cambia el color a los dos primeros enlaces que son hijos directos de “cabecera”. Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 29 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS FUNCIONES Un problema que nos podemos encontrar con JavaScript es el momento de inicializar los elementos de HTML porque hasta que no se acaba el código, no tenemos a nuestra disposición a todos los elementos. Una buena costumbre es poner al final del HTML todos los ficheros que hacen referencia a JavaScript. La razón principal es que la persona ya puede comenzar a visualizar la página en ese momento y no debe esperar a que se carguen todos los ficheros JavaScript que en ocasiones, si hacen referencia a direcciones externas, pueden producir un retardo molesto. Además de esta técnica que usaremos en nuestras plantillas, jQuery tiene dos métodos de ejecutar código en el momento que el Modelo de Objetos del Documento (DOM) está disponible: $(document).ready http://api.jquery.com/ready/ Le indicamos la función que se ejecutará en el momento de estar listo el DOM. En el siguiente ejemplo actualizará el contenido de un elemento con id igual a “capa_1”. Independiente de que este código esté al principio o al final no dará error porque no se ejecuta en el momento de leerse el JavaScript. $(document).ready(function () { var el = $("#capa_1"); el.html("Añadimos un texto"); }); Si el código fuera sólo var el = $("#capa_1"); el.html("Añadimos un texto"); No funcionaría al principio de la página porque aun no está disponible el elemento “capa_1”. $(function () { }); Tiene el mismo comportamiento que la anterior. Cuando se pasa una función como primer parámetro, le indicas a jQuery que lo ejecute cuando esté disponible el DOM. El ejemplo anterior sería: $(function () { var el = $("#capa_1"); el.html("Añadimos un texto"); }); Arrays Aplicar una función a un array es una tarea muy común. Lo hemos visto cambiando el comportamiento de los enlaces. Se usa mucho para asignar eventos que no por accesibilidad no están permitidos dentro del código HTML. Usamos el comando each (http://api.jquery.com/jQuery.each/) que le pasamos una función como parámetro y dentro de ésta podemos acceder a cada elemento con $(this). arrayElementos.each(function () { var el = $(this); Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 30 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS // Operaciones sobre cada elemento }); Selectores por función .parent() Obtiene el padre directo de un elemento. En la siguiente figura vemos una imagen dentro de un div. Si tenemos seleccionado la imagen y solicitamos su padre obtenemos la capa div. .children() Obtiene los hijos inmediatos únicos de un elemento. En la siguiente figura vemos una capa div con tres enlaces dentro. Si tenemos seleccionada la capa siv y solicitamos los hijos obtenemos un array de enlaces, que podemos gestionar facilmente con each. CONTENIDO Disponemos dos formas muy sencillas para modificar el contenido de un elemento. html http://api.jquery.com/html/ Nos deja remplazar el código o texto que hay en ese el elemento por el que le indiquemos. Permite código con etiquetas HTML. el.html("Añadimos un texto en <strong>negrita</strong>"); La capa pasa a tener el siguiente código <div id="capa_1">Añadimos un texto en <strong>negrita</strong></div> Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 31 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS text http://api.jquery.com/text/ Parecido al anterior pero sólo para remplazar con texto sin formato. Ambas funciones también permite leer el contenido si no se le envía ningún parámetro. En el caso de text, si lo que lee tiene etiquetas HTML las elimina. var texto = el.text(); val http://api.jquery.com/val/ Devuelve o asigna el valor a un campo de un formulario. var contenido = el.val(); el.val(contenido); append http://api.jquery.com/append/ En caso de que el elemento ya tenga contenido, no lo remplaza, lo escribe detrás del contenido actual. prepend http://api.jquery.com/prepend/ En caso de que el elemento ya tenga contenido, no lo remplaza, lo escribe antes del contenido actual. load http://api.jquery.com/load/ Podemos cargar el contenido desde otra página. Lo normal, y como ya hicimos el 2º día es que lo hagamos desde una acción de nuestros controladores. Por ejemplo si queremos cargar el contenido de la acción Contenido de nuestro controlador Home, ejecutaríamos: el.load("/Home/Contenido"); Si la acción hace algo tan básico como public string Contenido() { return "Este es el texto que devuelve el action Contenido"; } El resultado es Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 32 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS .css() Consultamos o modificamos los estilos del elemento. Por ejemplo si queremos cambiar el color de un texto a rojo para resaltarlo PROPIEDADES attr http://api.jquery.com/attr/ En ocasiones lo que nos interesa no es añadir contenido si no modificar alguna propiedad, por ejemplo el color o poner en negrita por si queremos destacar algo. el.attr("style", "color: red; font-weight: bold;"); y el resultado es visible en la etiqueta. prop http://api.jquery.com/prop/ Aunque en muchas ocasiones nos pueda llevar a confusión con la function attr, prop está orientada a modificar propiedades de los objetos como puedes ser checked, disabled, multiple, readOnly, etc., mientras que attr a modificar atributos como class, href, label, src, title, etc. Por ejemplo si queremos consultar o modificar el estado de un checkbox $(elemento).prop("checked"); Y $(elemento).prop("checked", true); Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 33 ASP.NET MVC 4 | ELEMENTOS GRÁFICOS EJERCICIOS Reemplazar contenido de un div con lo insertado en un textarea Añadir el contenido de un textarea a un div Chequear todos los checkbox que hay dentro de una capa div Igualar altura de todas las columnas que haya dentro de un capa div. Usaremos el método height() Añadir un icono delante de todos los enlaces que tengan la clase vineta ANUNCIOS Crear un helper para poder valorar un anuncio Crear un helper para poder realizar comentarios CATALOGADOR Crear helpers para los elementos comunes o Descripción de un catalogador o Descripción de una sección Andrés Vallés Botella | Analista | Desarrollos propios Servicio de Informática | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | España http://si.ua.es/es 34