Dynamic RadDock interaction with Grid / AJAX-enabled Context Menu

6 posts, 0 answers
  1. Andy
    Andy avatar
    6 posts
    Member since:
    Aug 2009

    Posted 09 Nov 2009 Link to this post

    I have created a dynamic  dashboard for my application using code from the following two examples:


    I have modified the My Portal example to fit our data structure, but the way that user-controls are dynamically added into RadDocks to create "widgets" is the same as the My Portal example.  My problem is that about half of my user-controls are using the Grid context menu technique mentioned above.  When one of these user-control/dock objects gets added to the page I get the following JS error which is puzzling to me.  

    Message: Sys.WebForms.PageRequestManagerServerErrorException: An unknown error occurred while processing the request on the server. The status code returned from the server was: 500 
    Line: 6 
    Char: 62099 
    Code: 0 
    URI: http://localhost:53177/Website/Telerik.Web.UI.WebResource.axd?_TSM_HiddenField_=ctl00_ScriptManagerMain_HiddenField&compress=1&_TSM_CombinedScripts_=%3b%3bSystem.Web.Extensions%2c+Version%3d3.5.0.0%2c+Culture%3dneutral%2c+PublicKeyToken%3d31bf3856ad364e35%3aen-US%3ad0c4ca6e-6b5d-49b6-922d-5244924fb100%3aea597d4b%3ab25378d2 

    My guess to as what is happening is that the RowContextMenu function has not been loaded at the time the Grid is looking for it.  I am not using a RadAjaxManager on this page, only an asp:updatepanel with the button that adds the dock set as an AsyncPostBackTrigger.

    How can I get this two great code samples to cooperate with each other? Please let me know if more information is needed.  

    Thanks, Andy

    Edit:  I should also add that this also occurs on a separate page where a user-control that is being loaded dynamically and contains a  RadGrid and is using the RowContextMenu code.

    There error I get here is more helpful in deciphering the issue but I do not know how to go about fixing it still:

    Message: 'PersonToDoRowContextMenu' is undefined 
    Line: 204658269 
    Char: 5 
    Code: 0 
    URI: http://localhost:53177/Website/Contacts/Contacts.aspx 
     

    This seems to back up my guessing that the JS is not added when the grid looks for it.
  2. Pero
    Admin
    Pero avatar
    1156 posts

    Posted 12 Nov 2009 Link to this post

    Hello Andy,

    Indeed this is the problem causing the JavaScript exception - the RadGrid cannot find the client-side event handler of the OnRowContextMenu client-side event. To solve this problem you can put  the method in the <head> tag of the .aspx where the UserControl is dynamically added. The only problem that arises is how to find the client-side object of the RadMenu of the corresponding RadGrid.

    Here is how I implemented this method. I am finding the ClientId of the Menu with the help of the RadGrid's ClientId (which in our case is the sender of the event).

    <head runat="server">
     
        <script type="text/javascript">
            function RowContextMenu(sender, eventArgs)
            {
                var senderID = sender.get_id();
                var menuID = senderID.substring(0, senderID.lastIndexOf('_')) + "_RadMenu1";
                var menu = $find(menuID);
                var evt = eventArgs.get_domEvent();
     
                if (evt.target.tagName == "INPUT" || evt.target.tagName == "A")
                {
                    return;
                }
     
                var index = eventArgs.get_itemIndexHierarchical();
                document.getElementById("radGridClickedRowIndex").value = index;
     
                sender.get_masterTableView().selectItem(sender.get_masterTableView().get_dataItems()[index].get_element(), true);
     
                menu.show(evt);
     
                evt.cancelBubble = true;
                evt.returnValue = false;
     
                if (evt.stopPropagation)
                {
                    evt.stopPropagation();
                    evt.preventDefault();
                }
            }
        </script>
     
    </head>


    Do not hesitate to contact us, If you have other problems or questions.


    Sincerely yours,
    Pero
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Andy
    Andy avatar
    6 posts
    Member since:
    Aug 2009

    Posted 12 Nov 2009 Link to this post

    Thanks for your response Pero.  Moving the context menu javascript to the page head of the aspx page is easier said than done.

    First,  I have a master page where the page header is.  Here is the hierarchy of everything in question.

    • FrameworkMaster.master (RadScriptManager)
    • Dashboard.aspx (RadAjaxManager, RadDockLayout, RadDockZone, RadDock ( UserControl )) 
    • UserControl.ascx (RadGrid w/ ContextMenu and RadScriptBlock containing script for ContextMenuRowIndex)

    Secondly, I need the javascript to load only if the dynamic user control has been loaded.  I would like to limit the amount of javascript I need to call upon. If the user only wants only one or two of the dynamic user controls loaded I don't want to have to write all of the javascript to support the dozen or so user controls that the user has the option of adding.

    Is there any way around this?  Can I do something with the RadScriptManager I have on my masterpage? Possibly register the context menu script with the ScriptManager on the master page in the page load of the user control?

    Thanks, Andy

    (Edited for spelling and further clarity)
  5. Pero
    Admin
    Pero avatar
    1156 posts

    Posted 17 Nov 2009 Link to this post

    Hi Andy,

    Another way of course is dynamically loading the client-script from the server with the ScriptManager.RegisterStartupScript method. Here is how I registered the client-script from the server:

    protected void Page_Load(object sender, EventArgs e)
    {
        string menuScript = "function RowContextMenu(sender, eventArgs)" +
    "{" +
        "var senderID = sender.get_id();" +
        "var menuID = senderID.substring(0, senderID.lastIndexOf('_')) + '_RadMenu1';" +
        "var menu = $find(menuID);" +
        "var evt = eventArgs.get_domEvent();" +
     
        "if (evt.target.tagName == 'INPUT' || evt.target.tagName == 'A')" +
        "{" +
            "return;" +
        "}" +
     
        "var index = eventArgs.get_itemIndexHierarchical();" +
        "document.getElementById('radGridClickedRowIndex').value = index;" +
     
        "sender.get_masterTableView().selectItem(sender.get_masterTableView().get_dataItems()[index].get_element(), true);" +
     
        "menu.show(evt);" +
     
        "evt.cancelBubble = true;" +
        "evt.returnValue = false;" +
     
        "if (evt.stopPropagation)" +
        "{" +
            "evt.stopPropagation();" +
            "evt.preventDefault();" +
        "}" +
    "}";
        ScriptManager.RegisterStartupScript(Page, Page.GetType(), "menuHandler", menuScript, true);
    }

    And here is the full source code of the .ascx file (with the CodeBehind) that contains the RadGrid:

    .ascx
    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="Grid.ascx.cs" Inherits="Dock_Common_Grid" %>
    <%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
    <%@ Register TagPrefix="sds" Namespace="Telerik.Web.SessionDS" %>
    <input type="hidden" id="radGridClickedRowIndex" name="radGridClickedRowIndex" value="1" />
    <p>
        Right-click the grid to open context menu.</p>
    <div style="margin-right: 20px;">
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <telerik:RadGrid ID="RadGrid1" runat="server" Width="100%" DataSourceID="SessionDataSource1"
                    AllowAutomaticDeletes="true" AllowAutomaticInserts="true" AllowAutomaticUpdates="true"
                    OnPreRender="RadGrid1_PreRender">
                    <MasterTableView AllowSorting="False" PageSize="10" AllowPaging="True" Width="100%"
                        DataKeyNames="ProductID" DataSourceID="SessionDataSource1" EditMode="InPlace">
                        <Columns>
                            <telerik:GridEditCommandColumn UniqueName="EditCommandColumn" Visible="false" />
                        </Columns>
                    </MasterTableView>
                    <ClientSettings>
                        <ClientEvents OnRowContextMenu="RowContextMenu"></ClientEvents>
                        <Selecting AllowRowSelect="true" />
                    </ClientSettings>
                    <PagerStyle Mode="NextPrevAndNumeric" />
                </telerik:RadGrid>
                <telerik:RadContextMenu ID="RadMenu1" runat="server" OnItemClick="RadMenu1_ItemClick">
                    <Items>
                        <telerik:RadMenuItem Text="Add" />
                        <telerik:RadMenuItem Text="Edit" />
                        <telerik:RadMenuItem Text="Delete" />
                    </Items>
                </telerik:RadContextMenu>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
    <br />
    <sds:SessionDataSource ID="SessionDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
        SelectCommand="SELECT ProductID, ProductName,UnitPrice, UnitsInStock FROM [Products]"
        DeleteCommand="DELETE FROM [Products] WHERE [ProductID] = ?" InsertCommand="INSERT INTO Products(ProductName, SupplierID, CategoryID, UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
        UpdateCommand="UPDATE [Products] SET [ProductName] = ?,[QuantityPerUnit] = ?, [UnitPrice] = ?, [UnitsInStock] = ? WHERE [ProductID] = ? AND [ProductName] = ? AND [UnitPrice] = ? AND [UnitsInStock] = ?"
        PrimaryKeyFields="ProductID" OldValuesParameterFormatString="original_{0}" ConflictDetection="CompareAllValues">
        <DeleteParameters>
            <asp:Parameter Name="original_ProductID" Type="Int32" />
        </DeleteParameters>
        <UpdateParameters>
            <asp:Parameter Name="ProductName" Type="String" />
            <asp:Parameter Name="UnitPrice" Type="Decimal" />
            <asp:Parameter Name="UnitsInStock" Type="Int16" />
            <asp:Parameter Name="original_ProductID" Type="Int32" />
            <asp:Parameter Name="original_ProductName" Type="String" />
            <asp:Parameter Name="original_QuantityPerUnit" Type="String" />
            <asp:Parameter Name="original_UnitPrice" Type="Decimal" />
            <asp:Parameter Name="original_UnitsInStock" Type="Int16" />
        </UpdateParameters>
        <InsertParameters>
            <asp:Parameter Name="ProductName" Type="String" />
            <asp:Parameter Name="SupplierID" Type="Int32" />
            <asp:Parameter Name="CategoryID" Type="Int32" />
            <asp:Parameter Name="UnitPrice" Type="Decimal" />
            <asp:Parameter Name="UnitsInStock" Type="Int16" />
            <asp:Parameter Name="UnitsOnOrder" Type="Int16" />
            <asp:Parameter Name="ReorderLevel" Type="Int16" />
            <asp:Parameter Name="Discontinued" Type="Boolean" />
        </InsertParameters>
    </sds:SessionDataSource>

    .cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using Telerik.Web.UI;
     
    public partial class Dock_Common_Grid : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            string menuScript = "function RowContextMenu(sender, eventArgs)" +
        "{" +
            "var senderID = sender.get_id();" +
            "var menuID = senderID.substring(0, senderID.lastIndexOf('_')) + '_RadMenu1';" +
            "var menu = $find(menuID);" +
            "var evt = eventArgs.get_domEvent();" +
     
            "if (evt.target.tagName == 'INPUT' || evt.target.tagName == 'A')" +
            "{" +
                "return;" +
            "}" +
     
            "var index = eventArgs.get_itemIndexHierarchical();" +
            "document.getElementById('radGridClickedRowIndex').value = index;" +
     
            "sender.get_masterTableView().selectItem(sender.get_masterTableView().get_dataItems()[index].get_element(), true);" +
     
            "menu.show(evt);" +
     
            "evt.cancelBubble = true;" +
            "evt.returnValue = false;" +
     
            "if (evt.stopPropagation)" +
            "{" +
                "evt.stopPropagation();" +
                "evt.preventDefault();" +
            "}" +
        "}";
            ScriptManager.RegisterStartupScript(Page, Page.GetType(), "menuHandler", menuScript, true);
        }
     
        protected void RadGrid1_PreRender(object sender, EventArgs e)
        {
            if (RadGrid1.EditIndexes.Count > 0 || RadGrid1.MasterTableView.IsItemInserted)
            {
                GridColumn col1 = RadGrid1.MasterTableView.GetColumn("EditCommandColumn") as GridColumn;
                col1.Visible = true;
            }
            else
            {
                GridColumn col2 = RadGrid1.MasterTableView.GetColumn("EditCommandColumn") as GridColumn;
                col2.Visible = false;
            }
        }
        protected void RadMenu1_ItemClick(object sender, RadMenuEventArgs e)
        {
            int radGridClickedRowIndex;
     
            radGridClickedRowIndex = Convert.ToInt32(Request.Form["radGridClickedRowIndex"]);
     
            switch (e.Item.Text)
            {
                case "Edit":
                    RadGrid1.Items[radGridClickedRowIndex].Edit = true;
                    RadGrid1.Rebind();
                    break;
                case "Add":
                    RadGrid1.MasterTableView.IsItemInserted = true;
                    RadGrid1.Rebind();
                    break;
                case "Delete":
                    RadGrid1.MasterTableView.PerformDelete(RadGrid1.Items[radGridClickedRowIndex]);
                    break;
            }
        }
     
    }

    I tested this code and it works without a problem on my side. Let me know if you have any problems.


    Sincerely yours,
    Pero
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  6. OfficeHeart
    OfficeHeart avatar
    99 posts
    Member since:
    Aug 2008

    Posted 29 Sep 2010 Link to this post

    Hi,

    We have the same problem. Is there a better solution then described above?
    Because we use many of
    var grid = $find('<%= RadGrid1.ClientID %>')
    and they all not work.

    Thanks in advance!
  7. Rumen
    Admin
    Rumen avatar
    12851 posts

    Posted 01 Oct 2010 Link to this post

    Hi Martin,

    Using this approach should be used to gain better performance. There is another way to obtain a reference to the array of all Telerik controls described in this KB article: How-to create a javascript array of all particular RadControls on the page.
    However, you should note that this way loops through all Telerik controls and could decrease performance.

    Kind regards,
    Rumen
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Back to Top
UI for ASP.NET Ajax is Ready for VS 2017