Blog ENI : Toute la veille numérique !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
💥 Les 22 & 23 novembre : Accès 100% GRATUIT
à la Bibliothèque Numérique ENI. Je m'inscris !
  1. Livres et vidéos
  2. Blazor
  3. Fonctionnalités avancées
Extrait - Blazor Développement Front End d'applications web dynamiques en C#
Extraits du livre
Blazor Développement Front End d'applications web dynamiques en C#
4 avis
Revenir à la page d'achat du livre

Fonctionnalités avancées

JavaScript et CSS

Maintenant que les composants ont été explorés, il est temps de voir en détail les fonctionnalités avancées de ces derniers. Nous allons commencer par traiter les fonctionnalités qui concernent JavaScript et CSS, pour ensuite aborder les ajouts faits en .NET 5.

1. Interopérabilité avec JavaScript

Même si Blazor permet d’écrire du code C# à la place de JavaScript pour les interactions les plus communes, il n’en reste pas moins qu’il existe une panoplie de composants et de projets JavaScript créés par la communauté pour répondre à un vaste ensemble de besoins. Blazor permet de travailler avec ces derniers, et ce de manière bidirectionnelle (c’est-à-dire qu’il est possible d’intégrer un composant JavaScript et de lui envoyer des données, mais aussi d’exécuter du code C# depuis JavaScript). Nous allons voir ces deux modes.

a. Invocation JavaScript depuis C#

C’est le scénario le plus courant. Il existe bien des cas d’usage où il est nécessaire d’avoir recours à un composant JavaScript et donc d’appeler des méthodes JavaScript depuis le code C#. L’équipe de développement de Blazor a prévu ces cas : elle a mis à disposition une interface, IJSRuntime, permettant d’effectuer cette manipulation. Cette interface est directement utilisable par injection de dépendances dans les composants :

[Inject] 
public IJSRuntime JSRuntime{ get; set; } 

Comme cela a été évoqué dans le chapitre Les composants en détail, il est nécessaire de réaliser les appels JavaScript à un niveau assez tardif dans le cycle de vie d’un composant, c’est-à-dire au minimum dans la méthode OnAfterRenderAsync. Cela permet d’assurer que la totalité du composant et de la communication est disponible afin de pouvoir traiter l’ordre en JavaScript. Il y a deux façons distinctes d’appeler une méthode JavaScript :

  • Invocation d’une méthode qui ne renvoie aucun paramètre. Cela se passe avec la méthode InvokeVoidAsync.

  • Invocation d’une méthode qui renvoie un paramètre. Cela...

Composant imbriqué

Créer un composant n’est pas toujours une finalité en soi. Il est possible d’intégrer un composant dans un autre facilement, juste en utilisant la balise de ce dernier.

1. Création d’un loader

Par exemple, si nous souhaitons réaliser un composant chargé d’afficher un texte, une image ou une animation pour faire patienter l’utilisateur (on appelle cela un loader) pendant le chargement de données, nous pouvons procéder de la sorte :

  • création d’un composant appelé Loader

  • ajout de son fichier CSS personnalisé.

En utilisant ce que nous savons et en récupérant le code CSS et HTML sur un site dédié aux loaders (par exemple https://loading.io/css), nous pouvons créer notre propre composant Loader réutilisable. Pour que ce composant soit directement utilisable dans la totalité de l’application, nous pouvons le placer dans le dossier Shared de notre projet. Ainsi, lorsque nous avons besoin d’un chargement, il nous suffit d’utiliser ce composant :

@if (Loading) 
{ 
    <Loader></Loader> 
} 
else 
{ 
... 
} 

Attention, les loaders présents sur le site précédemment mentionné sont blancs, et donc non visibles sur fond blanc. Il y a deux solutions afin de les rendre visibles : appliquer un fond de couleur différente sur la page ou appliquer un background aux éléments animés. Cela nécessite quelques modifications du code CSS.

images/04EI03.PNG

Rendu final du loader

Le code du loader est détaillé en fin de chapitre dans la section Exercice.

Cependant, ce loader tourne indéfiniment. Il serait intéressant de personnaliser le composant afin qu’il reflète l’état d’avancement de l’attente.

2. Ajout d’un message d’attente personnalisé

Nous pourrions améliorer le loader en ajoutant par exemple un paramètre qui indique le timeout (temps d’attente) ainsi que le message à afficher sous l’animation en cas de dépassement du timeout, lorsque le chargement est anormalement long. Cela est bien sûr possible en utilisant [Parameter] pour les deux données (l’une de type...

Communication HTTP

Lorsqu’on crée une application avec Blazor, cela doit rester une application front-end, sauf si l’on développe un composant isolé destiné à être intégré dans un site existant en ASP.NET Core. Ladite application communique alors avec une autre application stockée sur les serveurs, une API, qui fait office de back-end. Cette dernière peut être écrite dans n’importe quelle technologie, tant qu’elle respecte un standard de communication et un format lisible par HTTP (JSON, XML, gRPC…).

Voyons maintenant comment faire communiquer notre application Blazor avec un back-end.

1. Création d’un back-end

La première étape est de créer un back-end. Le cas d’usage ici est le stockage des données météorologiques. En ce sens, nous créons créer une nouvelle application de type API web en .NET Core à l’aide de la commande suivante :

dotnet new webapi --no-https 

Ce template d’API contient déjà les endpoints pour la partie météo. Cependant, l’avantage de Blazor est que l’on peut partager le modèle entre le back-end et le front-end. La meilleure solution est d’unifier le modèle dans une librairie de classes partagée entre les deux applications.

Si l’on développe avec la plateforme .NET Core 3.1, il faut créer une librairie en .NET Standard 2.1. Si l’on travaille avec la version .NET 5, la librairie peut être créée en .NET 5. Dans les deux cas, un projet de type librairie se crée à l’aide de la commande suivante :

dotnet new classlib 

Si l’on utilise Visual Studio sous Windows ou sous Mac, il est possible de regrouper la gestion de ces trois projets (API, Blazor, librairie) dans un seul fichier : une solution. Cette dernière se crée à l’aide de la commande :

dotnet new sln 

Une fois la solution créée, il suffit d’ajouter les projets créés précédemment en utilisant la fonctionnalité Ajouter un projet existant de l’IDE.

L’approche solution est inutile avec Visual Studio Code, ce dernier préférant la gestion par dossier au système de solution.

Notre projet Blazor Server définit...

Interactions avancées entre composants

Dans le chapitre Les composants en détail, nous avons vu le fonctionnement des formulaires et abordé la question de la validation des données sous-jacentes. Cependant, dans notre formulaire exemple, certaines faiblesses existent au niveau de cette validation. Par exemple, si l’utilisateur clique sur Valider et si des erreurs de saisie sont détectées, le bouton Valider reste actif alors même que les erreurs n’ont pas encore été corrigées.

Nous n’avons pas encore vu d’autres moyens que le two-way data binding pour permettre à un composant enfant de déclencher dynamiquement une action au sein d’un composant parent. Voyons maintenant comment améliorer nos formulaires et la communication entre composants.

1. Empêcher la validation d’un formulaire

Pour le moment, notre formulaire possède des éléments de validation qui affichent un message d’erreur (sous les champs ou sous forme de résumé) et cela empêche le formulaire d’être envoyé. Néanmoins, le bouton de validation du formulaire reste actif et cela pourrait nuire à l’expérience utilisateur globale. Il serait appréciable d’avoir un moyen de désactiver le bouton tant que tous les champs ne sont pas corrigés.

Une des possibilités serait de gérer soi-même les changements de chaque champ et de modifier un booléen permettant de gérer l’état du bouton à l’aide de l’attribut HTML disabled. Cette approche, bien que fonctionnelle, s’avère peu pratique, car elle nécessite une grande duplication de code au travers de tous les formulaires de notre application. Une meilleure approche serait de développer un composant chargé de valider les champs de nos formulaires, qui soit réutilisable dans toute l’application.

Pour que ce composant puisse fonctionner, il faut lui donner le contexte de validation du formulaire afin qu’il puisse le traiter et produire une valeur qu’on pourra utiliser pour activer ou désactiver notre bouton d’envoi de formulaire. Cette notion s’appelle la cascade de paramètres.

a. Cascade de paramètres

La cascade de paramètres permet...

Exercice

Il est maintenant temps de mettre en pratique tout ce que nous avons vu dans ce chapitre.

Pour cet exercice, nous allons :

  • créer un sous-composant réutilisable, qui contient l’adresse et permet un two-way data binding sur la fiche d’un employé,

  • améliorer la fiche d’un employé en ajoutant une carte, à l’aide d’OpenStreetMaps, qui permet de localiser l’adresse saisie. Utiliser la librairie Leaflet à cet effet et faire les interactions entre JavaScript et Blazor pour afficher la carte avec un marqueur. La récupération des données GPS d’une adresse peut se faire à l’aide de l’API nominatim : https://nominatim.org/release-docs/develop/api/Search/,

  • ajouter un loader réutilisable lors du chargement de la fiche d’un employé et de la liste des employés,

  • créer le back-end et faire communiquer l’application Blazor avec cette dernière. La communication doit être résiliente et gérer les éventuels soucis de connexion. Ce back-end permettra de lire et d’écrire les employés ainsi que de récupérer les données "statiques" (comme la liste des pays et des postes),

  • ajouter la possibilité de créer un nouvel employé et styliser l’application à l’aide d’une libraire pour implémenter Material Design (MatBlazor).

Étant donné que cet ouvrage se concentre uniquement sur Blazor, il est possible de récupérer le back-end déjà fait sur le dépôt GitHub et de se contenter d’écrire le code de communication en Blazor. Cependant, cela reste un bon exercice de se prêter à l’écriture de la totalité de l’application.

Concernant l’appel à l’API nominatim, il est nécessaire de préciser dans les headers de l’instance HttpClient la valeur User-Agent, afin de simuler un appel depuis un navigateur. Attention ! Cette pratique n’est pas du tout recommandée en production ou sur un autre projet, au risque de se faire bloquer les accès. Néanmoins, dans le cadre de cet exercice, c’est la façon la plus simple de procéder. Pour modifier les headers d’une...