get_node('#').children for root nodes results in undefined error

2,654 views
Skip to first unread message

Chris Meza

unread,
Jun 17, 2014, 7:29:07 PM6/17/14
to jst...@googlegroups.com
What is the correct way to reference the trees root nodes as a list of IDs?

I was hoping this would work:
var ids = instance.get_node('#').children;

Instead I get an undefined error. I'm not seeing anything in the docs or this group on how to specifically get the list of IDs of all the root nodes. I can manually write a jQuery selector to get the list of LIs of the root UL & collect the IDs into the array, but I'm curious if there is a built in method I'm not seeing.

Thanks.

PS: Ivan, I'm REALLY digging jsTree & have thoroughly enjoyed working with it & I sincerely appreciate the feedback/time you put into it & managing this group! Expect a donation soon (payday is Friday, but I'll be out of town this weekend).

Chris Meza

unread,
Jun 17, 2014, 7:39:07 PM6/17/14
to jst...@googlegroups.com
$('#jsTreeId ul.jstree-container-ul li').each(function(){
    console.log("ROOT ID", $(this).attr('id'));
});

This outputs my root node IDs, build the array, etc etc, but curious if I just missed something?

Ivan Bozhanov

unread,
Jun 18, 2014, 1:33:46 AM6/18/14
to jst...@googlegroups.com
That is really odd - I just tested this and using:
jQuery('#tree_id').jstree(true).get_node('#').children
returns an array of root nodes IDs - are you sure you tested your code after the "ready.jstree" event? Or that "instance" is really the instance you need - try with the selector. Sorry for asking such questions, but I really cannot reproduce the problem.

Best regards,
Ivan

Chris Meza

unread,
Jun 18, 2014, 11:08:32 AM6/18/14
to jst...@googlegroups.com
Yes, I have. Here is all my code related to this:

var jstEdit;

$('#types-list-edit')
.on('move_node.jstree', function(e, jst) {
    console.log("DROPPED", jst);
    updatePositions(jst);
})
.jstree({
    "checkbox" : {
        "keep_selected_style" : false
    }
   ,"core" : {  
       'data' : {
            'url' : '/api/getTree',
            'data' : function (node) {
                return { 'id' : node.id };
            }
        }
       ,'check_callback' : true
   }
   ,"plugins" : [ 
        "contextmenu"
       ,"unique"
       ,"dnd"
       ,"sort"
       ,"wholerow"
   ]
   ,'contextmenu' : {
       'select_node' : false
   }
   ,'sort' : function(node1, node2) {return sortNodes("edit", node1, node2)}
});

jstEdit = $.jstree.reference('#types-list-edit');

// other stuff here, not related to this

function updatePositions(jst) {
    var updates = [];
    var parents = [];
    
    // always add the current parent
    parents.push(jst.parent);
    
    // add old_parent to parents array if this move changed parents for the node
    if (jst.parent != jst.old_parent) {
        parents.push(jst.old_parent);
    }
    
    // loop thru the parents
    for (y = 0; y < parents.length; y++) {
        // get the array of children ids from the parent
        if (parents[y] == '#') {
            var nodes = [];
            $('#types-list-edit ul.jstree-container-ul li').each(function(){
                // console.log("ROOT ID", $(this).attr('id'));
                nodes.push($(this).attr('id'));
            });
        } else {
            var nodes = jstEdit.get_node(parents[y]).children;
        }
        
        // loop thru the nodes ids array
        for (x = 0; x < nodes.length; x++) {
            var node = jstEdit.get_node(nodes[x]);
            
            // update the position, only if it's different
            if (node.data.position != x) {
                node.data.position = x;
                
                // update parent to be an int for DB PK
                if (node.parent == "#") {
                    node.parent = 0;
                }
            
                // build the object & add to updates array
                updates.push({
                           id : node.id
                      ,parent : node.parent
                    ,position : node.data.position
                });
            }
        }
    }
}   
    

/api/getTree returns this:
[
    {
a_attr : "",
icon : "",
id : 6,
li_attr : "",
parent : 5,
text : "P2",
data : {
position : 5
}
}, {
a_attr : "",
icon : "",
id : 36,
li_attr : "",
parent : 46,
text : "36",
data : {
position : 0
}
}, {
a_attr : "",
icon : "",
id : 37,
li_attr : "",
parent : "#",
text : "P5",
data : {
position : 4
}
}, {
a_attr : "",
icon : "",
id : 38,
li_attr : "",
parent : "#",
text : "P6",
data : {
position : 5
}
}, {
a_attr : "",
icon : "",
id : 39,
li_attr : "",
parent : 46,
text : "39",
data : {
position : 0
}
}, {
a_attr : "",
icon : "",
id : 40,
li_attr : "",
parent : 46,
text : "40",
data : {
position : 0
}
}, {
a_attr : "",
icon : "",
id : 41,
li_attr : "",
parent : "#",
text : "P3",
data : {
position : 2
}
}, {
a_attr : "",
icon : "",
id : 42,
li_attr : "",
parent : 6,
text : "C5",
data : {
position : 0
}
}, {
a_attr : "",
icon : "",
id : 43,
li_attr : "",
parent : 46,
text : "43",
data : {
position : 0
}
}, {
a_attr : "",
icon : "",
id : 45,
li_attr : "",
parent : 41,
text : "C6",
data : {
position : 0
}
}, {
a_attr : "",
icon : "",
id : 46,
li_attr : "",
parent : "#",
text : "P1",
data : {
position : 0
}
}, {
a_attr : "",
icon : "",
id : 47,
li_attr : "",
parent : "#",
text : "P4",
data : {
position : 3
}
}, {
a_attr : "",
icon : "",
id : 48,
li_attr : "",
parent : 46,
text : "48",
data : {
position : 0
}
}, {
a_attr : "",
icon : "",
id : 49,
li_attr : "",
parent : 46,
text : "49",
data : {
position : 0
}
}
]




Uncaught TypeError: Cannot read property 'children' of undefined jstree.js:1708
$.jstree.core.redraw_node jstree.js:1708
$.jstree.plugins.wholerow.redraw_node jstree.js:6013
$.jstree.core._redraw jstree.js:1590
$.jstree.core.redraw jstree.js:1623
$.jstree.core.redraw_node jstree.js:1647
$.jstree.plugins.wholerow.redraw_node jstree.js:6013
(anonymous function) jstree.js:5552
n.extend.proxy.n.isFunction.e jquery.js:2
n.event.dispatch jquery.js:3
n.event.add.r.handle jquery.js:3
n.event.trigger jquery.js:3
n.fn.extend.triggerHandler jquery.js:3
$.jstree.core.trigger jstree.js:693
$.jstree.core.move_node jstree.js:3180
$.jstree.core.move_node jstree.js:3052
(anonymous function) jstree.js:4898
n.event.dispatch jquery.js:3
n.event.add.r.handle jquery.js:3
n.event.trigger jquery.js:3
n.fn.extend.triggerHandler jquery.js:3
$.vakata.dnd._trigger jstree.js:4946
$.vakata.dnd.stop jstree.js:5152
n.event.dispatch jquery.js:3
n.event.add.r.handle jquery.js:3

So, this is where I'm at today. I no longer fail because I do the manual jQuery selector since get_nodes('#').children bombs on me (I'll do it & see if it bombs with a similar stack trace). Odd thing is, I walked thru the above & I did not ever hit get_nodes(parents[y]).children if I was dealing with a root node . . . yet I *STILL* got the children error. 

Chris Meza

unread,
Jun 18, 2014, 11:10:22 AM6/18/14
to jst...@googlegroups.com
I forgot to include the sortNodes function:

function sortNodes(jstInstance, node1, node2) {
    if (jstInstance == "associate") {
        var a = jstAssoc.get_node(node1);
        var b = jstAssoc.get_node(node2);
    } else {
        var a = jstEdit.get_node(node1);
        var b = jstEdit.get_node(node2);
    }
    
    var a_pos = a.data.position;
    var a_name = a.text;
    
    var b_pos = b.data.position;
    var b_name = b.text;
    
    // sort by position if position values are present
    if (parseInt(a_pos) > -1 && parseInt(b_pos) > -1) {
        if (parseInt(a_pos) > parseInt(b_pos)) {
            return 1;
        } else {
            return -1;
        }
    } else {
        // if no position values, sort alphabetical
        if (a_name > b_name) {
            return 1;
        } else {
            return -1;
        }
    }
}




On Tuesday, June 17, 2014 6:29:07 PM UTC-5, Chris Meza wrote:

Chris Meza

unread,
Jun 18, 2014, 11:37:10 AM6/18/14
to jst...@googlegroups.com
Also, this is 3.0.0-0-gb446e66.


On Tuesday, June 17, 2014 6:29:07 PM UTC-5, Chris Meza wrote:

Chris Meza

unread,
Jun 18, 2014, 2:40:41 PM6/18/14
to jst...@googlegroups.com
AH Ok, now I know an issue is with my data for one. I had my middleware dev modify data for testing & he set a parent to a non-existent value. 

So, it bombs on any parent that doesn't exist.

Ivan Bozhanov

unread,
Jun 18, 2014, 3:02:01 PM6/18/14
to jst...@googlegroups.com
With flat data make sure the structure is OK. Tell me if you still have issues after fixing the structure.

Chris Meza

unread,
Jun 18, 2014, 3:28:49 PM6/18/14
to jst...@googlegroups.com
It wasn't the structure, but was the fact that the parent did not exist.

Here is the following changes I made to my function. The get_node('#').children was a red herring as it had more to do with the data vs jstree functionality. In my code, I was setting node.data.position = 0 if it was root so I could store the value in the DB as a FK int. I fixed it below:


function updatePositions(e, jst) {
    var updates = [];
    var parents = [];
    
    // always add the current parent
    parents.push(jst.parent);
    
    // add old_parent to parents array if this move changed parents for the node
    if (jst.parent != jst.old_parent) {
        parents.push(jst.old_parent);
    }
    
    // loop thru the parents
    for (y = 0; y < parents.length; y++) {
        // get the array of children ids from the parent
        var nodes = jstEdit.get_node(parents[y]).children;
        
        // loop thru the nodes ids array
        for (x = 0; x < nodes.length; x++) {
            var node = jstEdit.get_node(nodes[x]), position, parent;
            
            // update the position, only if it's different
            if (node.data.position != x) {
                position = x;
                
                // update parent to be an int for DB PK
                parent = (node.parent == "#") ? 0 : node.parent
                
                // build the object & add to updates array
                updates.push({
                           id : node.id
                      ,parent : parent
                    ,position : position
                });
            }
        }
    }
    
    // submit results
    $.ajax({
         url : '/api/updateThemePositions'
       ,type : 'POST'
       ,data : {'themes' : updates} 
    })
    .done(function(response) {
        notifyUser('Theme positions modification(s).', response.success)
    });
}
Reply all
Reply to author
Forward
0 new messages