Comment créer un message de chargement en ASP.Net ?

Vous avez déjà probablement fait face à ce problème : un simple composant Button, un traitement long attaché au bouton, un utilisateur impatient qui clique plusieurs fois sur ce même bouton… et là, c’est le drame : les données produites par le traitement sont créées plusieurs fois, les relations en base de données deviennent incohérentes, le site plante de toutes parts…

Heureusement, il a plusieurs moyens de remédier à ce problème, dont cette petite technique que je vous présente, qui consiste à cacher un bouton (ou le bloc qui le contient) lorsque l’on clique dessus, et à le remplacer par une animation de chargement. Elle est plutôt rapide à mettre en œuvre et se base en partie sur du JavaScript.

Du côté de la page ASPX

Sur la page ASPX concernée (ou sur un User Control), vous aurez besoin de trois choses :

  • Un élément simple capable d’accueillir le JavaScript (en général, un <ASP:Litteral>). C.f exemple plus bas : ID=ltlHiddenJavascript.
  • Un bloc contenant le bouton (une <div> avec un <ASP:Button> et un message de résultat par exemple, ou simplement un <ASP:Button>). C.f exemple plus bas : ID=divTraitement.
  • Un bloc contenant le message d’attente et une animation GIF, par exemple. C.f exemple plus bas : ID=divPleaseWait.
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
   <! Hôte du JavaScript >
   <asp:Literal ID="ltlHiddenJavascript" runat="server"></asp:Literal>
   <! Bloc contenant le bouton >
   <div ID="divTraitement" runat="server">
       <asp:Button ID="btnTraitement" runat="server" Text="Lancer le traitement" OnClick="btnTraitement_Click"
           OnClientClick="jsHideButton(true)" />
       <br />
       <br />
       <div>
           <asp:Label ID="lblResult" runat="server"></asp:Label>
       </div>
   </div>
   <! Bloc contenant le message d’attente >
   <div id="divPleaseWait" runat="server" style="display: none;">
       <! Image générée grâce à http://www.ajaxload.info/ : >
       <img src="img/loading.gif" alt="Merci de patienter..." />
       <p>
           Merci de bien vouloir patienter...
       </p>
   </div>
</asp:Content>

Le bouton possède notamment l’attribut (et la valeur) suivant : OnClientClick="jsHideButton(true)". C’est le nom de la fonction JavaScript qui va permettre de cacher le bouton et d’afficher l’animation

Concernant le bloc dédié au « message d’attente », je vous conseille de regarder ce site : http://www.ajaxload.info

Il permet de générer des images animées (au format GIF) sympathiques, aux couleurs de votre site, sans pour autant que celui-ci adopte un style Web des années 2000.

Du côté du code-behind

Côté code-behind, vous devez :

  • Insérer le code JavaScript « à la volée », c’est-à-dire au moment de l’évènement Page_Load ;
  • Effectuer le traitement long au moment de l’évènement OnClick du bouton (c’est l’origine du problème qui nous amène ici).

En ce qui concerne ce premier point, il faut en effet insérer le code JavaScript « à la volée », puisque ce dernier a besoin de l’ID Client des composants. Or, l’ID Client des composants ASP.Net n’est connu qu’une fois la page initialisée (sauf pour les dernières versions du Framework .Net où l’ID Client peut être forcé côté ASPX). On passe donc l’ID Client côté code-behind, une fois que celui-ci ait été généré.

   public partial class _Default : System.Web.UI.Page
   {
       protected void Page_Load(object sender, EventArgs e)
       {
           // Insertion du code JavaScript
           ltlHiddenJavascript.Text = JScriptHelper.HideButton(divTraitement.ClientID, divPleaseWait.ClientID);
       }
       protected void btnTraitement_Click(object sender, EventArgs e)
       {
           // Votre traitement "long" ; Ici, on fait patienter 3 secondes
           System.Threading.Thread.Sleep(3000);
           lblResult.Text = "Traitement terminé !";
       }
   }

Une fonction « outil » pour clarifier le code

Dans le chapitre précédent, vous avez pu noter la présence de la fonction suivante :

JScriptHelper.HideButton(divTraitement.ClientID, divPleaseWait.ClientID);

C’est une petite méthode « static » qui permet d’éclaircir le code :

   public static class JScriptHelper
   {
       /// <summary>
       /// Retourne le code JavaScript qui permet de cacher 
       /// le bouton après un clic et de faire apparaître une 
       /// animation de chargement. Evite ainsi les clics
       /// multiples et les enregistrements erronés.
       /// </summary>
       /// <param name="strIdButton">id du bouton (ou de la div)
       /// à cacher</param>
       /// <param name="strIdImage">id de la div (contenant 
       /// une animation, du texte, etc.) à afficher 
       /// en attendant</param>
       /// <returns>Le code JavaScript à insérer dans 
       /// un élément HTML (ex.: <asp:Literal>)</returns>
       public static string HideButton(string strIdButton,
           string strIdPleaseWait)
       {
           return String.Format(@"
<script type=""text/javascript"">
function jsHideButton(pSwitch) {{
   if (pSwitch) {{
       /* On cache le bouton */
       document.getElementById('{0}').style.display = ""none"";
       document.getElementById('{1}').style.display = ""block"";
   }}
   else {{
       /* On montre le bouton */
       document.getElementById('{0}').style.display = ""block"";
       document.getElementById('{1}').style.display = ""none"";
   }}
}};
</script>",
             strIdButton, strIdPleaseWait);
       }
   }

Attention au String.Format() et aux accolades ! En effet, en JavaScript, on trouve forcément ces caractères (‘{‘ et ‘}’). Or, ils sont utilisés par la fonction String.Format() pour représenter les chaînes à insérer : on doit donc les échapper en les doublant. Bref, dans notre cas, il faut doubler les accolades utilisées par la syntaxe du JavaScript.

Pour en revenir au code JavaScript en lui-même, son fonctionnement est simple : il change le style CSS des éléments concernés. « Display: none » pour les cacher, « Display: block » pour les afficher.

Démo

Un petit projet de démonstration est attaché à ce billet : ici

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.