PDA

View Full Version : [CLOSED] Exception window when expanding node for TreeGrid



alscg
Feb 11, 2014, 9:20 AM

Daniil
Feb 11, 2014, 12:39 PM
Hi @alscg,

Please clarify how are you going to load the children to those nodes? You don't populate its children in the ProxyTree method and don't configure a TreeStore with a Proxy. So, if a node has no Children and it is not a leaf node, then on expanding it tries to load the children from the page unless you configure a TreeStore with some Proxy.

alscg
Feb 12, 2014, 5:45 AM
Hi @alscg,

Please clarify how are you going to load the children to those nodes? You don't populate its children in the ProxyTree method and don't configure a TreeStore with a Proxy. So, if a node has no Children and it is not a leaf node, then on expanding it tries to load the children from the page unless you configure a TreeStore with some Proxy.

Hi Daniil

We are loading children by using direct method. So added the listener [.Listeners(x => x.BeforeItemClick.Fn = "LoadNodes")] for event 'BeforeItemClick'.
Here is code for load nodes function -



var LoadNodes = function (store, operation, options) {
var node = App.TreeGridId.getStore().getNodeById(operation.da ta.id);
App.direct.LoadChildNodes(node.getId(), {
success: function (result) {
if (result.length > 0) {
node.set('loading', false);
node.set('loaded', true);
node.removeAll();
node.appendChild(result);
}
},
eventMask: {
showMask: true,
minDelay: 500
},
failure: function (errorMsg) {
Ext.Msg.alert('Failure', errorMsg);
}
});
//return false;
}


And code for Direct action method


[DirectMethod]
public ActionResult LoadChildNodes(string nodeId)
{
NodeCollection nodes = new Ext.Net.NodeCollection() {
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText1", AttributesObject = new {nodeText = "ChildNodeText1", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }},
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText2", AttributesObject = new {nodeText = "ChildNodeText2", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }},
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText3", AttributesObject = new {nodeText = "ChildNodeText3", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }},
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText4", AttributesObject = new {nodeText = "ChildNodeText4", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }}
};

if (nodeId == "1000")
{
return this.Direct(new Ext.Net.NodeCollection());
}
else
{
return this.Direct(nodes);
}
}


This works and adds children to node which expanded, but still gives ext.net exception window.
7578
Could you tell us correct Proxy method to achieve this without getting ext.net exception window.

Here is completed modified code for loading children:

Controller Code


[DirectController(GenerateProxyForOtherControllers = true, IDMode = DirectMethodProxyIDMode.None)]
public class ExtNetController : Controller
{
public ActionResult ProxyTree()
{
NodeCollection nodes = new NodeCollection();
Node node = new Node();
node.NodeID = "1000";
node.Text = "FirstNode";
for (int i = 0; i < 5; i++)
{
Node childnode = new Node();
childnode.NodeID = i.ToString();
childnode.Text = "Node " + i;
childnode.Expanded = false;
node.Children.Add(childnode);
childnode.AttributesObject = new { nodeText = "Node " + i, iconHtml = "<img src='iconImage.png' width='15' height='15' />" };
}

node.AttributesObject = new { nodeText = node.Text, iconHtml = "<img src='iconImage.png' width='15' height='15' />" };
nodes.Add(node);

return View(nodes);
}

[DirectMethod]
public ActionResult LoadChildNodes(string nodeId)
{
NodeCollection nodes = new Ext.Net.NodeCollection() {
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText1", AttributesObject = new {nodeText = "ChildNodeText1", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }},
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText2", AttributesObject = new {nodeText = "ChildNodeText2", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }},
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText3", AttributesObject = new {nodeText = "ChildNodeText3", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }},
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText4", AttributesObject = new {nodeText = "ChildNodeText4", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }}
};

if (nodeId == "1000")
{
return this.Direct(new Ext.Net.NodeCollection());
}
else
{
return this.Direct(nodes);
}
}
}


View code


@model NodeCollection
<html>
<style>
.no-node-icon img.x-tree-icon {
display: none;
}
</style>

<head>
<meta name="viewport" content="width=device-width" />
<title>ProxyTree</title>
<script type="text/javascript">
var displayIcons = function (value, meta, record, index) {
return Ext.String.format(record.data.iconHtml);
};

var LoadNodes = function (store, operation, options) {
var node = App.TreeGridId.getStore().getNodeById(operation.da ta.id);
App.direct.LoadChildNodes(node.getId(), {
success: function (result) {
if (result.length > 0) {
node.set('loading', false);
node.set('loaded', true);
node.removeAll();
node.appendChild(result);
}
},
eventMask: {
showMask: true,
minDelay: 500
},
failure: function (errorMsg) {
Ext.Msg.alert('Failure', errorMsg);
}
});
}
</script>
</head>
<body>
<div>
@Html.X().ResourceManager()
@(Html.X().Container().ID("TreeGrid").Height(400).Items(
Html.X().TreePanel().ID("TreeGridId").Header(false)
.RootVisible(false)
.HideHeaders(true)
.Icon(Icon.None)
.UseArrows(true)
.Cls("no-node-icon")
.Fields(
Html.X().ModelField().Name("nodeText"),
Html.X().ModelField().Name("iconHtml").Type(ModelFieldType.String)
)
.ColumnModel(
Html.X().Column().Align(Alignment.Right).DataIndex ("iconHtml").Renderer("displayIcons").Width(75),
Html.X().TreeColumn().DataIndex("nodeText").Width(280)
)
.Root(Html.X().Node().NodeID("0").Text("All Notes").Children(Model))
.Listeners(x => x.BeforeItemClick.Fn = "LoadNodes")
)
)
</div>
</body>
</html>

Daniil
Feb 12, 2014, 5:54 AM
What about this way?
http://mvc.ext.net/#/TreePanel_Loaders/Direct_Method/

alscg
Feb 12, 2014, 4:29 PM
What about this way?
http://mvc.ext.net/#/TreePanel_Loaders/Direct_Method/

Hi Daniil,

We have tried this (http://mvc.ext.net/#/TreePanel_Loaders/Direct_Method/) and error is same.
7584

Here are the change according to 'http://mvc.ext.net/#/TreePanel_Loaders/Direct_Method/' in previous code.
Instead of code line
.Listeners(x => x.BeforeItemClick.Fn = "LoadNodes")
We changed it to
.Listeners(l => { l.BeforeLoad.Fn = "LoadNodes"; }) as per your suggestion.

Another change is code line
var node = App.TreeGridId.getStore().getNodeById(operation.da ta.id);
is replaced by code line
var node = operation.node;

But result is same, we got same ext.net exception window.

We also tried this 'http://mvc.ext.net/#/TreePanel_Loaders/Proxy/', It simply does not support TreeGrid feature.
Adding below line of code in markup gives error of not support this TreeGrid feature.


.Fields(
Html.X().ModelField().Name("nodeText"),
Html.X().ModelField().Name("iconHtml").Type(ModelFieldType.String)
)
.ColumnModel(
Html.X().Column().Align(Alignment.Right).DataIndex ("iconHtml").Renderer("displayIcons").Width(75),
Html.X().TreeColumn().DataIndex("nodeText").Width(280)
)


We need TreeGrid feature, because we want to display some icons on first column. This is our project requirement and with this feature now we want on demand loading as we have very large amount of Tree node data that can not be processed at start.

Here is modified code again in case you want to verify the changes as per your suggested link sample -

Controller Code (No change compared to previous)



[DirectController(GenerateProxyForOtherControllers = true, IDMode = DirectMethodProxyIDMode.None)]
public class ExtNetController : Controller
{
public ActionResult ProxyTree()
{
NodeCollection nodes = new NodeCollection();
Node node = new Node();
node.NodeID = "1000";
node.Text = "FirstNode";
for (int i = 0; i < 5; i++)
{
Node childnode = new Node();
childnode.NodeID = i.ToString();
childnode.Text = "Node " + i;
childnode.Expanded = false;
node.Children.Add(childnode);
childnode.AttributesObject = new { nodeText = "Node " + i, iconHtml = "<img src='iconImage.png' width='15' height='15' />" };
}

node.AttributesObject = new { nodeText = node.Text, iconHtml = "<img src='iconImage.png' width='15' height='15' />" };
nodes.Add(node);

return View(nodes);
}

[DirectMethod]
public ActionResult LoadChildNodes(string nodeId)
{
NodeCollection nodes = new Ext.Net.NodeCollection() {
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText1", AttributesObject = new {nodeText = "ChildNodeText1", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }},
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText2", AttributesObject = new {nodeText = "ChildNodeText2", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }},
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText3", AttributesObject = new {nodeText = "ChildNodeText3", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }},
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText4", AttributesObject = new {nodeText = "ChildNodeText4", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }}
};

if (nodeId == "1000")
{
return this.Direct(new Ext.Net.NodeCollection());
}
else
{
return this.Direct(nodes);
}
}
}


View code (change as explained above)


@model NodeCollection
<html>
<style>
.no-node-icon img.x-tree-icon
{
display: none;
}
</style>
<head>
<meta name="viewport" content="width=device-width" />
<title>ProxyTree</title>
<script type="text/javascript">
var displayIcons = function (value, meta, record, index) {
return Ext.String.format(record.data.iconHtml);
};

var LoadNodes = function (store, operation, options) {
var node = operation.node; // App.TreeGridId.getStore().getNodeById(operation.da ta.id);
App.direct.LoadChildNodes(node.getId(), {
success: function (result) {
if (result.length > 0) {
node.set('loading', false);
node.set('loaded', true);
node.removeAll();
node.appendChild(result);
}
},
eventMask: {
showMask: true,
minDelay: 500
},
failure: function (errorMsg) {
Ext.Msg.alert('Failure', errorMsg);
}
});
}
</script>
</head>
<body>
<div>
@Html.X().ResourceManager()
@(Html.X().Container().ID("TreeGrid").Height(400).Items(
Html.X().TreePanel().ID("TreeGridId").Header(false)
.RootVisible(false)
.HideHeaders(true)
.Icon(Icon.None)
.UseArrows(true)
.Cls("no-node-icon")
.Fields(
Html.X().ModelField().Name("nodeText"),
Html.X().ModelField().Name("iconHtml").Type(ModelFieldType.String)
)
.ColumnModel(
Html.X().Column().Align(Alignment.Right).DataIndex ("iconHtml").Renderer("displayIcons").Width(75),
Html.X().TreeColumn().DataIndex("nodeText").Width(280)
)
.Root(Html.X().Node().NodeID("0").Text("All Notes").Children(Model))
//.Listeners(x => x.BeforeItemClick.Fn = "LoadNodes")
.Listeners(l => { l.BeforeLoad.Fn = "LoadNodes"; })
)
)
</div>
</body>
</html>



Could it not be possible to make change to ignore the exception window in existing code, as other things are working as expected. Only this exception window comes with sending unnecessary request to parent action method (in this case 'ProxyTree()', might be root cause of this) which is not required.

Waiting for your positive response to fix this.

Thanks

Daniil
Feb 13, 2014, 3:00 AM
Could it not be possible to make change to ignore the exception window in existing code, as other things are working as expected. Only this exception window comes with sending unnecessary request to parent action method (in this case 'ProxyTree()', might be root cause of this) which is not required.


Well, you could prevent a default load request by:

.Listeners(l => { l.BeforeLoad.Handler = "return false"; })
and you need to expand a node manually in the success handler:


...
node.appendChild(result);
node.expand();

It is a solution for the sample with the BeforeItemClick.

alscg
Feb 13, 2014, 5:58 AM
Well, you could prevent a default load request by:

.Listeners(l => { l.BeforeLoad.Handler = "return false"; })
and you need to expand a node manually in the success handler:


...
node.appendChild(result);
node.expand();

It is a solution for the sample with the BeforeItemClick.

Hi Daniil,

Thanks for the fix, it worked for us.

alscg
Feb 17, 2014, 4:52 AM
Hi Daniil,

Thanks for the fix, it worked for us.

Hi Daniil,

I have applied the fix suggested by you.
But observed that when i expand the node which is appended on demand.
Action method request sent twice. I think request should be sent once only.

Please see the attached screen for firebug console.7597
In attached image you can see, first node is expanded and then child node of first is expanded.
So it should be two action method request but expanding first node's child node causes request twice.

Could you please let us know the reason for this and possible solution.

Here are the complete code -

Controller code


[DirectController(GenerateProxyForOtherControllers = true, IDMode = DirectMethodProxyIDMode.None)]
public class ExtNetController : Controller
{
public ActionResult ProxyTree()
{
NodeCollection nodes = new NodeCollection();
Node node = new Node();
node.NodeID = "1000";
node.Text = "FirstNode";
for (int i = 0; i < 5; i++)
{
Node childnode = new Node();
childnode.NodeID = i.ToString();
childnode.Text = "Node " + i;
childnode.Expanded = false;
node.Children.Add(childnode);
childnode.AttributesObject = new { nodeText = "Node " + i, iconHtml = "<img src='iconImage.png' width='15' height='15' />" };
}

node.AttributesObject = new { nodeText = node.Text, iconHtml = "<img src='iconImage.png' width='15' height='15' />" };
nodes.Add(node);

return View(nodes);
}

[DirectMethod]
public ActionResult LoadChildNodes(string nodeId)
{
NodeCollection nodes = new Ext.Net.NodeCollection() {
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText1", AttributesObject = new {nodeText = "ChildNodeText1", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }},
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText2", AttributesObject = new {nodeText = "ChildNodeText2", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }},
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText3", AttributesObject = new {nodeText = "ChildNodeText3", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }},
new Node(){NodeID = Guid.NewGuid().ToString(), Text = "ChildNodeText4", AttributesObject = new {nodeText = "ChildNodeText4", iconHtml= "<img src='iconImage.png' width='15' height='15' />" }}
};

if (nodeId == "1000")
{
return this.Direct(new Ext.Net.NodeCollection());
}
else
{
return this.Direct(nodes);
}
}
}


View code



@model NodeCollection
<html>
<style>
.no-node-icon img.x-tree-icon {
display: none;
}
</style>

<head>
<meta name="viewport" content="width=device-width" />
<title>ProxyTree</title>
<script type="text/javascript">
var displayIcons = function (value, meta, record, index) {
return Ext.String.format(record.data.iconHtml);
};

var LoadNodes = function (store, operation, options) {
var node = App.TreeGridId.getStore().getNodeById(store.data.i d);// operation.node; //
App.direct.LoadChildNodes(node.getId(), {
success: function (result) {
if (result.length > 0) {
node.set('loading', false);
node.set('loaded', true);
node.removeAll();
node.appendChild(result);
node.expand();
}
},
eventMask: {
showMask: true,
minDelay: 500
},
failure: function (errorMsg) {
Ext.Msg.alert('Failure', errorMsg);
}
});
}

var PreventDefaultRequest = function (store, operation, options) {
return false;
}

</script>
</head>
<body>
<div>
@Html.X().ResourceManager()
@(Html.X().Container().ID("TreeGrid").Height(400).Items(
Html.X().TreePanel().ID("TreeGridId").Header(false)
.RootVisible(false)
.HideHeaders(true)
.Icon(Icon.None)
.UseArrows(true)
.Cls("no-node-icon")
.Fields(
Html.X().ModelField().Name("nodeText"),
Html.X().ModelField().Name("iconHtml").Type(ModelFieldType.String)
)
.ColumnModel(
Html.X().Column().Align(Alignment.Right).DataIndex ("iconHtml").Renderer("displayIcons").Width(75),
Html.X().TreeColumn().DataIndex("nodeText").Width(280)
)
.Root(Html.X().Node().NodeID("0").Text("All Notes").Children(Model))
.Listeners(x => x.BeforeItemExpand.Fn = "LoadNodes")
.Listeners(x => x.BeforeLoad.Fn = "PreventDefaultRequest")
)
)
</div>
</body>
</html>

Daniil
Feb 17, 2014, 7:42 AM
I think this

.Listeners(x => x.BeforeItemExpand.Fn = "LoadNodes")
is executed again after

node.expand();

Could you, please, clarify why do you switch to BeforeItemExpand from BeforeItemClick?

alscg
Feb 17, 2014, 8:35 AM
I think this

.Listeners(x => x.BeforeItemExpand.Fn = "LoadNodes")
is executed again after

node.expand();

Could you, please, clarify why do you switch to BeforeItemExpand from BeforeItemClick?

Hi Daniil,

It was always 'BeforeItemExpand', in my previous posts by mistake 'BeforeItemClick' that was added (Sorry for this). And for most of the scenarios it was behaving similar to 'BeforeItemExpand'. I figured out this when you given me the fix with 'node.expand();'. In this case 'BeforeItemClick' not letting me collapse the the node once it is expanded, so even clicking node for collapse it again expanding this as we have used 'node.expand();'.

So i realize it and changed it to 'BeforeItemExpand', because this was my event to fetch on demand nodes.

But now with 'BeforeItemExpand' we have sending request twice issue, could please suggest the fix for this.

Thanks

Vladimir
Feb 17, 2014, 8:52 AM
You have to return false from LoadNodes
Please see online sample

Daniil
Feb 17, 2014, 10:41 AM
You have to return false from LoadNodes
Please see online sample

For clarification. Vladimir suggests to use the BeforeLoad event for your requirement. I would agree with him. It is better that BeforeItemExpand and BeforeItemClick.

Let's return back to this post.
http://forums.ext.net/showthread.php?28049&p=124954&viewfull=1#post124954

You should uncomment this line

//return false;
in the BeforeLoad event.

alscg
Feb 17, 2014, 11:20 AM
For clarification. Vladimir suggests to use the BeforeLoad event for your requirement. I would agree with him. It is better that BeforeItemExpand and BeforeItemClick.

Let's return back to this post.
http://forums.ext.net/showthread.php?28049&p=124954&viewfull=1#post124954

You should uncomment this line

//return false;
in the BeforeLoad event.

Hi Daniil,

Uncommenting the line
//return false; in method 'LoadNodes' stops expanding node. I am not even able to expand first node.

It was there when i took this code from original sample post 'http://mvc.ext.net/#/TreePanel_Loaders/Direct_Method/'. But keeping this line simply does not allow to expand node, which is useless. So i commented that out and node started expanding.

So i think uncommenting this is not working for us.

Thanks

Daniil
Feb 17, 2014, 11:41 AM
Please use

var node = operation.node;
instead of

var node = App.TreeGridId.getStore().getNodeById(store.data.i d);

There is a JavaScript error occurring on "store.data.id".

alscg
Feb 17, 2014, 12:40 PM
Please use

var node = operation.node;
instead of

var node = App.TreeGridId.getStore().getNodeById(store.data.i d);

There is a JavaScript error occurring on "store.data.id".

Hi Daniil,

Changing that is not working for me.7601



var node = operation.node; //App.TreeGridId.getStore().getNodeById(store.data.i d);


With 'BeforeItemExpand' below code is working for me


var node = App.TreeGridId.getStore().getNodeById(store.data.i d);


Please check the event you are using, it should be 'BeforeItemExpand'

Thanks

Daniil
Feb 17, 2014, 1:10 PM
Please check the event you are using, it should be 'BeforeItemExpand'

Repeat myself, we highly recommend you to use BeforeLoad instead of BeforeItemExpand.


For clarification. Vladimir suggests to use the BeforeLoad event for your requirement. I would agree with him. It is better that BeforeItemExpand and BeforeItemClick.

Let's return back to this post.
http://forums.ext.net/showthread.php?28049&p=124954&viewfull=1#post124954

You should uncomment this line

//return false;
in the BeforeLoad event.

So, my code was for the BeforeLoad event.

"store.data.id" works in a BeforeItemExpand, because the argument that you named "store" is not a Store, it is a record.

alscg
Feb 19, 2014, 5:20 AM
Repeat myself, we highly recommend you to use BeforeLoad instead of BeforeItemExpand.



So, my code was for the BeforeLoad event.

"store.data.id" works in a BeforeItemExpand, because the argument that you named "store" is not a Store, it is a record.

Hi Daniil,

Now i am getting very strange issue. As per your suggestion i changed my sample code to use 'BeforeLoad' event. And it is working.
This event getting fired each time when i expand the node.

Problem is with my rela project code, it's almost the same code as i have prepared for sample code for you.
Yet in real code 'BeforeLoad' event is not getting fired all the time when i expand tree node.

My real project code has four level node hierarchy, first two levels i populate with real nodes and rest two level with one dummy nodes.
Dummy nodes gets filled with real dynamic node when user expand that particular node or parent node.
So Till third level node i did not get 'BeforeLoad' event fired why i am not able to understand.

Although i am trying to reproduce the same in sample code. Meanwhile could you me any hint why this happening.

When and for which node 'BeforeLoad' event gets fired ?

Thanks

Daniil
Feb 19, 2014, 9:50 AM
The BeforeLoad event should fire on expnading of a non-leaf node if that node has no children. If a node has children or just one child, expanding of that node won't fire a BeforeLoad event.

So, if I understand you correctly, the node that you expand already have some dummy node, right? If so, what is the need of that dummy node?

alscg
Feb 20, 2014, 5:23 AM
The BeforeLoad event should fire on expnading of a non-leaf node if that node has no children. If a node has children or just one child, expanding of that node won't fire a BeforeLoad event.

So, if I understand you correctly, the node that you expand already have some dummy node, right? If so, what is the need of that dummy node?

Hi Daniil,

Yes, correct i got how 'BeforeLoad' fired.
My design of tree is not suitable currently for this as it has dummy node [Because earlier i used 'BeforeItemExpand' and for other reasons].

Yes i need to remove the dummy nodes and make my tree to work with 'BeforeLoad' event.

Thanks again Daniil for your support to understand and helping me to optimizing my tree code to work better.