Getting JSON Data

1,570 views
Skip to first unread message

Michael D

unread,
Jan 31, 2014, 1:28:38 PM1/31/14
to jst...@googlegroups.com
Hi,

I have an MVC app that I am trying to use with your plugin.  Currently this is what I have, and it works:

    <script src="~/Scripts/jstree.js"></script>
   
<script type="text/javascript">
 
        $
(function () {
           
LoadTree(function (result) {
                $
('#tree').jstree({
                   
"core": {
                       
"data": result,
                       
"multiple": false,
                       
"animation": 200,
                       
"check_callback": true,
                       
"themes": {
                           
"icons": false,
                           
"stripes": true,
                           
"dots": true
                       
}
                   
},
                   
"plugins": ["state", "types", "wholerow"]  //"dnd", "contextmenu", "search",  
               
});
           
});
        });
       function LoadTree(callback) {
            $
.ajax({
                type
: 'GET',
                url
: '/Edit/LoadTree',
                dataType
: 'text',
                contentType
: 'application/json',
                cache
: false,
                success
: function (data) {
                    callback
(JSON.parse(data));
               
},
                error
: function (xhr, ajaxOptions, error) {
                    alert
(xhr.status);
                    alert
('Error: ' + xhr.responseText);
               
}
           
});
       
}
    </script>


However I need to be able to refresh the data, so I'm trying to switch it to something like this:

    <script src="~/Scripts/jstree.js"></script>
   
<script type="text/javascript">

 
        $(
function () {
            $('#tree').jstree({
               
"core": {
                   
'data': {
                        type:
'GET',
                        url:
function () { return '/Edit/LoadTree'; },
                        dataFilter:
function (response) {
                           
return JSON.parse(response);
                        }
                    },
                   
"multiple": false,
                   
"animation": 200,
                   
"check_callback": true,
                   
"themes": {
                       
"icons": false,
                       
"stripes": true,
                       
"dots": true
                    }
                },
               
"plugins": ["state", "types", "wholerow"]  //"dnd", "contextmenu", "search",  
            });
        });
   }

I need to JSON.parse() the return value because the data is coming from C# as a string.  Running through JSON.parse() returns a valid JSON string.

However, with the bottom set of code, I get this error "Uncaught TypeError: Object #<Object> has no method 'cloneNode'"

Any help would be greatly appreciated!

Michael D

unread,
Jan 31, 2014, 10:41:47 PM1/31/14
to jst...@googlegroups.com
Okay, thank-you for your help Ivan.  One last question.

If I update the tree calling "$('#tree').jstree("refresh");", all the nodes collapse.  However if I reload the page, they expand back to their previous state prior to the refresh.  Is this by design?  Is there any way to keep the state of which nodes are expanded or collapsed when a refresh occurs?

Ivan Bozhanov

unread,
Feb 1, 2014, 4:20:42 AM2/1/14
to jst...@googlegroups.com
Do you have node IDs that are unique (and specified by you in the data)?

Michael D

unread,
Feb 1, 2014, 8:39:43 AM2/1/14
to jst...@googlegroups.com
I do have node id's, however they are not in the JSON so thus the tree never knows about them.  By adding them it should keep the structure on reload?  I'll go ahead and try it.  Thank-you again!

Michael D

unread,
Feb 4, 2014, 3:45:10 PM2/4/14
to jst...@googlegroups.com
Alright, last question.  I would make a new topic, but it's pretty similar.

I went with your approach without modifying the headers.  I've tried a few times and I cannot seem to get it to work.  However using the code you provided and adding "contentType: 'application/json'" worked great.

Now I'm trying to search.

The following code almost works, however it gives the error that the object is not a JSON object, because I can't figure out how to run the return value through a JSON.parse().
               "search": {
                   
"ajax": {
                        url
: "/Reports/SearchTree",
                        dataType
: 'text',
                        contentType
: '
application/json',
                        data: function () {
                           
return this.data.search.str;
                       
}
                   
}
               
},

Any idea?

Thank-you again for your help!

Ivan Bozhanov

unread,
Feb 4, 2014, 5:27:25 PM2/4/14
to jst...@googlegroups.com
If you do not have control over what your server returns - try using jquery's dataFilter ajax option.

Michael D

unread,
Feb 5, 2014, 8:13:56 AM2/5/14
to jst...@googlegroups.com
Hi Ivan,

So I changed my method to this:

                "search": {
                   
"ajax": {
                        url
: "/Reports/SearchTree",
                        dataType
: 'text',
                        contentType
: 'application/json',
                        data
: function () {
                           
return this.data.search.str;
                       
},

                        cache
: false,
                        dataFilter
: function (response) {
                            console
.log(JSON.parse(response));
                           
return JSON.parse(response);
                       
}
                   
}
               
},

In the console.log, the JSON object appears to be correct.  However I get the following error:
Uncaught TypeError: Object #<Object> has no method 'concat'

The error is in jstree.js on line 4986, which is the 5th line in the following code ($.each(....)):
                this._search_load = function (d, str) {
var res = true,
t = this,
m = t._model.data;
$.each(d.concat([]), function (i, v) {
if(m[v]) {
if(!m[v].state.loaded) {
t.load_node(v, function () { t._search_load(d, str); });
res = false;
}
}
});
if(res) {
this.search(str, true);
}
};

Ivan Bozhanov

unread,
Feb 5, 2014, 9:01:55 AM2/5/14
to jst...@googlegroups.com
Please set
dataType: 'text',

to 'json' (not text), and lose the dataFilter - all you need to do is return a string from the server in the format: ["asfd","asdf2"]

Michael D

unread,
Feb 5, 2014, 9:41:27 AM2/5/14
to jst...@googlegroups.com
Hi Ivan,

I've tried almost everything to return a JSON object by modifying the headers, and I'm not getting anywhere with it.

            Response.Headers.Add("Content-type", "text/json");
           
Response.Headers.Add("Content-type", "application/json");
           
Response.Write(JsonConvert.SerializeObject(all));

When I load JSON method myself, it returns:
"{ "id": "All", "text": "All Results", "children": [.........]}"

But I still have the same error.
Uncaught TypeError: Object #<Object> has no method 'concat'

One thing I did try was to return a simple string, same format, and updated the datatype as you suggested.  If I have my JSTree as follows, I don't receive any error, however the tree doesn't update.
            $('#treeReport').jstree({
               
"core": {
                   
'data': function (node, cb) {
                       
var vars = {
                           
Action: 'Load'
                       
}
                        $
.ajax({
                            type
: 'POST',
                            url
: '/Edit/LoadTree',

                            dataType
: 'text',
                            contentType
: 'application/json',

                            data
: JSON.stringify(vars),
                            cache
: false
                       
}).done(function(d) { cb(JSON.parse(d)); })

                   
},
                   
"multiple": false,
                   
"animation": 200,
                   
"check_callback": true,

                   
"state": { "key": "tree" },

                   
"themes": {
                       
"icons": false,
                       
"stripes": true,
                       
"dots": true
                   
}
               
},

               
"search": {
                   
"ajax": {
                        url
: "/Reports/SearchTree",

                        dataType
: 'json',

                        contentType
: 'application/json',
                        data
: function () {
                           
return this.data.search.str;
                       
},
                        cache
: false,
                        dataFilter
: function (response) {
                            console
.log(JSON.parse(response));
                           
return JSON.parse(response);
                       
}
                   
}
               
},

               
"plugins": ["state", "types", "wholerow", "search"]  //"dnd", "contextmenu",  
           
});

Thank-you for your patience with me through this.

Michael D

unread,
Feb 5, 2014, 11:09:19 AM2/5/14
to jst...@googlegroups.com
Alright well I really did a hack here, but it works.  I run a function that calls my C# method, parses the result to JSON, then updates the data source for the tree.  After calling refresh, the tree has the new results.  I know it isn't perfect, but it works for my needs.  Thank-you again for all your work on this amazing plugin!

Ivan Bozhanov

unread,
Feb 5, 2014, 4:49:09 PM2/5/14
to jst...@googlegroups.com
I am glad it is working now, I just wanted to clarify - your data was fine - I believe the problem was with the response for the search call :) You had the error in the search plugin ... That AJAX call was broken, not the one from core.data. The search AJAX should return something like:
["id-to-open-1","some-other-id-to-open"]
With JSON headers of course.

Cheers,
Ivan

Michael D

unread,
Feb 6, 2014, 10:56:54 AM2/6/14
to jst...@googlegroups.com
Okay, that makes sense.  Thank again for all of your help!

JBP

unread,
Feb 6, 2014, 12:48:06 PM2/6/14
to jst...@googlegroups.com
Hi, first of all thanks for this great plugin.

Got almost the same problem and Firefox only throws a TypeError: context is undefined in jQuery Sizzle.contains and then i tryed with Chrome (better stack trace) and found that jsTree threated the data as html instead of json so the dataType specified in the ajax data is not mandatory.

The correct solution is to use application/json but be could make dataType mandatory adding the following code to jstree.js in _load_node function before
var type = x.getResponseHeader('Content-Type');

if (s.dataType = 'json')
{
 
return callback.call(this, this._append_json_data(obj, d));
}


Message has been deleted

Ivan Bozhanov

unread,
Feb 6, 2014, 2:19:28 PM2/6/14
to jst...@googlegroups.com
I gave in on the .d property and it is now handled, but I will not give in on something as simple as headers - it cannot be that hard to return a properly formatted string with a single header of "application/json".

Best regards,
Ivan

Ivan Bozhanov

unread,
Jan 31, 2014, 3:22:12 PM1/31/14
to jst...@googlegroups.com
You do not need the dataFilter function. You need to fix your headers - you are returning the response with a wrong Content-Type header of "text/html" instead of "application/json" - fix that and everything will work as expected. If you do not know how to fix that - search the group - there was question about a day ago about this same problem - the answer is here. Or you can use a work around - configure data as a function:

                    'data': function (node, cb) { 
$.ajax(
                        type:
'GET',
dataType : 'json',
                        url:
function () { return '/Edit/LoadTree'; }
                        }).done(function(d) { cb(JSON.parse(d)); })
                    },


However - I would really advise to simply fix your Content-Type header, that will also make the use of JSON.parse unnecessary.
Best regards,
Ivan

Ahmed Khateeb

unread,
Jan 30, 2018, 6:06:08 AM1/30/18
to jsTree
This is a great workaround, it is working for me now. I had to add token in header in jstree request.
Reply all
Reply to author
Forward
0 new messages