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

Cannot Select Node (client-side)

4 Answers 120 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
digitall
Top achievements
Rank 1
digitall asked on 29 Apr 2011, 09:35 PM

To give a little background, I have a RadSplitter set up with two panes - one for a RadTreeView and the other for "external content" (using URLs, but they are all internal to the site). The nodes in the tree are setup like this:

  • Root Node (database driven)
    • Static Node, ServerSideCallback expand method
      • X Nodes (database driven)
    • Static Node, ServerSide expand method (required for custom context menus)
      • X Nodes (database driven, custom context menus)

The entire TreeView object is setup as an AjaxUpdatedControl which, combined with the Javascript "node.showLoadingStatus()" method (in lieu of a LoadingPanel covering the entire tree), allows the nodes that are configured as ServerSide to appear to behave identically to the ServerSideCallback expanding nodes. This is setup as so:

<telerik:RadAjaxManager runat="server" ID="RadAjaxManager1" EnableAJAX="true">
    <AjaxSettings>
        <telerik:AjaxSetting AjaxControlID="trProjects">
            <UpdatedControls>
                <telerik:AjaxUpdatedControl ControlID="trProjects" />
                <telerik:AjaxUpdatedControl ControlID="hvNodeToSelect" />
            </UpdatedControls>
        </telerik:AjaxSetting>
    </AjaxSettings>
    <ClientEvents OnResponseEnd="ajaxCallback" />
</telerik:RadAjaxManager>

When a certain action occurs on the main RadPane (where the "external" content is at - internal pages so XSS is not an issue) the loaded page calls a function called "selectNode" on the parent (which contains the RadSplitter, TreeView, etc.) which looks like this:

//called from child pages to select the associated node
function selectNode(parent, child) {
    var parentNode = treeView.findNodeByValue(parent);
    setNodeToSelect(child);
  
    if (!parentNode.get_expanded()) {
        if (!parentNode.get_parent().get_expanded())
            parentNode.get_parent().expand();
  
        parentNode.expand();              
  
    } else {
        if (parentNode.get_expandMode() != 1) { //Server-side (encapsulated by RadAJAX)
            var childNode = treeView.findNodeByValue(child);
            childNode.set_selected(true);            
            nodeToSelect = null; //page-level javascript variable
        }
    }
}

The first thing it does is check to see if the parent node is expanded (all the way through the top-level root node) and expands down. For the purposes of this issue this is the block being called and not the other half (the "else" clause). When I execute the action that fires this the bottom-level child node (one of the database-driven X nodes as referenced above, the parent being the one with the ServerSideCallback expand mode) gets selected which is exactly what I want.

What I've noticed though is once I've utilized the "parentNode.expand();" method on a node that is ServerSide (which the RadAjaxManager makes appear as if no postback occurs) this functionality stops working. To better explain this, inside the method above there is a small function called setNodeToSelect called right at the beginning which looks like this:

function setNodeToSelect(value) {
    nodeToSelect = value;
    hvNodeToSelect.value = nodeToSelect;
}

This sets the page-level variable "nodeToSelect" equal to the value of the node that needs to select. It also sets a hidden field's value equal to that same one, but that has no bearing on this. Since "parentNode.expand();" is trying to expand a ServerSideCallback node that should fire the client-side "NodePopulated" event. I have that configured to do the actual node selection and the signature looks like this:

function trProjects_NodePopulated(sender, args) {
    var node = args.get_node();
  
    if (nodeToSelect != null) {
        treeView.findNodeByValue(nodeToSelect).set_selected(true);
        nodeToSelect = null;
    }
}

This seems to occur fine up until I have expanded the node that is setup as ServerSide for retrieving items (which is required because of a custom context menu per item). Once I have done that (with the RadAjaxManager making it appear a postback didn't occur) I can no longer call the "parentNode.expand();" methods nor does the NodePopulated event get fired. What is even stranger is calling "parentNode.expand();" doesn't throw any errors, instead it just fails to expand the ServerSideCallback node being referenced. The strangest part of all is if I do something like "alert(parentNode.get_expanded());" it returns True even though the node is not actually expanded!

I was tinkering with how this whole process worked and was finally able to get a Javascript error that might help point someone in the right direction on this. If I have the Static Node (the one with ServerSideCallback as the expand mode) already expanded what should occur is any action executed should automatically select the node it is associated with inside that "else" block above that starts out with "if (parentNode.get_expandMode() != 1)" since the parent is already expanded. This functionality works great up until I do something with the ServerSide node and then it starts erroring out with this: "this.get_element() is undefined" on line 1241 of one of the Telerik embedded Javascript files (ScriptResource.axd).

The line that fails (1241) is:

this.get_element().value=d

The line where this fails is immediately above this entry:

_registerSelectedNode:function(d){this._insertSortedHierarchicalIndexInArray(d._getHierarchicalIndex(),this._clientState.selectedNodes);

Any thoughts on this? Are there known issues with mixing ServerSide and ServerSideCallback nodes with an AjaxManager intervening on behalf of ServerSide nodes? Keep in mind that this only fails once I have interacted with the ServerSide node. Up until I do that everything works exactly as expected.

Thanks in advance!

Edit: Added "this.get_element().value=d" for better reference. Also some slight formatting changes (whitespace) for easier reading.

4 Answers, 1 is accepted

Sort by
0
digitall
Top achievements
Rank 1
answered on 03 May 2011, 07:22 PM
Anyone?
0
Nikolay Tsenkov
Telerik team
answered on 05 May 2011, 01:35 PM
Hello Scott,

When you execute node.expand() on a node with ExpandMode ServerSide, the entire TreeView is postbacked inside of an ajax request and you probably manage to select the current node, since there is no JavaScript error (or there is?). But I guess, before the node is made visibly selected, it's been removed (on ajax request, the controls are being disposed prior to the starting of the request). Then the new TreeView is received client-side and it doesn't have a selected node.

If this is the problem I would suggest the following:
 - client-side, check the expand mode of the currently expanded node in the handler of ClientNodeExpanding, and if the node is with ExpandMode ServerSide => do nothing more;
 - server-side check the ExpandMode of the node and if it's again ServerSide => find the parent and select it there (this time there is a full page life-cycle and you will have the entire tree to refer to).

If I didn't get the problem you experience, please, try to explain only the problem and post a complete example reproducing it (as simple as possible).


Regards,
Nikolay Tsenkov
the Telerik team

Browse the vast support resources we have to jump start your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.

0
digitall
Top achievements
Rank 1
answered on 05 May 2011, 06:35 PM
I don't think that's the case - before I put an AjaxManager on the page the nodes that were ServerSide caused the whole page to post back. The ones that were ServerSideCallback appear to use ajax though.

I will try to get a demo example posted here for you to see.
0
digitall
Top achievements
Rank 1
answered on 07 May 2011, 03:58 PM
I think I know what was causing this, however the root explanation is a bit beyond me. I had the following setup:

var treeview = null;
  
function setup() {
     Sys.Application.remove_load(setup);
     treeview = $find("<%=this.trProjects.ClientID %>");
}
  
Sys.Application.add_load(setup);

I then used the "treeview" variable in a number of places whenever I needed to access the tree. As it turns out, by sharing this all over the place I was utilizing what appears to be a cached copy of the treeview. I ended up having to change this scenario to all serverside because we opted for custom context menus on all the nodes and this issue came up again until I reset the treeview variable with a new "$find()" call. Doing that caused everything to work exactly as expected.

I don't know enough about what "$find()" does, but I wouldn't have expected it to retain a cached copy of the entire object until I reset the variable with a new "$find()" call.

Hopefully that helps somebody!
Tags
TreeView
Asked by
digitall
Top achievements
Rank 1
Answers by
digitall
Top achievements
Rank 1
Nikolay Tsenkov
Telerik team
Share this question
or