Fermer

novembre 18, 2021

Gestion d'un composant parent dans Blazor


Comment un composant enfant dans une TelerikWindow ferme-t-il la fenêtre lorsque l'utilisateur a terminé avec le dialogue ?

Une conversation intéressante sur l'un de mes articles précédents à propos de Telerik UI pour Blazor m'a fait réfléchir à la façon dont un composant imbriqué dans une fenêtre Telerik peut contrôler la fenêtre (ou tout composant parent) qui l'utilise. Alors que l'équipe Telerik Blazor a immédiatement pris en compte les commentaires des clients et travaille déjà sur le composant Dialog, pour cette étude de cas, je m'en tiendrai au scénario d'origine : comment un composant enfant dans une TelerikWindow ferme-t-il la fenêtre lorsque l'utilisateur est-ce que le dialogue est terminé?

J'ai trois solutions mais elles ne sont pas aussi astucieuses que celle suggérée sur mon précédent article de blog. Mais cela me permet également de parler d'une meilleure pratique lors de la création de composants : ce sont les outils que vous devriez utiliser pour informer vos composants parents lorsque quelque chose se produit à l'intérieur de votre composant. Et faire savoir à vos parents potentiels ce que vous faites est une bonne chose.

Avant de commencer (et tant que nous parlons de la création de boîtes de dialogue), n'ignorez pas les Boîtes de dialogue prédéfinies Telerik . Si vous créez une boîte de dialogue personnalisée avec le composant TelerikWindow pour fournir des informations (une boîte de dialogue d'alerte), obtenir l'approbation d'une action (une boîte de dialogue de confirmation) ou accepter une chaîne (une boîte de dialogue d'invite) de l'utilisateur… t besoin de créer cette boîte de dialogue personnalisée. Les boîtes de dialogue prédéfinies facilitent ces tâches courantes.

Mais disons que vous avez une interface utilisateur plus intéressante dans votre boîte de dialogue que la prise en charge des boîtes de dialogue prédéfinies.

Intégration des contrôles

Je vais commencer par le cas le plus simple. : Vous disposez d'une boîte de dialogue composée d'un ou plusieurs composants et d'un bouton qui déclenche le traitement. Lorsque l'utilisateur clique sur le bouton, vous souhaitez que la boîte de dialogue disparaisse. Le moyen le plus simple de gérer cela est de lier la propriété Visible de TelerikWindow à une variable de niveau classe (un champ) et, dans le code attaché au bouton, de définir ce champ sur false.

Cette solution ressemble à ceci :[19659009]<TelerikWindow Visible="@windowVisible">
<WindowContent>
…autres composants…
<TelerikButton OnClick="Process">Terminer</TelerikButton>
< /WindowContent>
</TelerikWindow>

@code {
bool windowVisible = true;

private void FermerWindow()
{
windowVisible = false;
}

Intégration des composants

Mais que se passe-t-il si vous souhaitez que votre boîte de dialogue se ferme à cause de quelque chose qui se passe à l'intérieur de l'une des boîtes de dialogue Composants? Que se passe-t-il si, par exemple, votre boîte de dialogue ressemble à ceci et que vous souhaitez que la fenêtre se ferme parce que l'utilisateur a fait quelque chose à l'intérieur du composant DoSomething :

<TelerikWindow>    
   <WindowContent >
     <Faire quelque chose></Faire quelque chose>
  </WindowContent> ]<TelerikWIndow>

Si vous avez de la chance, le composant DoSomething expose un événement ou une propriété que vous pouvez utiliser pour contrôler votre fenêtre. Et c'est super… mais comment y arriver si c'est vous qui créez le composant DoSomething ? La solution la plus simple est la solution typique : si le composant enfant ne se soucie pas de ce qui se passe dans le composant parent, tout ce dont vous avez besoin est une liaison d'événement unidirectionnelle.

Pour cette solution, le composant DoSomething doit simplement déclarer une propriété en tant qu'EventCallback, marquez-le en tant que paramètre et appelez la méthode InvokeAsync de EventCallback lorsque le composant souhaite informer son parent que quelque chose s'est produit (et, éventuellement, transmettre des données). Si votre événement renvoie des données, vous devez spécifier le type de données que vous renvoyez dans le cadre de la déclaration de EventCallback.

Voici le code pour créer un composant DoSomething qui notifie son parent lorsque l'utilisateur clique sur le bouton du composant en déclenchant un événement ProcessingCompleted et en transmettant une valeur booléenne :

…autres composants…
<TelerikButton OnClick="@DoProcessing">Terminer</TelerikButton>

@code {
    [Parameter]
    public EventCallback<bool> Traitement terminé { get ; set; }

    private async Tâche DoProcessing()
    {
        …code de traitement…
        wait ProcessingCompleted.InvokeAsync(false);
    }
}

Le composant parent a maintenant un choix . Si tout ce que le composant parent veut faire est de réagir à l'événement et d'exécuter une méthode, cet exemple définit mon champ windowVisible lorsque le composant déclenche son événement ProcessingCompleted :

<TelerikWindow Visible="@ windowVisible">    
   <WindowContent>
      …autres composants…
      <DoSomething ProcessingCompleted="@CloseWindow"></DoSomething>
   </[1945904] ]WindowContent>
</TelerikWindow>

@code {
   bool windowVisible = true;

   private void FermerWindow()
   { 
      windowVisible = false;
   }
}

Si le parent veut réellement utiliser les données transmises par l'événement, le code n'est que légèrement plus compliqué. Vous devez utiliser une expression lambda lors de la capture de l'événement et la méthode utilisée dans l'expression lambda doit accepter les données transmises par l'événement.

Voici un code qui utilise la valeur transmise par l'événement déclenché dans l'enfant pour définir le Champ windowVisible :

<TelerikWindow Visible="@windowVisible">    
   <WindowContent>
      …autres composants…
      <DoSomething ProcessingCompleted="@(p => CloseWindow(p))"></DoSomething>[19659080]</WindowContent>
</TelerikWindow>

@code {
    bool windowVisible = true;

    private void FermerWindow(bool fermer )
    {
        windowVisible = close;
    }
}

Ainsi, en ajoutant un EventCallback à votre composant, vous pouvez informer tout parent qui utilise votre composant que quelque chose d'intéressant s'est produit dans votre composant. Bien sûr, ce que le composant parent fait avec ces informations appartient au parent (dans ce cas : fermer la fenêtre). informations avec votre composant.

Par exemple, vous pouvez ne pas vouloir que votre composant enfant DoSomething déclenche son événement si, par exemple, la fenêtre est déjà fermée. Je reconnais que je n'ai pas un bon exemple dans cette étude de cas, pour deux raisons. Premièrement, il n'y a aucun mal à fermer une fenêtre déjà fermée, alors pourquoi s'embêter à vérifier ? Deuxièmement, comment quelqu'un cliquerait-il exactement sur le bouton d'un composant à l'intérieur d'une fenêtre fermée ? Cependant, c'est le scénario que j'ai, et vous pouvez probablement en imaginer un meilleur que celui que j'ai utilisé ici.

Pour que le parent partage des informations avec l'enfant le composant DoSomething, vous devez ajouter un événement bidirectionnel liaison à l'intérieur de votre composant. Pour implémenter la liaison de données bidirectionnelle, vous avez besoin de deux paramètres dans votre composant. Un paramètre contient les données que vous souhaitez partager (je l'appellerai le paramètre de données). L'autre paramètre est juste un EventCallback comme nous l'avons vu auparavant (j'appellerai ce paramètre le paramètre d'événement). Les deux paramètres sont liés par leur nom : l'EventCallback doit s'appeler Changed.

Maintenant, dans le code de votre composant DoSomething, vous pouvez vérifier la valeur du paramètre de données et déclencher votre événement . Voici un exemple avec un paramètre de données appelé windowState et un paramètre d'événement correspondant appelé windowStateChanged. Dans le code de mon bouton, je ne déclenche l'événement que si l'état de la fenêtre indique que la fenêtre est ouverte :

<TelerikWindow Visible="@windowVisible">    
   <Contenu de la fenêtre>
      …autres composants…
      <TelerikButton OnClick="@DoProcessing">Terminer</TelerikButton>< ]/WindowContent>
</TelerikWindow>

@code {
   [Parameter]
   public bool windowState { get; set;  }
   [Parameter]
   public EventCallback<bool> windowStateChanged { get[19659022]; set; } 

    private async Tâche DoProcessing()
    {
        …code de traitement…
        Si (windowState)
       {
          await windowStateChanged.InvokeAsync(false[196590222])InvokeAsync(false[196590222])[196590];
       }
    }
}

Le gain est que vous n'avez pas besoin d'écrire une méthode dans le composant parent pour définir le champ windowVisible : vous pouvez lier l'événement directement au champ. Par conséquent, le balisage requis est différent de celui que vous utilisez avec la liaison unidirectionnelle. Avec la liaison bidirectionnelle, le composant DoSomething utilise le nom du paramètre de données (préfixé par @bind-) et se lie directement au champ que vous partagez entre les composants. Le paramètre d'événement garantit que le champ du parent est mis à jour chaque fois que l'événement est déclenché dans le composant DoSomething.

Cet exemple associe le paramètre windowState de DoSomething au champ windowVisible du composant parent :

<TelerikWindow Visible="@windowVisible">    
   <WindowContent>
      …autres composants…
      <DoSomething @bind-windowState="windowVisible"></DoSomething> ]</WindowContent>
</TelerikWindow>

@code {
   bool windowVisible;

Mais la vraie morale de cet article est que, lorsque vous écrivez un composant, c'est toujours une bonne idée de déclencher des événements lorsque quelque chose change à l'intérieur de votre composant. Vous pouvez le faire avec une liaison de données unidirectionnelle ou bidirectionnelle, mais, dans les deux cas, le déclenchement d'événements permet à votre parent d'intégrer ce qu'il fait avec ce que fait votre composant.




Source link