Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

strange issue when opening jquery dialog for first time (within asp.net gridview)

Tags:

jquery

asp.net

I have a gridview inside an updatepanel. One of the fields in the gridview is an ASP.net linkbutton like so:

 <ItemTemplate>
       <asp:LinkButton ID="hlSortOrder" runat="server" CssClass="hlDialog" OnClick="LoadLog"
        Text='<%# DataBinder.Eval(Container, "DataItem.SortOrder") %>'></asp:LinkButton>
  </ItemTemplate>

When someone clicks the linkbutton I call the OnClick method that I created called LoadLog. LoadLog looks like this:

protected void LoadLog(object sender, EventArgs e)
        {
            GridViewRow gr = (GridViewRow)((DataControlFieldCell)((LinkButton)sender).Parent).Parent;
            Label l = (Label)gr.FindControl("lblID");
            DataSet ds;

            ds = BL.GetRunoffAnswerLog(Convert.ToInt64(l.Text));

            if (ds != null)
            {
                if (ds.Tables[0].Rows.Count == 0)
                {
                    gvLog.Visible = false;
                    gvLog.DataSource = null;
                    lblRowsCount.Text = "No log for this record!";
                }
                else
                {
                    lblRowsCount.Text = ds.Tables[0].Rows.Count.ToString() + " row(s) found for this record.";
                    gvLog.DataSource = ds.Tables[0];
                    gvLog.DataBind();
                    gvLog.Visible = true;
                }
            }
            ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "openDialog", "$('#dialog').dialog({draggable: true, modal: true, height: 500, width: 750, title: 'Log', open: function (type, data) {$(this).parent().appendTo('form');}});", true);
        }

Basically it gets a handle of the grid view row, pulls some data back from the database and assigns it to the gvLog source. After that notice the line at the end:

ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "openDialog", "$('#dialog').dialog({draggable: true, modal: true, height: 500, width: 750, title: 'Log', open: function (type, data) {$(this).parent().appendTo('form');}});", true);

I have to do this so that I can open up my dialog box. When I click a row in my gridview ONLY the first time I get this:

enter image description here

Notice it only really shows the title...weird. But once I click that same row again it shows the entire dialog:

enter image description here

It only happens on the first click, if I keep clicking different rows it works fine. I should add that I had to add the following jquery code:

 <script type="text/javascript">
        $(document).ready(function () {
            var prm = Sys.WebForms.PageRequestManager.getInstance();

            prm.add_endRequest(function () {
                $("#dialog").hide();
                // re-bind your jQuery events here 
           });
        ....more code...

Based on this discussion: jQuery $(document).ready and UpdatePanels?

If I do not have that code the minute a post back happens the entire div that this dialog is inside always gets shown on my page and I dont want that...

As one of the members below has mentioned. I believe what is happening is the first time you click the linkbutton the client side event is happening first which is opening the actual open dialog, even though I raise this event in server side code...as you see above only when you click the "LoadLog" event click do I register this jquery opendialog. But it appears that this still opens the dialog the first time and once you click it the second time only then is the data shown.

like image 716
oJM86o Avatar asked Jun 27 '12 14:06

oJM86o


1 Answers

I have had a lot of issues with jQuery awesomeness and UpdatePanels. Try this approach:

  1. Place the div that you are using for your dialog outside of your update panel. Don't create your dialog in code behind. Instead create your dialog on page load. Since your dialog is outside the updatepanel it won't get clobbered. Make sure to not auto-open it.
  2. Add an additional div to your dialog div to hold your content.
  3. Create a javascript function that
    • clears the contents of the content div in your dialog of any previous content
    • appends the gvLog control to the dialog content div, something like $('#dialogContent').append($('#<%= gvLog.ClientID %>'));
    • shows the dialog
  4. Now in your code behind tweak the RegisterClientScriptBlock to call this new javascript function.

Example Code
Code Behind:

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            //load in some dummy data
            Dictionary<int, string> vals = new Dictionary<int, string>()
            {
                {1, "ONE"},
                {2, "TWO"},
                {3, "THREE"},
                {4, "FOUR"},
                {5, "FIVE"},
                {6, "SIX"}
            };

            gvData.DataSource = vals;
            gvData.DataBind();
        }
    }

    protected void LoadLog(object sender, EventArgs e)
    {
        LinkButton lb = (LinkButton)sender;
        var key = lb.CommandArgument;

        Random r = new Random();
        Dictionary<int, int> dict = new Dictionary<int, int>();

        for (int i = 0; i <= r.Next(5, 20); i++)
        {
            dict.Add(r.Next(), r.Next());
        }

        gvLog.DataSource = dict;
        gvLog.DataBind();

        //show log in dialog on client
        ScriptManager.RegisterStartupScript(up, up.GetType(), "openDialog", "showLog();", true);
    }
}

Designer Code:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>
    <script src="Scripts/jquery-ui-1.8.21.custom.min.js" type="text/javascript"></script>
    <link href="ui-lightness/jquery-ui-1.8.21.custom.css" rel="stylesheet" type="text/css" />

    <script type="text/javascript">
        $(function () { 
            //setup dialog
            $('#dialog').dialog({draggable: true, 
                                modal: true, 
                                height: 500, 
                                width: 750, 
                                title: 'Log',
                                autoOpen: false});
        });

        function showLog() {
            //clear any old log data
            $('#dvContent').empty();
            //append current log
            $('#<%= gvLog.ClientID %>').appendTo($('#dvContent'));
            //show dialog
            $('#dialog').dialog('open');
        }
    </script>
</head>

<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="sp" runat="server" />
    <div>
        <asp:UpdatePanel ID="up" runat="server">
            <ContentTemplate>
                <asp:GridView ID="gvData" runat="server">
                    <Columns>
                        <asp:TemplateField>
                            <ItemTemplate>
                                <asp:LinkButton ID="lbShowLog" runat="server" Text="Show Log" 
                                    OnClick="LoadLog" CommandArgument='<%# Eval("Key") %>' />
                            </ItemTemplate>
                        </asp:TemplateField>
                    </Columns>
                </asp:GridView>

                <div style="display:none;">
                    <asp:GridView ID="gvLog" runat="server">
                    </asp:GridView>
                </div>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>

    <div id="dialog" style="display:none;">
        <div id="dvContent">

        </div>
    </div>
    </form>
</body>
</html>
like image 190
Peter Avatar answered Oct 12 '22 23:10

Peter