How to create a new dock dynamically without Postback

8 posts, 0 answers
  1. uday chekur
    uday chekur avatar
    2 posts
    Member since:
    Mar 2010

    Posted 28 Feb 2011 Link to this post

    Hello,

    Here is my situation. I am developing a portal page using Raddocks. On top of the page I will have a rad grid which will have a linkbutton with an onclick event on server side. When the user clicks on a linkbutton of a specific row of a radgrid, a new widget/dock should be created and added to the Layout. 

    Every dock has a usercontrol in it which is loaded via a webservice. I am saving the state in the database from client side. My issue here is that whenever I am creating a new dock, all the existing docks are getting recreated and all the usercontrols are getting loaded again. I just want the user selected dock to be loaded. 

    I know that I can use AsyncPostBackTrigger, but I am getting an error that it is not able to find the control that I am clicking(btnAddWidget) which is inside a RadGrid. I was wondering if there is any other way to handle this without having to re-create all the docks again. I have the flexibility to replace the RadGrid with any other control like a listview or something.

    The following is my code:

    Default.aspx:

       function OnClientDockPositionChanged(dock, args) {
                                SaveState();
                            }
                            function OnClientResizeEnd(dock, args) {
                                SaveState();
                            }
                           function OnClientCommand(dock, args) {
                                SaveState();
                            }
                            function SaveState() {
                                var i;
                                var state = "";
                               var zone1 = $find("RadDockZone1");
                                var zone2 = $find("RadDockZone2");
                                var array1Docks = zone1.get_docks();
                                var array2Docks = zone2.get_docks();
                                for (i = 0; i < array1Docks.length; i++) {
                                    var dock = array1Docks[i];
                                    var dockID = dock.get_id();
                                    var tag = $get(dockID).attributes["tag"].value;
                                    state = state + tag + "#" + array1Docks[i].saveClientState() + "|";
                                }
                                for (i = 0; i < array2Docks.length; i++) {
                                    var dock = array2Docks[i];
                                    var dockID = dock.get_id();
                                    var tag = $get(dockID).attributes["tag"].value;
                                    state = state + tag + "#" + array2Docks[i].saveClientState() + "|";
                                }
                                SOLEWebService.VerifyUserSessionAndUpdateUserSettings(state, success, onFail);
                            }
                          function success(result) {
                                alert("success");
                            }
                           function onFail(result) {
                                alert(result.d);
                            }
                   function OnClientInitialize(dock, args) {
                    var dockID = dock.get_id();
                  var tag = $get(dockID).attributes["tag"].value;
                  var UserControl = $get(dockID).attributes["UserControl"].value;
                  if ($get(dockID).attributes["NewDock"] != null && $get(dockID).attributes["NewDock"].value != null) {
                      var newDock = $get(dockID).attributes["NewDock"].value;
                      var state = "";
                      state = tag + "#" + dock.saveClientState() + "|";
                      SOLEWebService.VerifyUserSessionAndSaveUserSettings(state, success, onFail);
                  }
                     UserControlService.GetUserWidgetData(UserControl, tag, function (result) {
                     $get(dockID + "_C").innerHTML = result;
                  });
              }
           <script src="/Scripts/JQuery/Scripts/JQuery-1.4.1-vsdoc.js" type="text/javascript"></script>
        </head>
    <body>
        <form id="form1" runat="server">
        <telerik:RadScriptManager runat="server" ID="RadScriptManager1" EnablePageMethods = "true" EnableScriptCombine="true">
        <Services>
          <asp:ServiceReference Path = "~/UserControlService.asmx" />
          <asp:ServiceReference Path = "~/SOLEWebService.asmx" />
        </Services>
        </telerik:RadScriptManager>
      <telerik:RadStyleSheetManager ID="RadStyleSheetManager1" runat="server" EnableStyleSheetCombine="true">
        </telerik:RadStyleSheetManager>
          <telerik:RadAjaxPanel ID="RadAjaxPanel1" runat="server"  ClientEvents-OnResponseEnd = "RecallJquery">
            <asp:UpdatePanel runat="server" ID="UpdatePanel1">
            <ContentTemplate>
            <table>
            <tr>
            <td>
            <div id = "gridViewPanel" class = "ContainerPanel">
              <div id="gridViewHeader" class="collapsePanelHeader">
                <div id="Div2" class="HeaderContent">Add Stuff</div>
                <div id="Div3" class="ArrowClose"></div>
             </div>
              <div id = "gridContent" class = "Content" style="display:none">
                     <telerik:RadGrid runat="server" ID="grdWidgets" OnNeedDataSource="grdWidgets_NeedDataSource"
                        AllowPaging="True" Width="400px" >
                        <MasterTableView DataKeyNames="Widgets" Width="100%" TableLayout="Fixed">
                            <Columns>
                                <telerik:GridTemplateColumn UniqueName="TemplateColumn" HeaderText="" ItemStyle-Width = "50px">
                            <ItemTemplate>
                                <asp:Panel ID="Panel1" runat="server">
                                    <asp:LinkButton ID="btnAddWidget" runat="server"   Text = "Add" OnClick = "btnAddWidget_Click"  />
                                </asp:Panel>
                            </ItemTemplate>
                        </telerik:GridTemplateColumn>
               </Columns>
                        </MasterTableView>
                        <ClientSettings AllowRowsDragDrop="True">
                            <Selecting AllowRowSelect="True" EnableDragToSelectRows="false" />
                          <Scrolling AllowScroll="true" UseStaticHeaders="true" ScrollHeight="320px" />
                        </ClientSettings>
                        <PagerStyle Mode="NumericPages" PageButtonCount="4" />
                    </telerik:RadGrid>
             </div>
             </div>
            </td>
            </tr>
            </table>
           <telerik:RadDockLayout runat="server" ID="RadDockLayout1" OnLoadDockLayout="RadDockLayout1_LoadDockLayout">
            <table>
                <tr>
                    <td style="vertical-align: top">
                        <telerik:RadDockZone ID="RadDockZone1" runat="server" Orientation="Vertical" Width="250px"
                            MinHeight="400px">
                         </telerik:RadDockZone>
                    </td>
                    <td style="vertical-align: top">
                        <telerik:RadDockZone ID="RadDockZone2" runat="server" Orientation="Vertical" Width="560px"
                            MinHeight="400px">
                         </telerik:RadDockZone>
                    </td>
                </tr>
            </table>
            </telerik:RadDockLayout>
             </ContentTemplate>
           <%--  <Triggers>
                <asp:AsyncPostBackTrigger ControlID="btnAddWidget" EventName="Click" />
            </Triggers>--%>
                </asp:UpdatePanel>
                </telerik:RadAjaxPanel>
     
    Code-Behind:
     Protected Sub grdWidgets_NeedDataSource(ByVal source As Object, ByVal e As GridNeedDataSourceEventArgs)
            grdWidgets.DataSource = PortalDataManager.GetDefaultWidgets()
        End Sub

        Private ReadOnly Property CurrentDockStates() As List(Of DockState)
            Get
                'Get saved state string from the database - set it to dockState variable for example 
                Dim dockStatesFromDB As String = String.Empty
               dockStatesFromDB = PortalDataManager.GetUserWidgetSettings(33357)
               Dim _currentDockStates As New List(Of DockState)()
                If dockStatesFromDB Is Nothing Then
                    Return _currentDockStates
                End If
                If dockStatesFromDB Is String.Empty Then
                    Return _currentDockStates
                End If
                Dim stringStates As String() = dockStatesFromDB.Split("|"c)
                For i As Integer = 0 To stringStates.Length - 2
                    Dim currentState As String() = stringStates(i).Split("#"c)
                    Dim uniqueName As String = currentState(0)
                    Dim state As String = currentState(1)
                    If state.Trim() <> String.Empty Then
                        Dim ds As DockState = DockState.Deserialize(state)
                        ds.Tag = uniqueName
                        ds.UniqueName = uniqueName
                        _currentDockStates.Add(ds)
                    End If
                Next
         Return _currentDockStates
            End Get
        End Property
     
     Protected Sub RadDockLayout1_LoadDockLayout(ByVal sender As Object, ByVal e As DockLayoutEventArgs)
            Dim states As List(Of DockState) = CurrentDockStates
            For Each state As DockState In states
                e.Positions(state.UniqueName) = state.DockZoneID
                e.Indices(state.UniqueName) = state.Index
            Next
        End Sub

        Private Function CreateRadDockFromState(ByVal state As DockState) As RadDock
            Dim dock As New RadDock()
            dock.DockMode = DockMode.Docked
            dock.ID = String.Format("RadDock{0}", state.UniqueName)
            dock.ApplyState(state)
            SetDockProperties(dock)
            AddClientEventsToDock(dock)
            Return dock
        End Function

        Private Sub SetDockProperties(ByRef dock As RadDock)
            dock.AutoPostBack = False
            dock.CommandsAutoPostBack = False
            dock.Commands.Add(New DockCloseCommand())
            dock.Commands.Add(New DockExpandCollapseCommand())
            dock.EnableEmbeddedScripts = True
            dock.EnableRoundedCorners = True
            dock.EnableAnimation = True
        End Sub

        Private Sub AddClientEventsToDock(ByRef dock As RadDock)
            dock.OnClientInitialize = "OnClientInitialize"
            dock.OnClientResizeEnd = "OnClientResizeEnd"
            dock.OnClientDragEnd = "OnClientDragEnd"
            dock.OnClientDockPositionChanged = "OnClientDockPositionChanged"
            dock.OnClientCommand = "OnClientCommand"
        End Sub

     Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
             If (Not Page.IsPostBack) Then
            Dim dockCount As Integer = CurrentDockStates.Count
            For i As Integer = 0 To dockCount - 1
                If CurrentDockStates(i).Closed = False Then
                    Dim dock As RadDock = CreateRadDockFromState(CurrentDockStates(i))
                    RadDockLayout1.Controls.Add(dock)
                    LoadUserControl(dock)
                End If
            Next
            End If
        End Sub

       Protected Sub btnAddWidget_Click(ByVal sender As Object, ByVal e As System.EventArgs)
            Dim btnAdd As LinkButton = CType(sender, LinkButton)
            Dim myPanel As Panel = CType(btnAdd.Parent, Panel)
            Dim dataItem As GridDataItem = CType(myPanel.NamingContainer, GridDataItem)
            Dim widgetType As String = dataItem("Widgets").Text
            Dim widgetTag As String = dataItem("WidgetTag").Text
            Dim userControl As String = dataItem("WidgetUserControl").Text
            Dim dock As RadDock = CreateRadDock(widgetTag)
            dock.Attributes("NewDock") = "True"
            dock.Attributes("UserControl") = userControl
            dock.Attributes("tag") = dock.Tag
            RadDockZone1.Controls.Add(dock)
            btnAdd.Text = "Added"
            btnAdd.Enabled = False
        End Sub

     Private Function CreateRadDock(ByVal tag As String) As RadDock
            Dim dock As New RadDock()
            dock.DockMode = DockMode.Docked
            dock.UniqueName = tag
            dock.Tag = tag
            dock.ID = String.Format("RadDock{0}", dock.UniqueName)
            dock.Title = "New Dock"
            SetDockProperties(dock)
            AddClientEventsToDock(dock)
            Dim img As New Image()
            img.ImageUrl = "Reload.gif"
            dock.ContentContainer.Controls.Add(img)
           Return dock
       End Function

       Protected Sub grdWidgets_ItemCreated(ByVal sender As Object, ByVal e As Telerik.Web.UI.GridItemEventArgs) Handles grdWidgets.ItemCreated
            If TypeOf e.Item Is GridDataItem Then
                Dim dataItem As GridDataItem = CType(e.Item, GridDataItem)
                dataItem.ToolTip = dataItem("Widgets").Text
            End If
        End Sub

        Public Sub LoadUserControl(ByRef dock As RadDock)
            If dock.Tag Is Nothing Then
                Return
            End If
            Dim img As New Image()
            img.ImageUrl = "Reload.gif"
            dock.ContentContainer.Controls.Add(img)
            dock.Attributes("UserID") = 33357
            dock.Attributes("UserControl") = PortalDataManager.GetUserControlForWidget(dock.Tag)
            dock.Attributes("tag") = dock.Tag
        End Sub

    Thanks so much for your time on this,

    Uday.


  2. Pero
    Admin
    Pero avatar
    1156 posts

    Posted 01 Mar 2011 Link to this post

    Hi Uday,

    First of all, I noticed two things that might cause problems in your application:
    • You have nested an UpdatePanel in an AjaxPanel. Nesting UpdatePanels or AjaxPanels is not recommended and might result in an ajax conflicts.
    • The docks are recreated in the Page.Load instead of Page.Init, on postbacks. This can result in the dockstate not being loaded correctly because the docks are not created before the LoadDockLayout event is fired. Please consider recreating the docks on Page.Init if you notice that the correct state has not been loaded. 

    Regarding your question, I believe the approach described in the project from the following Code Library article will help you achieve the desired scenario: http://www.telerik.com/community/code-library/aspnet-ajax/docking/saving-state-of-dynamically-created-raddocks-in-database-using-hidden-updatepanel.aspx.
    Notice that the docks are added to the update panel, and then with a custom JavaScript loaded from the server, they are docked to the respective zone. If the state is saved on the client you should remove the $find('{0}').doPostBack('DockPositionChanged') from the call to the ScriptManager.RegisterScript method in the ButtonAddDock_Click  subroutine.
    Also it is not needed to handle the dock_Command event, since your commands are not posting the page back to the server.
    As AsyncPostBackTrigger can be used the RadGrid. The UpdatePanel should catch the events from the grids LinkButtons.
    If you want to execute custom javascript on ajax response, you should call your custom function in the script registered with the ScriptManager.RegisterScript method, in the ButtonAddDock_Click subroutine.

    All the best,
    Pero
    the Telerik team
    Registration for Q1 2011 What’s New Webinar Week is now open. Mark your calendar for the week starting March 21st and book your seat for a walk through all the exciting stuff we ship with the new release!
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. uday chekur
    uday chekur avatar
    2 posts
    Member since:
    Mar 2010

    Posted 01 Mar 2011 Link to this post

    Hello Pero,

    Thank you so much for the reply. I made the changes that you suggested. 

    I made AsyncPostBackTrigger to find the radgrid events, but it is still doing post back and loading all the docks again. I was curious if there was a way to create a new dock on the client side and just dock into any one of the zones instead of going to the server. 

    I also had another question. I am adding usercontrols to the docks using a webservice and I was wondering if there is a way to find the controls inside the raddock that were loaded. I think there is a way to find them on the server side, but in my case let's say a user click's on the edit custom command of the dock, I want to slide down a box which gives them options to change the settings of the dock. I want to save the settings and refresh the dock from the client side itself. Can you direct me towards  a project or an example on this.

    Thanks so much,

    Uday.
  5. Pero
    Admin
    Pero avatar
    1156 posts

    Posted 03 Mar 2011 Link to this post

    Hi Uday,

    For the time being the RadDock cannot be created on the client. It can only be created on the server.

    I created a sample project, to test whether clicking on the buttons in the grid will cause a postback or ajax call, and it turns out that the Grid initiates Ajax calls. The sample is attached to the thread.

    To find the user controls loaded within the dock, you should use the RadDock.ContentContainer.FindControl
    method.
    I believe the following code will give you idea how to achieve the scenario with the sliding box. It has a hidden <div/> that is shown when a custom dock command is clicked. The hidden <div/> will play the role of the sliding box.
    Copy Code
    <%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <headrunat="server">
        <title></title>
    </head>
    <body>
        <formid="form1"runat="server">
        <asp:ScriptManagerID="RadScriptManager1"runat="server">
        </asp:ScriptManager>
        <scripttype="text/javascript">
            function OnClientCommand(dock, args)
            {
                var command = args.command;
                var divSettings = $get("chooseSettings");
                if (command.get_state() == 1)
                {
                    divSettings.style.display = "block";
                    command.set_state(2);
                }
                else
                {
                    divSettings.style.display = "none";
                    command.set_state(1);
                }
            }
        </script>
        <div>
            <telerik:RadDockLayoutID="RadDockLayout1"runat="server">
                <telerik:RadDockZoneID="RadDockZone1"runat="server"MinHeight="300px"Width="300px">
                    <telerik:RadDockID="RadDock1"runat="server"Title="RadDock-Title"Width="300px">
                        <Commands>
                            <telerik:DockCloseCommand/>
                            <telerik:DockToggleCommandState="Primary"Text="Edit"AlternateText="Finish Edit"
                                OnClientCommand="OnClientCommand"/>
                        </Commands>
                        <ContentTemplate>
                            <divid="chooseSettings"style="background-color: Yellow; display: none; height: 100px">
                                Choose fields to display
                            </div>
                            Dock's Content
                        </ContentTemplate>
                    </telerik:RadDock>
                </telerik:RadDockZone>
            </telerik:RadDockLayout>
        </div>
        </form>
    </body>
    </html>


    Greetings,
    Pero
    the Telerik team
    Registration for Q1 2011 What’s New Webinar Week is now open. Mark your calendar for the week starting March 21st and book your seat for a walk through all the exciting stuff we ship with the new release!
  6. Gareth
    Gareth avatar
    2 posts
    Member since:
    May 2011

    Posted 06 Dec 2012 Link to this post

    Has there been any further development with this? Is it possible to create a new dock dynamically on the client-side without a postback occurring?

    Many thanks,
    Gareth Hayter.
  7. Slav
    Admin
    Slav avatar
    1355 posts

    Posted 11 Dec 2012 Link to this post

    Hi Gareth,

    I am afraid there is not an out of the box approach for creating a RadDock on the client-side. You could recreate the HTML of the control from a template through JavaScript and its DOM API. Please, note that you will also need to provide the $create clause with all the necessary dependencies. For best results review the generated code from a single RadDock. This approach is quite complex and may involve a lot of client-side complications.

    An easier approach is to use the RadDock's client-side method clone. It will copy the client-side object of an already existing RadDock control, the Closed property of which will be set to true so that it is not visible on the page:

    dock = $find("<%=RadDock1.ClientID %>");
    var newDock = dock.clone();
    dock.set_closed(false);

    Regards,
    Slav
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
  8. Gareth
    Gareth avatar
    2 posts
    Member since:
    May 2011

    Posted 11 Dec 2012 Link to this post

    Hi Slav

    Thanks very much for the suggestion. Is there any possibility of this functionality being added to a future release?

    Thanks,
    Gareth.
  9. Slav
    Admin
    Slav avatar
    1355 posts

    Posted 14 Dec 2012 Link to this post

    Hi Gareth,

    Currently such a functionality is not planned for implementation in the RadDock control. If you are having difficulties using my suggestion, please describe in detail your scenario so that I can help you accordingly or recommend another approach if possible.

    Regards,
    Slav
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
Back to Top
UI for ASP.NET Ajax is Ready for VS 2017