jQuery UI Widgets › Forums › Navigation › Tree › jqxTree Load on Demand with Ajax: re-open issue
Tagged: #jquery-tree, ajax, javascript tree, jqwidgets tree, jqxtree, Tree
This topic contains 17 replies, has 8 voices, and was last updated by Todor 5 years, 5 months ago.
-
Author
-
Hello,
in your example source code of jqxTree in chapter Load on Demand with Ajax, the function that is bound to the expand event returns immediately if the event’s element is the root element:
if (tree.jqxTree('getItem', event.args.element).label == "Root") return
This prevents the view from repeatedly appending “Root Folder” children.
But assume your ajax.htm would look like this:
[ { "label": "Folder 1", "items": [{ "value": "ajax.html", "label" : "Loading..." } ] }, { "label": "Folder 2", "items": [{ "value": "ajax.html", "label" : "Loading..." } ] }, { "label": "Folder 3", "items": [{ "value": "ajax.html", "label" : "Loading..." } ] } ]
Now children will repeatedly be appended when reopening a parent and there is (of course) no static approach anymore.
I am looking for a pattern to solve the Reopen problem. The server is stateless so I need to make the loading decision in the client.
Do you have any suggestion/ideas?
Best regards,
ReneHello Rene,
Here is a modified version of the demo Load on Demand with Ajax.
<!DOCTYPE html><html lang="en"><head> <title id='Description'>This sample demonstrates how to load Tree Items via Ajax </title> <link rel="stylesheet" href="../../jqwidgets/styles/jqx.base.css" type="text/css" /> <script type="text/javascript" src="../../scripts/gettheme.js"></script> <script type="text/javascript" src="../../scripts/jquery-1.8.2.min.js"></script> <script type="text/javascript" src="../../jqwidgets/jqxcore.js"></script> <script type="text/javascript" src="../../jqwidgets/jqxbuttons.js"></script> <script type="text/javascript" src="../../jqwidgets/jqxscrollbar.js"></script> <script type="text/javascript" src="../../jqwidgets/jqxpanel.js"></script> <script type="text/javascript" src="../../jqwidgets/jqxtree.js"></script> <script type="text/javascript" src="../../jqwidgets/jqxexpander.js"></script> <script type="text/javascript"> $(document).ready(function () { var theme = getTheme(); // Create jqxTree var tree = $('#jqxTree'); var source = [{ label: "Root", expanded: true, items: [ { label: "Root Folder 1", items: [{ value: "ajax1.htm", label: 'Loading...'}] }, { label: "Root Folder 2", items: [{ value: "ajax2.htm", label: 'Loading...'}] } ] }]; tree.jqxTree({ source: source, theme: theme, width: 200 }); tree.bind('expand', function (event) { var label = tree.jqxTree('getItem', event.args.element).label; var $element = $(event.args.element); var loader = false; var loaderItem = null; var children = $element.find('ul:first').children(); $.each(children, function () { var item = tree.jqxTree('getItem', this); if (item && item.label == 'Loading...') { loaderItem = item; loader = true; return false }; }); if (loader) { $.ajax({ url: loaderItem.value, success: function (data, status, xhr) { var items = jQuery.parseJSON(data); tree.jqxTree('addTo', items, $element[0]); tree.jqxTree('removeItem', loaderItem.element); } }); } }); }); </script></head><body class='default'> <div id="jqxTree"> </div></body></html>
And here are the files:
ajax1.htm:
[{ "label": "Folder 1", "items": [{ "value": "ajax.htm", "label" : "Loading..." } ] },{ "label": "Folder 2", "items": [{ "value": "ajax.htm", "label" : "Loading..." } ] },{ "label": "Folder 3", "items": [{ "value": "ajax.htm", "label" : "Loading..." } ] }]
ajax2.htm:
[{"label": "Folder 5" },{"label": "Folder 6" },{"label": "Folder 7" },{"label": "Folder 8" }]
ajax.htm:
[{"label": "Folder 9" },{"label": "Folder 10" },{"label": "Folder 11" },{"label": "Folder 12" }]
Best Regards,
DimitarjQWidgets team
http://www.jqwidgets.com/Hi Dimitar
Thank you. That was quick. And it works.
Your code relies on a change of type of element e in tree.jqxTree(‘getItem’, e);
First call: HTMLLIELement that represents a tree item => ajax()
Second call: HTMLDivElement => no ajax()I rewrote the bind function as follows:
tree.bind(‘expand’, function(event) {
var parEl = event.args.element;
var $parEl = $(parEl);var childEl = $parEl.find(‘ul:first’).children();
var $childEl = $(childEl);// First call: HTMLLIELement that represents a tree item => ajax()
// Second call: HTMLDivElement => return
if (!tree.jqxTree(‘getItem’, $childEl[0])) {
return;
}var parItem = tree.jqxTree(‘getItem’, parEl)
var parLabel = parItem.label;
$.ajax({
url: ‘edtree_expand’,
data: {‘parent’: parLabel},
success: function (data, status, xhr) {
var items = jQuery.parseJSON(data);
tree.jqxTree(‘addTo’, items, $parEl[0]);
tree.jqxTree(‘removeItem’, $childEl[0]);
}
});return true;
});However, the fact that I can rely on the fact the *all* labels in my tree are different allows the following:
tree.bind(‘expand’, function(event) {
var parEl = event.args.element;
var $parEl = $(parEl);
var childEl = $parEl.find(‘li’);
var $childEl = $(childEl);var firstChildItem = tree.jqxTree(‘getItem’, $childEl[0]);
if (firstChildItem.label != loadingLabel.label)
return; // already loadedvar parItem = tree.jqxTree(‘getItem’, parEl);
$.ajax({
url : ‘edtree_expand’,
data: {‘parent’: parItem.label},
success : function(jsonData, status, xhr) {
tree.jqxTree(‘removeItem’, $childEl[0]);var childItems = jQuery.parseJSON(jsonData);
// time to render in jqxTree addTo is a problem:
tree.jqxTree(‘addTo’, childItems, parEl);
}
});
return true;
});Don’t know what I prefer. Anyway, my issue is solved. Thanks again!
Best regards,
RenéHi Peter and Rene.. I also want to load child with ajax for level 2 node.. I’ve try code above but children in level 2 already expanded when I expand level 1 node..
I’ve also got error like this in firebug :
I can not post image here…
The error is like this :
TypeError: o is undefined on jqxtree.js (line 7)Is jqxtree.js must be modified too ?
thx..can somebody help me please… i’m so confused…
I got an error in _refreshMapping when calling function _refreshMapping:function(f,q){
TypeError: o is undefined.in that function, i see var o has been initialized with var o=h[k.id];
but when I show the value of h[k.id], the value has a undefined value..Hello yehezqiel,
Do you experience the issue by running the code we provided or is it your own solution? In the latter case, please post a code sample, which we may test locally.
Best Regards,
DimitarjQWidgets team
http://www.jqwidgets.com/Thx for your response Dimitar..
I use code that you provided in documentation with a little modified by me.
But I don’t modified source code in jqxtree.js.
In firebug, there is an error there..Here is my code. I want to show a tree with 3 level.. Level 2 will be loaded by ajax when I expand or check node in level 1. And level 3 will be loaded when I expand or check node in level 2.. But level 3 has already loaded when I expand or check node in level 1.
I’ve try code which is posted by you Dimitar, but doesn’t work for me.Here is the JSP file.
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %><!DOCTYPE html><html lang="en"> <head> <link rel="stylesheet" href="../includes/css/jqxTree/jqx.base.css" type="text/css" /> <script type="text/javascript" src="../includes/js/jqxTree/gettheme.js"></script> <script type="text/javascript" src="../includes/js/jqxTree/jquery-1.8.2.min.js"></script> <script type="text/javascript" src="../includes/js/jqxTree/jqxcore.js"></script> <script type="text/javascript" src="../includes/js/jqxTree/jqxbuttons.js"></script> <script type="text/javascript" src="../includes/js/jqxTree/jqxscrollbar.js"></script> <script type="text/javascript" src="../includes/js/jqxTree/jqxpanel.js"></script> <script type="text/javascript" src="../includes/js/jqxTree/jqxtree.js"></script> <script type="text/javascript" src="../includes/js/jqxTree/jqxexpander.js"></script> <script type="text/javascript" src="../includes/js/jqxTree/jqxcheckbox.js"></script> <script type="text/javascript" src="../js/common.js"></script> <script type="text/javascript"> $(document).ready(function () { var theme = getDemoTheme(); var tree = $('#jqxTree'); $('#jqxTree').jqxTree({ checkboxes: true }); var source = [{ label: "All Category", expanded: true, value:"0", id:"parent", level:"0", checked:true, items: ${level1} }]; tree.jqxTree({ source: source, theme: theme, width: 600 }); tree.on('expand', function (event) { if (tree.jqxTree('getItem', event.args.element).value == 0) return; var $element = $(event.args.element); var loader = false; var loaderItem = null; var children = $element.find('li'); $.each(children, function () { var item = tree.jqxTree('getItem', this); if (item.label == 'Loading...') { loaderItem = item; loader = true; return false }; }); if (loader) { $.ajax({ url: loaderItem.value, success: function (data, status, xhr) { var items = jQuery.parseJSON(data); tree.jqxTree('addTo', items, $element[0]); tree.jqxTree('removeItem', loaderItem.element); } }); } }); $('#jqxTree').on('checkChange', function (event) { var args = event.args; var checked = args.checked; var item = $('#jqxTree').jqxTree('getItem', args.element); if(checked) { $("#jqxTree").jqxTree('expandItem', $("#"+item.id)[0]); } else { if(item.level==0) { $('#jqxTree').jqxTree('collapseAll'); $('#jqxTree').jqxTree('uncheckAll'); } else if(item.level==1) { $("#jqxTree").jqxTree('collapseItem', $("#"+item.id)[0]); var children = $(args.element).find("li"); $.each(children, function () { $("#jqxTree").jqxTree('uncheckItem', $("#"+this.id)[0]); }); } else { $("#jqxTree").jqxTree('collapseItem', $("#"+item.id)[0]); } } }); $(window).load() { if(${fromServer}) { $("#jqxTree").jqxTree('expandItem', $("#cat1")[0]); } } }); function submitForm() { var F = MM_findObj("form"); var items = $('#jqxTree').jqxTree('getCheckedItems'); var checkedItems = new Array(); $.each(items, function () { checkedItems[checkedItems.length] = this.value; }); var result=""; for(var i=0; i<checkedItems.length; i++) { result+=checkedItems[i]; if(i!=checkedItems.length-1) result+=","; } F.categorySelected.value=result; F.submit(); } </script> </head> <body class='default'> <div id="jqxTree"> </div> <br/><br/> <form:form method="post" name="form" id="form"> <input type="hidden" name="categorySelected" id="categorySelected" /> <input type="submit" value="submit" onclick="submitForm()" /> <br/><br/> </form:form> </body> </html>
And here is code in sever (I use java)
@RequestMapping(value = "/productCategory", method = RequestMethod.GET) public void getTest(Model model, HttpServletRequest request, HttpSession session) { String level1 = " [" + " { label: \"First\", value:\"1\", id:\"cat1\", level:\"1\", items: [{ value: \"getDataCategory?id=1\", label: 'Loading...'}] }," + " { label: \"Second\", value:\"2\",level:\"1\", id:\"cat2\", items: [{ value: \"getDataCategory?id=2\", label: 'Loading...'}] }" + " ] "; model.addAttribute("level1", level1); model.addAttribute("fromServer", false); }@RequestMapping(value = "/getDataCategory", method = RequestMethod.GET) public void getDataCategory(Model model, HttpServletRequest request, HttpSession session) { String id = request.getParameter("id"); String fromServer = request.getParameter("fromServer"); String result = ""; if (fromServer == null) { fromServer = ""; } if (fromServer.equals("true")) { if (id.equals("1")) { result = " [{\"label\": \"Women\", \"value\":\"3\", \"level\":\"2\", \"id\":\"cat3\" }," + "{\"label\": \"Men\", \"value\":\"4\", \"level\":\"2\", \"id\":\"cat4\", \"checked\":\"true\" }," + "{\"label\": \"Girls\", \"value\":\"5\", \"level\":\"2\", \"id\":\"cat5\" }," + "{\"label\": \"Boys\", \"value\":\"6\", \"level\":\"2\", \"id\":\"cat6\" }]"; } } else { if (id.equals("1")) { result = " [{\"label\": \"Women\", \"value\":\"3\", \"level\":\"2\", \"id\":\"cat3\" }," + "{\"label\": \"Men\", \"value\":\"4\", \"level\":\"2\", \"id\":\"cat4\", \"items\": [{ \"value\": \"getDataCategory?id=2\", \"label\": \"Loading...\"}] }," + "{\"label\": \"Girls\", \"value\":\"5\", \"level\":\"2\", \"id\":\"cat5\" }," + "{\"label\": \"Boys\", \"value\":\"6\", \"level\":\"2\", \"id\":\"cat6\" }]"; } else if (id.equals("2")) { result = " [{\"label\": \"One\", \"value\":\"7\", \"level\":\"2\", \"id\":\"cat7\" }," + "{\"label\": \"Two\", \"value\":\"8\", \"level\":\"2\", \"id\":\"cat8\" }," + "{\"label\": \"Three\", \"value\":\"9\", \"level\":\"2\", \"id\":\"cat9\" }," + "{\"label\": \"Four\", \"value\":\"10\", \"level\":\"2\", \"id\":\"cat10\" }]"; } } request.setAttribute("data", result); } @RequestMapping(value = "/productCategory", method = RequestMethod.POST) public void postDataCategory(Model model, HttpServletRequest request, HttpSession session) { String allCategorySelected = request.getParameter("categorySelected"); String level1 = " [" + " { label: \"Men\", value:\"1\", id:\"cat1\", level:\"1\",checked:true, items: [{ value: \"getDataCategory?id=1&fromServer=true\", label: 'Loading...'}] }," + " { label: \"Women\", value:\"2\",level:\"1\", id:\"cat2\", items: [{ value: \"getDataCategory?id=2\", label: 'Loading...'}] }" + " ] "; model.addAttribute("level1", level1); model.addAttribute("fromServer", true); }
Thank’s
Hi, I’m getting the same error over Firefox… on Chrome and IE the console is getting this error
“SCRIPT5007: No se puede establecer la propiedad ‘level’ de referencia nula o sin definir
jqxtree.js, Línea 7 Carácter 31905”I’m using the code of the example in this post… i’m using jqwidgwets version 1.7
best regards…
Hello,
We will test for the reported behaviour with the current version of jQWidgets. There has not been any issue with the previous version, 2.6.1.
Best Regards,
DimitarjQWidgets team
http://www.jqwidgets.com/I get error: Uncaught TypeError: Cannot set property ‘level’ of undefined.
Details:Uncaught TypeError: Cannot set property ‘level’ of undefined jqx-all.js:7
a.extend._refreshMapping jqx-all.js:7
e jqx-all.js:7
a.extend.addTo jqx-all.js:7
a.jqx.invoke jqx-all.js:7
a.jqx.jqxWidgetProxy jqx-all.js:7
(anonymous function) jqx-all.js:7
b.extend.each jquery-1.9.1.min.js:3
b.fn.b.each jquery-1.9.1.min.js:3
a.fn.(anonymous function) jqx-all.js:7
(anonymous function) test.php:39
b.event.dispatch jquery-1.9.1.min.js:3
v.handle jquery-1.9.1.min.js:3
b.event.trigger jquery-1.9.1.min.js:3
(anonymous function) jquery-1.9.1.min.js:4
b.extend.each jquery-1.9.1.min.js:3
b.fn.b.each jquery-1.9.1.min.js:3
b.fn.extend.trigger jquery-1.9.1.min.js:4
a.extend._raiseEvent jqx-all.js:7
(anonymous function) jqx-all.js:7
r.complete jquery-1.9.1.min.js:5
c jquery-1.9.1.min.js:3
p.fireWith jquery-1.9.1.min.js:3
u jquery-1.9.1.min.js:5
b.fx.tick jquery-1.9.1.min.js:5Source code:
<!DOCTYPE html><html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <script src="Framework/Scripts/jquery-1.9.1.min.js"></script> <script src="Framework/Scripts/jqwidgets/jqx-all.js"></script> <link rel="stylesheet" href="Framework/Styles/jqx.base.css" type="text/css" /> <script type="text/javascript"> $(document).ready(function () { // Create jqxTree var tree = $('#jqxTree'); var source = [{ label: "Root", expanded: true, items: [ { label: "Root Folder 1", items: [{ value: "ajax1.htm", label: 'Loading...'}] }, { label: "Root Folder 2", items: [{ value: "ajax2.htm", label: 'Loading...'}] } ] }]; tree.jqxTree({ source: source, width: 200 }); tree.bind('expand', function (event) { var label = tree.jqxTree('getItem', event.args.element).label; var $element = $(event.args.element); var loader = false; var loaderItem = null; var children = $element.find('ul:first').children(); $.each(children, function () { var item = tree.jqxTree('getItem', this); if (item && item.label == 'Loading...') { loaderItem = item; loader = true; return false }; }); if (loader) { var items = new Array(); items.push({label: 'l', value: 'v', items: [{label: "Nalagam...", value: "nalagam"}]}) tree.jqxTree('addTo', items, $element[0]); tree.jqxTree('removeItem', loaderItem.element); } }); }); </script></head><body class='default'> <div id="jqxTree"> </div></body></html>
Hi Makla,
Please, see this Online Sample: http://www.jqwidgets.com/jquery-widgets-demo/demos/jqxtree/ajaxloading.htm?web. It shows how the jqxTree Items can be loaded on demand.
Best Regards,
Peter StoevjQWidgets Team
http://www.jqwidgets.com/Why is this not OK?
var items = new Array();items.push({label: 'l', value: 'v', items: [{label: "Nalagam...", value: "nalagam"}]})tree.jqxTree('addTo', items, $element[0]);
I am loading all kind of staff on demand. So I want to create items manually. I don’t see any difference between my code and the example code. My code is based on: load on demand example.
I don’t understand this. First is OK and second is with error.
tree.jqxTree('addTo', { label: 'Item', value: 'value' }, $element[0]); //OKtree.jqxTree('addTo', { label: 'Item', value: 'value', items: [{label: "Nalagam...", value: "nalagam"}]}, $element[0]); //error
Hi, i have this issue too!
When i clicked on arrow to load node’s children, node has collapsed quickly.
I’m using jqwidget v6.1.0, jqxtree component.this is my code:
function TreeNode(id, parentid, text, value) {
var self = this;
self.id = id;
self.parentid = parentid;
self.text = text;
self.value = value;
}function toId(input) {
return input == null ? “-1″ : input + ”;
}var mydata = {
UserId: userid
}
$.ajax({
url: “api/dashboard/getTreeRoot”,
type: “Post”,
data: mydata,
async: false
})
.done(function (tree) {
$(‘#jqxLoader’).jqxLoader(‘close’);
self.showLoader(false);var nodes = [];
for (var i in tree) {var node = tree[i];
nodes.push(new TreeNode(
toId(node.FldId),
toId(node.FldParentId),
node.FldNameFarsi,
node.FldId));
}
var source =
{
datatype: “json”,
datafields: [
{ name: ‘id’ },
{ name: ‘parentid’ },
{ name: ‘text’ },
{ name: ‘value’ }
],
id: ‘id’,localdata: nodes
};
var dataAdapter = new $.jqx.dataAdapter(source);
dataAdapter.dataBind();
var records = dataAdapter
.getRecordsHierarchy(‘id’, ‘parentid’, ‘items’, [{ name: ‘text’, map: ‘label’ }]);
$(‘#jqxTree’)
.jqxTree({
source: records,
width: ‘100%’,
height: ‘320px’,
rtl: true,
checkboxes: true,
hasThreeStates: true,
theme: ‘material’
});
}).fail(function () {});
-
AuthorPosts
You must be logged in to reply to this topic.