This is a migrated thread and some comments may be shown as answers.

How to create a new dock dynamically without Postback

7 Answers 250 Views
Dock
This is a migrated thread and some comments may be shown as answers.
uday chekur
Top achievements
Rank 1
uday chekur asked on 28 Feb 2011, 10:44 PM
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.


7 Answers, 1 is accepted

Sort by
0
Pero
Telerik team
answered on 01 Mar 2011, 04:51 PM
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!
0
uday chekur
Top achievements
Rank 1
answered on 01 Mar 2011, 09:13 PM
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.
0
Pero
Telerik team
answered on 03 Mar 2011, 01:52 PM
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!
0
Gareth
Top achievements
Rank 1
answered on 06 Dec 2012, 10:32 PM
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.
0
Slav
Telerik team
answered on 11 Dec 2012, 03:30 PM
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.
0
Gareth
Top achievements
Rank 1
answered on 11 Dec 2012, 11:28 PM
Hi Slav

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

Thanks,
Gareth.
0
Slav
Telerik team
answered on 14 Dec 2012, 03:29 PM
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.
Tags
Dock
Asked by
uday chekur
Top achievements
Rank 1
Answers by
Pero
Telerik team
uday chekur
Top achievements
Rank 1
Gareth
Top achievements
Rank 1
Slav
Telerik team
Share this question
or