Search code examples
c#asp.netwebformsbootstrap-5bootstrap-toast

ASPX webform Bootstrap toast Auto hide not working in updatepanel


All I am using Bootstrap Toast to display alert messages. But the issue I am getting is to hide them automatically.

I tried with and without data-bs-autohide="true" data-bs-delay="3000" but no success.

The tricky part is I am creating this toast in Code behind and appending it to the aspx page control.

I tried static code in HTML, but it still did not work.

I believe it's due to asp:UpdatePanel

Here is my code.

How can I make it auto hide?

page.aspx

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <div class="container body-content pt-3 mb-3">

        <asp:UpdatePanel ID="UpdatePanel4" runat="server" UpdateMode="Conditional">
            <ContentTemplate>
                <div class="col-md-12">
                    <div runat="server" id="alertParent" class="toast-container position-fixed top-0 end-0 p-3">
                    </div>
 <asp:Button ID="Button1" CssClass="btn btn-primary" CausesValidation="false" OnClick="Button1_Click" runat="server" Text="Show" />
                </div>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
</asp:Content>

page.aspx.cs

protected void ShowAlertMessage(string tstr, string Header = "")
{
    try
    {
        //Header = string.IsNullOrEmpty(Header) ? "Error" : Header;

        alertParent.Visible = true;
        alertParent.Style.Add("z-index", "3");

        var div = new HtmlGenericControl("div");                
        div.Attributes["role"] = "alert";
        div.Attributes["aria-live"] = "assertive";
        div.Attributes["aria-atomic"] = "true";
        div.Attributes["data-bs-autohide"] = "true";
        div.Attributes["data-bs-delay"] = "3000";

        var Child_div = new HtmlGenericControl("div");
        Child_div.Attributes["class"] = "toast-header";

        var Sub_Child_1 = new HtmlGenericControl("strong");
        Sub_Child_1.Attributes["class"] = "me-auto";
        Sub_Child_1.InnerHtml = Header;

        var Sub_Child_2 = new HtmlGenericControl("span");
        //Sub_Child_2.Attributes["type"] = "button";
        Sub_Child_2.Attributes["class"] = "btn-close";
        Sub_Child_2.Attributes["data-bs-dismiss"] = "toast";
        Sub_Child_2.Attributes["aria-label"] = "Close";

        Child_div.Controls.Add(Sub_Child_1);
        Child_div.Controls.Add(Sub_Child_2);

        var Child_div_2 = new HtmlGenericControl("div");
        Child_div_2.Attributes["class"] = "toast-body";

        div.Controls.Add(Child_div);
        div.Controls.Add(Child_div_2);

        string sFlag, smessage;
        if (tstr.Length == 0)
            return;

        string[] words = tstr.Split('_');
        sFlag = words[0];
        smessage = words[1];
        switch (sFlag)
        {
            case "warning":
                {
                    div.Attributes["class"] = "toast fade  text-bg-warning";
                    Child_div_2.InnerHtml = smessage;
                    break;
                }

            case "danger":
                {// REM error
                    div.Attributes["class"] = "toast fade text-bg-danger";
                    Child_div_2.InnerHtml = smessage;
                    break;
                }

            case "success":
                {// REM error
                    div.Attributes["class"] = "toast fade text-bg-success";
                    Child_div_2.InnerHtml = smessage;
                    break;
                }

            case "primary":
                {// REM error
                    div.Attributes["class"] = "toast fade text-bg-primary";
                    Child_div_2.InnerHtml = smessage;
                    break;
                }

            case "info":
                {// REM error
                    div.Attributes["class"] = "toast fade text-bg-info";
                    Child_div_2.InnerHtml = smessage;
                    break;
                }

            default:
                {
                    div.Attributes["class"] = "toast fade hide text-bg-info";
                    Child_div_2.InnerHtml = "";
                    alertParent.Visible = false;
                    alertParent.Style.Add("z-index", "-1");
                    break;
                }
        }
        alertParent.Controls.Add(div);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

protected void Button1_Click(object sender, EventArgs e)
{
    ShowAlertMessage("success_My Message is here.");
}


Solution

  • Bootstrap Toasts must first be initialized

    As noted in the Bootstrap 5 documentation, "Toasts are opt-in for performance reasons, so you must initialize them yourself."

    To initialize the new Toast from the ASPX C# code behind we can add an ID and use ScriptManager to call Bootstrap methods. We need to both initialized the Toast and show it for the autohide to work.

    C# Code

    div.ID = "toast-1";
    var script = $"bootstrap.Toast.getOrCreateInstance(document.getElementById('{div.ID}')).show();";
    ScriptManager.RegisterStartupScript(this.Page, Page.GetType(), "text", script, true);
    

    Complete Demo

    The demo has been tested in Visual Studio. Clicking the button creates a new Toast component as in the original. However, it then uses ScriptManager to initialize and show the Toast. The Toast displays for 3 seconds and then automatically hides.

    // C# code Page.aspx.cs 
    
    using System;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    
    public partial class Page : System.Web.UI.Page
    {
        protected void ShowAlertMessage(string tstr, string Header = "")
        {
            try
            {
                alertParent.Visible = true;
                alertParent.Style.Add("z-index", "3");
    
                var div = new HtmlGenericControl("div");
                div.Attributes["role"] = "alert";
                div.Attributes["aria-live"] = "assertive";
                div.Attributes["aria-atomic"] = "true";
                div.Attributes["data-bs-autohide"] = "true";
                div.Attributes["data-bs-delay"] = "3000";
    
                var Child_div = new HtmlGenericControl("div");
                Child_div.Attributes["class"] = "toast-header";
    
                var Sub_Child_1 = new HtmlGenericControl("strong");
                Sub_Child_1.Attributes["class"] = "me-auto";
                Sub_Child_1.InnerHtml = Header;
    
                var Sub_Child_2 = new HtmlGenericControl("span");
                //Sub_Child_2.Attributes["type"] = "button";
                Sub_Child_2.Attributes["class"] = "btn-close";
                Sub_Child_2.Attributes["data-bs-dismiss"] = "toast";
                Sub_Child_2.Attributes["aria-label"] = "Close";
    
                Child_div.Controls.Add(Sub_Child_1);
                Child_div.Controls.Add(Sub_Child_2);
    
                var Child_div_2 = new HtmlGenericControl("div");
                Child_div_2.Attributes["class"] = "toast-body";
    
                div.Controls.Add(Child_div);
                div.Controls.Add(Child_div_2);
    
                string sFlag, smessage;
                if (tstr.Length == 0)
                    return;
    
                string[] words = tstr.Split('_');
                sFlag = words[0];
                smessage = words[1];
                switch (sFlag)
                {
                    case "warning":
                        {
                            div.Attributes["class"] = "toast fade text-bg-warning";
                            Child_div_2.InnerHtml = smessage;
                            break;
                        }
    
                    case "danger":
                        {// REM error
                            div.Attributes["class"] = "toast fade text-bg-danger";
                            Child_div_2.InnerHtml = smessage;
                            break;
                        }
    
                    case "success":
                        {// REM error
                            div.Attributes["class"] = "toast fade text-bg-success";
                            Child_div_2.InnerHtml = smessage;
                            break;
                        }
    
                    case "primary":
                        {// REM error
                            div.Attributes["class"] = "toast fade text-bg-primary";
                            Child_div_2.InnerHtml = smessage;
                            break;
                        }
    
                    case "info":
                        {// REM error
                            div.Attributes["class"] = "toast fade text-bg-info";
                            Child_div_2.InnerHtml = smessage;
                            break;
                        }
    
                    default:
                        {
                            div.Attributes["class"] = "toast fade hide text-bg-info";
                            Child_div_2.InnerHtml = "";
                            alertParent.Visible = false;
                            alertParent.Style.Add("z-index", "-1");
                            break;
                        }
                }
                alertParent.Controls.Add(div);
    
                // NEW CODE 
                div.ID = "toast-1";
                var script = $"bootstrap.Toast.getOrCreateInstance(document.getElementById('{div.ID}')).show();";
                ScriptManager.RegisterStartupScript(this.Page, Page.GetType(), "text", script, true);
    
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    
        protected void Button1_Click(object sender, EventArgs e)
        {
            ShowAlertMessage("success_My Message is here.");
        }
    }
    
    <!-- Page.aspx -->
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Page.aspx.cs" Inherits="Page" %>
    
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
    <head runat="server">
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>Demo</title>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" />
    </head>
    <body>
        <form id="aspNet" runat="server">
            <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
            <div class="container body-content pt-3 mb-3">
                <asp:UpdatePanel ID="UpdatePanel4" runat="server" UpdateMode="Conditional">
                    <ContentTemplate>
                        <div class="col-md-12">
                            <div runat="server" id="alertParent" class="toast-container position-fixed top-0 end-0 p-3">
                            </div>
                            <asp:Button ID="Button1" CssClass="btn btn-primary" CausesValidation="false" OnClick="Button1_Click" runat="server" Text="Show" />
                        </div>
                    </ContentTemplate>
                </asp:UpdatePanel>
            </div>
        </form>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
    </body>
    </html>