ASP.NET MVC: establecer el foco en un control al cargar la página

ASP.NET MVCUno de los aspectos más criticados por los desarrolladores cuando comienzan a trabajar con ASP.NET MVC es el hecho de tener que volver a resolver problemas que estaban ya más que solucionados en Webforms.

Y uno de estos casos es un detallito muy simple pero útil: establecer el foco de edición en un control concreto al cargar una página. En Webforms era suficiente con asignar al atributo defaultFocus del tag <form> el nombre del control que nos interesara, y ya lo teníamos solucionado; ASP.NET MVC no trae ninguna solución “de serie” para conseguirlo, aunque, como veremos en este post, no es mucho más complicado que la alternativa Webforms una vez hemos preparado la infraestructura necesaria.

En líneas generales, la solución consiste en utilizar un pequeño script que, una vez cargada la página, mueva el foco hacia el control que nos interese. Por ejemplo, si quisiéramos que el campo con identificador “Nombre” obtenga el foco automáticamente, podríamos utilizar jQuery de la siguiente forma:

<script type="text/javascript">
    $(function () {
        $("#Nombre").focus();
    });
</script>

Aunque eficaz, es una solución demasiado trabajosa e introduce una dependencia en el código, difícilmente manejable, hacia el nombre del control. Si quisiéramos introducir este código en múltiples puntos de nuestra aplicación tendríamos que copiar y pegar en cada vista, y sustituir el id del control apropiado en cada caso, lo cual es bastante incómodo.

¿No podríamos mejorar esto un poco?

El helper SetFocusTo()

Una posible solución, realmente rápida de implementar, sería crear un helper personalizado, al que llamaremos SetFocusTo(), que genere el código por nosotros partiendo únicamente de la información de la propiedad a editar.

Y para evitar la dependencia hacia el nombre de la propiedad y hacerlo más flexible, incluso podríamos crear la versión fuertemente tipada del mismo, de forma que podamos utilizarlo de cualquiera de las siguientes formas:

// Usando el nombre de la propiedad:
@Html.SetFocusTo("Nombre")

// Usando la versión fuertemente tipada:
@Html.SetFocusTo(model=>model.Nombre)

El código del helper es el siguiente:

public static class HtmlHelpers
{
    public static MvcHtmlString SetFocusTo<TModel, TProperty>(
                    this HtmlHelper<TModel> html,
                    Expression<Func<TModel, TProperty>> expression)
    {
        var prop = ExpressionHelper.GetExpressionText(expression);
        return html.setFocusTo(prop);
    }

    public static MvcHtmlString SetFocusTo(this HtmlHelper html, 
                                           string propertyName)
    {
        var prop = ExpressionHelper.GetExpressionText(propertyName);
        return html.setFocusTo(prop);
    }

    private static MvcHtmlString setFocusTo(this HtmlHelper html, 
                                            string property)
    {
        string id = html.ViewData.TemplateInfo.GetFullHtmlFieldId(property);
        var script = "<script type='text/javascript'>" +
                        "$(function() {" +
                            "$('#" + id + "').focus();" +
                        "});" +
                        "</script>";
        return MvcHtmlString.Create(script);
    }

}

Recordad que para que estos helpers estén visible en las vistas y podáis usarlos normalmente, debéis incluir el espacio de nombres en el que están definidos bien sea añadiendo una directiva @using en la vista, o bien en la sección <namespaces> del archivo web.config que encontraréis en la carpeta /Views (o en la del área correspondiente).

¡Y eso es todo! De esta forma ya volvemos a disponer de la posibilidad de establecer el foco por defecto sobre un control de forma muy rápida, compacta, y cómoda de utilizar.

Publicación original (14-dic-2011): http://www.variablenotfound.com/2011/12/aspnet-mvc-establecer-el-foco-en-un.html

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *