Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 1 de febrero de 2022
Blazor

Si habéis utilizado isolation con módulos JavaScript en Blazor 5, probablemente lo que vamos a ver en este post os resulte muy interesante para organizar los archivos JavaScript de la aplicación, especialmente aquellos que sean utilizados desde un único componente.

Como recordaréis, el aislamiento de JavaScript de Blazor permitía cargar de forma dinámica un archivo .js y ejecutar código definido en él. Por ejemplo, imaginad un módulo como el siguiente, definido en wwwroot/modules/MyPrompt.js:

export function showPrompt(message, defaultValue) {
    return prompt(message, defaultValue);
}

Si queremos interoperar con este código desde Blazor, la forma más sencilla es:

  • Inyectar en la página o componente un objeto IJSRuntime para importar una referencia al módulo llamando a su método InvokeAsync(), especificando como primer parámetro el valor "import", seguido de la ruta hacia el archivo:
var module = await JsRuntime.InvokeAsync<IJSObjectReference>("import", "./modules/MyPrompt.js");
  • Una vez obtenida la referencia al módulo, de nuevo usar InvokeAsync() para llamar a la función.
var name = await module.InvokeAsync<string>("showPrompt", "Your name?", 

Nota: el módulo puede ser mantenido durante la vida del componente, por ejemplo cargando la referencia cuando el componente se haya renderizado por primera vez (en OnAfterRender()), y manteniéndola en memoria hasta su destrucción.

A continuación podemos ver un ejemplo completo en acción. Observad que al pulsar el botón es cuando cargamos el módulo y ejecutamos la función:

@page "/"
@inject IJSRuntime JsRuntime

@if (!string.IsNullOrWhiteSpace(name))
{
    @:Name: @name
} else
{
    @:No name specified
}
&nbsp;<a href="" @onclick="@GetNameButtonClicked">Set name</a>

@code {
    private string name = null;
    async Task GetNameButtonClicked()
    {
        var module = await JsRuntime.InvokeAsync<IJSObjectReference>("import", "./modules/MyPrompt.js");
        name = await module.InvokeAsync<string>("showPrompt", "Your name?", name ?? string.Empty);
    }
}

Y así luciría en tiempo de ejecución:

Componente en funcionamiento: la pulsación del link 'set name' abre el prompt para preguntar el nombre y el valor introducido es mostrado en pantalla

Estructura de proyecto con el archivo Index.razor.js anidado con el componente Index.razorEl problema con este enfoque es que, cuando tenemos código JavaScript exclusivo para un componente, su archivo .js quedará ubicado en el proyecto lejos de éste, dificultando su mantenimiento. Además, a la larga, podríamos encontrarnos un gran número de archivos en la carpeta wwwroot o descendientes, lo cual podría ser difícil de gestionar.

Con Blazor 6, podemos ubicar los archivos de script específicos para un componente junto a éste. Es más, podemos anidarlo utilizando la convención de nombrado {NombreDelComponente}.razor.js, como en Counter.razor.js.

De esta forma, como podéis ver en la captura lateral, su ubicación es mucho más intuitiva y, dado que su contenido irá siempre relacionado con el componente al que se ha asociado, será mucho más fácil de mantener.

Para cargar estos recursos debemos utilizar su ruta real en el proyecto, como en el siguiente ejemplo:

var module = await JsRuntime
     .InvokeAsync<IJSObjectReference>("import", "./Pages/Index.razor.js");
...

Para que esto sea posible, todos los archivos que sigan esta convención son copiados de forma automática a wwwroot durante el proceso de publicación. En el ejemplo anterior, el archivo JavaScript será finalmente ubicado en  wwwroot/Pages/Index.razor.js una vez en desplegado.

Por último, vale la pena comentar que para módulos JS que sean compartidos entre distintos componentes, por supuesto podemos seguir usando wwwroot como carpeta base para ellos, como en el ejemplo que veíamos al principio :)

Publicado en Variable not found.

Aún no hay comentarios, ¡sé el primero!