Client state persistence across pages

10 posts, 1 answers
  1. Adam
    Adam avatar
    70 posts
    Member since:
    Jun 2008

    Posted 17 Mar 2009 Link to this post


    Hey guys.  I've taken a couple of stabs at this problem without too much luck yet.

    Our scenario is a RadSplitter with two panes, left and right, with a dockable left hand RadSlidingPane hosted inside a MasterPage with the Content in the right hand pane.  The desired behavior is that, as a user would resize or dock the left hand side, that its state is persisted across postbacks and pages.  Since the resize events are not server events, we can't do any actual server processing on resize, so that only leaves client side methods.  We've tried cookies, but it seems as though, when moving from page to page, the cookies are duplicated from time to time so that we get page-specific cookies for the Request instead of only ever having one cookie there.  And, since there are now no client side methods that set the widths of anything other than the splitter, I don't see many other options left.

    What solutions do you have for this set up?  

    Thanks a lot,

    Adam.g
  2. Answer
    Max
    Max avatar
    4 posts
    Member since:
    Oct 2008

    Posted 17 Mar 2009 Link to this post

    I just tried to set this up using a asmx service linked off the master page and this works pretty well for me.  Only difference from your requirement is that is uses Session instead of cookies.

    TelerikStateService.asmx:
    namespace MyProject
    {  
      [WebService(Namespace = 
    "http://tempuri.org/")]  
      [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]  
      [System.ComponentModel.ToolboxItem(false)]  
      [System.Web.Script.Services.ScriptService]  
      public class TelerikStateService : System.Web.Services.WebService  
      {  
        [WebMethod(EnableSession=true)]  
        public void TogglePane(string paneID, bool isCollapsed)  
        {  
          Session[paneID + "_Collapsed"] = isCollapsed;  
        }  
      }

    Master page markup:

      <telerik:RadScriptManager ID="RadScriptManager1" runat="server" EnableScriptCombine="true">  
        <Services> 
          <asp:ServiceReference Path="~/TelerikStateService.asmx" /> 
        </Services> 
      </telerik:RadScriptManager> 
    <telerik:RadSplitter ID="RadSplitter1" runat="server">  
      <telerik:RadPane ID="MyPane" OnClientCollapsed="CollapsePane" OnClientExpanded="ExpandPane" runat="server">  
        ...  
      </telerik:RadPane>  
    </telerik:RadSplitter>

      <script type="text/javascript">    
        function CollapsePane(sender, args) {  
          MyProject.TelerikStateService.TogglePane(sender.get_id(), true);  
        }  
        function ExpandPane(sender, args) {  
          MyProject.TelerikStateService.TogglePane(sender.get_id(), false);  
        }
      </script> 

    Master page Page_Load, call this method for each pane:
     
        public void LoadPaneSettings(RadPane pane)  
        {  
          bool paneCollapsed = (bool)(Session[pane.ClientID + "_Collapsed"] ?? false);        
          pane.Collapsed = paneCollapsed;  
        } 

    Let me know if you can clean this up a bit for me ^.^
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Tsvetie
    Admin
    Tsvetie avatar
    1517 posts

    Posted 20 Mar 2009 Link to this post

    Hello Adam,
    I am not quite sure how you implemented your cookies. In case you send me your code, I will review it and probably would find the cause for the duplication.

    I have attached a simple test page that demonstrates one implementation of your scenario. I hope this would help you.

    Sincerely yours,
    Tsvetie
    the Telerik team


    Instantly find answers to your questions on the new Telerik Support Portal.
    Check out the tips for optimizing your support resource searches.
  5. Adam
    Adam avatar
    70 posts
    Member since:
    Jun 2008

    Posted 20 Mar 2009 Link to this post

    I love the cookie approach, and you're correct that the above example works great for preserving the docked state,
    but we are attempting to store the width as well.  So, while there isn't a problem obtaining the width on the client side, there IS a problem setting the width on the client side.  I am unaware of a client side method that sets the RadSlidingPane's width on the client side, so I'm attempting to set the width on the server side, and therein lies the problem.

    Expanding upon the original code to store the docking info and the width:

                    var SplitterCookie = "SplitterCookie";  
                    var SplitterCookieDelimiter = "*";  
                    
                    function PreserveState(sender, eventArgs)  
                    {  
                        debugger;  
                        var zone = $find('<%= SlidingZone1.ClientID %>');  
                        var expandedPaneID = zone.get_dockedPaneId();  
                        expandedPaneID += SplitterCookieDelimiter + sender.get_width();  
                        SetCookie('SplitterCookie', expandedPaneID);  
                    }  
                      
                    function OnClientLoaded(object, args)  
                    {  
                        var zone = object;  
                        var dockedPaneID = GetCookie('SplitterCookie');  
                          
                        if (dockedPaneID)   
                        {  
                          debugger;  
                          var docked = dockedPaneID.substring(0, dockedPaneID.indexOf(SplitterCookieDelimiter));  
                          if(docked)  
                          {  
                              setTimeout(function(){  
                                  zone.dockPane(docked);  
                              }, 0);              
                          }  
                        }  
                    } 

    private const String _SPLITTERCOOKIENAME = @"SplitterCookie";  
        private const char _SPLITTERCOOKIEDELIMITER = '*';  
     
        /// <summary>  
        /// Gets the cookie used for storing the client persisted state of the Splitter  
        /// </summary>  
        private void GetSplitterPersistenceCookie()  
        {  
            HttpCookie cookie = Request.Cookies[_SPLITTERCOOKIENAME];  
     
            if (cookie != null)  
            {  
                string[] cookieValues = cookie.Value.Split(_SPLITTERCOOKIEDELIMITER);  
     
                Nav.Width = new Unit(Double.Parse(cookieValues[1]), UnitType.Pixel);  
            }  
        } 

    When we attempt to retrieve the cookie on page_load of the master page, we often get the correct cookie value.  However, while going from page to page, we soon see a duplicate cookie, and so we end up retrieving an invalid value.

    Any thoughts?

    Adam.g

  6. Tsvetie
    Admin
    Tsvetie avatar
    1517 posts

    Posted 24 Mar 2009 Link to this post

    Hello Adam,
    You can use the set_width client-side method of the RadSlidingPane to set the width of the sliding pane on the client. For example:
    <telerik:RadSplitter ID="RadSplitter1" runat="server"
        <telerik:RadPane ID="RadPane1" runat="server" Width="22px"
            <telerik:RadSlidingZone ID="RadSlidingZone1" runat="server"
                <telerik:RadSlidingPane ID="RadSlidingPane1" Width="150" runat="server" Title="Pane 1"
                </telerik:RadSlidingPane> 
            </telerik:RadSlidingZone> 
        </telerik:RadPane> 
        <telerik:RadSplitBar ID="RadSPlitBar1" runat="server" /> 
        <telerik:RadPane ID="RadPane2" runat="server"
            <button onclick="SetSlidingPaneWidth(300);return false;">Set 300 px as width</button> 
        </telerik:RadPane> 
    </telerik:RadSplitter> 
    <script type="text/javascript"
    function SetSlidingPaneWidth(newWidth) 
        var slidingPane = $find('<%= RadSlidingPane1.ClientID %>'); 
        slidingPane.set_width(newWidth); 
    </script> 

    Make sure that you first set the new width for the sliding pane and then dock it.

    All the best,
    Tsvetie
    the Telerik team

    Check out Telerik Trainer , the state of the art learning tool for Telerik products.
  7. Michael Pullella
    Michael Pullella avatar
    16 posts
    Member since:
    Jul 2010

    Posted 09 Aug 2010 Link to this post

    "When we attempt to retrieve the cookie on page_load of the master page, we often get the correct cookie value.  However, while going from page to page, we soon see a duplicate cookie, and so we end up retrieving an invalid value."

    I have taken this approach as well, and am finding the same problem that Adam had... How did / can you get around this?
  8. Adam
    Adam avatar
    70 posts
    Member since:
    Jun 2008

    Posted 09 Aug 2010 Link to this post

    We gave up on checking cookies a long while back in the process and have not had any problems with the approach marked as answer in this thread.  If that approach is an option for you, I would highly recommend it.
  9. Michael Pullella
    Michael Pullella avatar
    16 posts
    Member since:
    Jul 2010

    Posted 09 Aug 2010 Link to this post

    Adam..

    When you say "gave up on checking cookies", what are you saying exactly? 

    Right now, I'm doing this:
            function OnClientLoaded(object, args) {
                var zone = object;
                var dockedPaneID = getCookie('dockedID');
    alert("setting pane to " + dockedPaneID);
                if (dockedPaneID) {
                    setTimeout(function() {
                        zone.dockPane(dockedPaneID);
                    }, 0);
                }
            }

    are you saying that you are not getting the cookie (line above the alert)? 

    Thanks in advance Adam!
  10. Adam
    Adam avatar
    70 posts
    Member since:
    Jun 2008

    Posted 09 Aug 2010 Link to this post

    Yes, instead of getting and setting the Splitter settings on the client, we set them on load of the page.  So, instead of storing the data in cookies, we have a locally instanced service that we can call from javascript that sets session settings for the user.  It's very similar to Max's approach listed above.
  11. Michael Pullella
    Michael Pullella avatar
    16 posts
    Member since:
    Jul 2010

    Posted 09 Aug 2010 Link to this post

    Thanks Adam..

    For now, this approach isn't going to work, but I have changed the idea that Telerik gave and it seems to be working.  Basically, I just set an expiration on the cookie for 30 minutes.  Even though I have waited longer than 30 minutes between postbacks, the solution seems to still be working

    function setCookie(name, value, minutes) {
        if (seconds) {
            var date = new Date();
            date.setTime(date.getTime() + (minutes * 60 * 1000));
            var expires = "; expires=" + date.toGMTString();
        }
        else var expires = "";
        document.cookie = name + "=" + value + expires + "; path=/";
    }

    function
    PreserveState() {
        var zone = $find('<%= mainSlidingZone.ClientID %>');
        var expandedPaneID = zone.get_dockedPaneId();
        setCookie('dockedID', expandedPaneID, 30);
    }

    Thanks for your help Adam... If we find that this isn't going to work, I will take your advice and use Max's approach.
Back to Top
UI for ASP.NET Ajax is Ready for VS 2017