Les composants en détail
Analyse d’un composant
Dans le chapitre Première application, nous avons abordé la question des composants Blazor, qui sont l’élément central de toute application Blazor. Tout d’abord, il convient de préciser : il n’y a aucune différence fondamentale entre un composant qui s’exécute en version Client et un composant qui est intégré dans une application Blazor Server. Ainsi, en s’efforçant de bien respecter les principes d’architecture énoncés précédemment, on s’assure que nos composants peuvent migrer d’un schéma à l’autre sans difficulté.
1. La structure d’un composant
Dans un composant Blazor, le code est intégré dans la vue, ce qui peut déranger un développeur. En effet, les pratiques de clean architecture poussent, à raison, à séparer le code de la vue au maximum. Si on décide de laisser l’instruction @code dans notre composant directement, il y a fort à parier que des raccourcis malheureux seront faits à un moment ou un autre. Pour éviter cela, il est possible de séparer le code C# de la vue HTML.
Lorsque nous faisons cette séparation, il devient impossible d’accéder à tout ce qui a été déclaré comme étant privé dans notre fichier de code, alors que c’était possible auparavant. Cela reste une bonne pratique de considérer les membres privés comme étant un détail d’implémentation, et de ce fait, que la vue n’ait accès qu’aux données publiques, comme n’importe quel client de notre code.
Pour pouvoir implémenter cette séparation, il est nécessaire que notre vue (qui est une classe de façon sous-jacente) hérite de la classe qui contient notre code.
Afin de mettre en pratique ce concept, nous allons transformer le composant Counter. La première étape est de créer une classe, que nous allons appeler CounterBase :
using Microsoft.AspNetCore.Components;
public class CounterBase : ComponentBase
{
}
Rien de compliqué ici. On note cependant que cette classe hérite de ComponentBase, qui est la classe de base...
Formulaires et interactions utilisateur
Dans notre exemple précédent, où nous avons un composant parent pour envelopper le composant Counter afin de lui donner une valeur initiale, il a été fait mention d’un attribut HTML sur un champ texte : @bind-value. Cet attribut joue un rôle prépondérant dans les formulaires.
1. Bindings
À l’exception des sites vitrines, toutes les applications web proposent un formulaire de saisie de données. Ce dernier permet à l’utilisateur de saisir des informations et il permet aussi de les envoyer à l’application pour traitement. Ces données vont, de ce fait, être ’’bindées’’, c’est-à-dire qu’on va les lier à un modèle qui permettra la lecture et l’écriture.
Il existe deux modes de binding : le one-way data binding, et le two-way data binding.
a. One-way data binding
Ce mode permet d’indiquer que les données transitent dans un sens, mais pas dans l’autre. Le sens peut être depuis le DOM HTML vers le composant, ou inversement. D’ailleurs, ce mode a déjà été vu dans les deux sens sur le composant Counter. En effet, lorsque l’on affiche une valeur du composant directement dans le code HTML, grâce à l’instruction @, on réalise en fait un one-way data binding du composant vers le DOM :
<p>Current count: @CurrentCount</p>
De la même façon, lorsque l’on affecte un attribut d’un élément DOM vers le composant Razor, on utilise le même type de binding :
<button
class="btn btn-primary"
style="background: @Color"
@onclick="IncrementCount">Click me</button>
@code {
public string Color {get;set;} = "red";
}
Il s’agit du du mode le plus simple, le plus performant et le plus courant. Blazor supporte également l’utilisation d’expression C# pour certains attributs HTML courants, par exemple l’attribut disabled qui permet de désactiver un composant. Si, par exemple, on souhaite que le bouton d’incrément du compteur soit désactivé dès lors que la valeur...
Exercice
Nous allons faire un petit exercice afin d’améliorer la première implémentation de notre application commencée dans le chapitre Première application.
1. Énoncé
En reprenant le code fait précédemment, nous allons réaliser les tâches suivantes :
-
Créer un service permettant de récupérer les informations concernant le personnel. Il est nécessaire de se reposer sur les principes d’injection de dépendances, afin de donner aujourd’hui une implémentation en mémoire et plus tard une implémentation en contactant une API.
-
Créer un composant affichant la liste du personnel ainsi qu’un composant affichant la fiche d’une personne en particulier. Cette fiche est éditable et doit être liée à un modèle de données qui est envoyé sur le service pour une sauvegarde. Faire en sorte également qu’on puisse accéder à la fiche d’une personne si on connaît son id, en passant la valeur par le biais de l’URL.
-
Ajouter les contrôles sur la fiche d’un employé en rendant obligatoires ses informations (exception faite de la date d’anniversaire). Le nom de la rue ne doit pas dépasser 128 caractères et être au minimum de 3 caractères. Le code postal doit être composé de 5 chiffres. Les messages d’erreur doivent être en français.
2. Corrigé
a. Gestion du personnel
La première étape de cet exercice est de créer un service permettant de récupérer les informations concernant le personnel. Comme indiqué dans l’énoncé, la première implémentation est en mémoire, donc la substitution doit être possible. Il faut de ce fait commencer par définir l’interface de contrat permettant de récupérer les informations concernant le personnel depuis une source de données quelconque :
public interface IEmployeeService
{
IAsyncEnumerable<Employee> GetAll();
Task AddOrUpdate(Employee employee);
Task Delete(Employee employee);
}
On constate que cette interface de contrat permet de gérer une source d’employés :...