Treeview from MOSS 2007 List

Feb 26, 2013 at 9:48 AM
Help!

I'm trying to create a tree view (in a web part) from data contained in a custom list (called FilePlan). The list contains a parentID, ChildID and Name fields (amongst others). I have searched the web and tried adapting a number of examples, but have been unable to get anything to work. I'm fairly new to jQuery and obviously don't have enough knowledge to get this working. I can't use any third party software and don't have access to the server, so it all needs to sit on the client side. We're running SharePoint 2007 with no access to SharePoint Designer either. Any help, preferably some usable code, would be much appreciated. Many thanks.
Feb 26, 2013 at 1:52 PM
I've built this out using JS CSOM, not SPServices b/c the web services can't handle folders correctly. To date, this is the only tree view library worth anything to write about:

http://wwwendt.de/tech/dynatree/doc/samples.html
http://wwwendt.de/tech/dynatree/index.html

This all works client side, so you'll be able to use it within your restrictions.

Cheers,
Matthew
Feb 26, 2013 at 6:38 PM
Thanks Matthew. Some excellent examples. I can see many possibilities using Dynatree, but how do I get the data from a SharePoint list into JSON format and link that into your code?

Paul
Feb 26, 2013 at 7:32 PM
Unfortunately, I cannot share this code (contract details)... To get the data in JSON format, SPServices has an XML to JSON function or if you are using SP2010 and above, you can use CSOM or REST API's.

If you get some code working, I'll be happy to help you along with it.

Cheers,
Matthew
Feb 26, 2013 at 10:43 PM
Hey Matt.
Re: "...web services can't handle folders correctly."

Can you say a few more words on this. I might have the need soon to walk a folder structure and thought that I could get a list of folders and files within a given folder using WebServices.

Let us know.

Thanks.

_____
Paul

Sent from mobile device.
Coordinator
Feb 27, 2013 at 4:07 AM
I was curious about Matt's comment, too. I might require a lot of calls if there are deeply nested folders, but I'm not sure why it wouldn't work.

M.
Feb 27, 2013 at 12:43 PM
Edited Feb 27, 2013 at 12:49 PM
@ptavares:
The problems I've run into are related to this thread, at the bottom you'll notice I have to delete items, wholesale copy of values, then recreate them.
http://spservices.codeplex.com/discussions/288548

I relied on CSOM for the TreeNav because the solution uses the drag and drop feature. I have ran into issues in the past using web services to move items/folders around, so that's the main pain point. CSOM works as expected.

Cheers,
Matthew
Coordinator
Feb 27, 2013 at 1:30 PM
So this issue wasn't in creating a tree view, but in moving items around in the hierarchy? You definitely can't move an item; it's got to be a copy and delete, which really isn't the same thing.

M.
Feb 27, 2013 at 3:00 PM
Edited Feb 27, 2013 at 3:21 PM
@sympmarc Exactly...

It became a show stopper on one project, so it seemed appropriate to share that experience upfront with PaulM22.

Cheers,
Matthew
Feb 27, 2013 at 7:59 PM
Edited Feb 27, 2013 at 8:12 PM
Hi guys,

Thanks for the advice so far. Just to clarify, I'm not interested in the drag and drop functionality for my project, simply to create a tree structure on a web part page from a SP2007 list. I can get a tree by using Dynatree and a static json data file, but I need to be able to generate the tree from the list in which the data regularly changes. I can presumably extract the data from the list in JSON format and supply that to Dynatree? If so, how?

Thanks
Paul
Coordinator
Feb 27, 2013 at 8:09 PM
Paul:

I haven't used Dynatree, but the basic idea would be to use GetListItems to grab the list items and either use SPXmlToJson or some custom code to convert to JSON.

M.
Feb 27, 2013 at 9:33 PM
Thanks Matt...
I'm glad to hear that reading and displaying the data is not an issue...
Thanks for the reference post.


_________
Paul T


On Wed, Feb 27, 2013 at 4:09 PM, sympmarc <notifications@codeplex.com> wrote:

From: sympmarc

Paul:

I haven't used Dynatree, but the basic idea would be to use GetListItems to grab the list items and either use SPXmlToJson or some custom code to convert to JSON.

M.

Read the full discussion online.

To add a post to this discussion, reply to this email (SPServices@discussions.codeplex.com)

To start a new discussion for this project, email SPServices@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com


Feb 28, 2013 at 1:50 PM
I've had a go and managed to create a JSON output from the GetListItems XML output, and although I can see the individual items in the array I don't know how I can see the whole JSON file. I guess the JSON file needs to be formatted a certain way to feed DynaTree? Here's what I have so far:
<script language="javascript" type="text/javascript">
$(document).ready(function() {
  $().SPServices({
    operation: "GetListItems",
    async: false,
    listName: "MOSS Fileplan",
    CAMLViewFields: "<ViewFields><FieldRef Name='Title' /><FieldRef Name='Parent_URL' /><FieldRef Name='Process' /></ViewFields>",
    CAMLQuery: "<Query><Where><Eq><FieldRef Name='Parent_URL' /><Value Type='Text'>" + "S10" + "</Value></Eq></Where></Query>",
    completefunc: function (xData, Status) {
      $(xData.responseXML).find("[nodeName='z:row']").each(function() {
        //alert(xData.responseXML.xml);
        var myJson = $(xData.responseXML).SPFilterNode("z:row").SPXmlToJson({
          mapping: {
            ows_ID: {mappedName: "ID", objectType: "Counter"},
            ows_Title: {mappedName: "MdbaUrl", objectType: "Text"},
            ows_Process: {mappedName: "Process", objectType: "Text"},
            ows_Parent_URL: {mappedName: "ParentUrl", objectType: "Text"}
          }, // name, mappedName, objectType
          includeAllAttrs: false,
          removeOws: true
        });
        // To read a field it is ALWAYS $(this).attr("ows_<internal field name>");
        var liHtml = "<li>" + $(this).attr("ows_Process") + " (" + $(this).attr("ows_Title") + ")</li>";
        $("#tasksUL").append(liHtml);
      });
    }
  });
});
</script>
<ul id="tasksUL"/>
Coordinator
Feb 28, 2013 at 2:07 PM
There's no "file". The myJson variable will hold the JSON object, but only within the scope of the completefunc function, as you have things defined.

Since I haven't worked with Dynatree, I have no idea how it wants the JSON to be structured. If you figure it out, please post it back here if you can, as I'm sure others would be interested.

M.
Mar 2, 2013 at 2:06 PM
@PaulM22

You are on the right track. Since you are getting items back from the list, you now have to format them in a way that you'd like for them to display. You'll want to do that by building up on big object and add that to the dynatree's options.

Admittedly, I've never used the SPXmlToJson function, so I'm not versed in using it. It'll probably be easier for you to roll your own thing anyway. Here's an example of what the hierarchy should look like as an object:
            children: [
                   {
                    title: "Root",
                    isFolder: true,
                    key: "Root",
                    children: [
                        {
                            title: "Folder 1",
                            isFolder: true,
                            key: "folder1",
                            id: 1,
                            children: [
                                {
                                    title: "Folder 3",
                                    isFolder: true,
                                    key: "folder3",
                                    id: 3
                                }
                            ]
                        },
                        {
                            title: "Yeah!!!",
                            id: 2
                        },
                        {
                            title: "Item 1",
                            id: 4
                        },
                        {
                            title: "Folder 2",
                            isFolder: true,
                            key: "folder2",
                            id: 5,
                            children: [
                                {
                                    title: "Sub-item 2.1",
                                    id: 6
                                },
                                {
                                    title: "Sub-item 2.2",
                                    id: 7
                                }
                            ]
                        },
                        {
                            title: "Item 3",
                            id: 8
                        }
                    ]
                }
            
So what I've done was build up the items and then make a call to dynatree within the "completefunc" ( I used CSOM, but whatev ):

  $().SPServices({
    operation: "GetListItems",
    async: false,
    listName: "MOSS Fileplan",
    CAMLViewFields: "<ViewFields><FieldRef Name='Title' /><FieldRef Name='Parent_URL' /><FieldRef Name='Process' /></ViewFields>",
    CAMLQuery: "<Query><Where><Eq><FieldRef Name='Parent_URL' /><Value Type='Text'>" + "S10" + "</Value></Eq></Where></Query>",
    completefunc: function (xData, Status) {
      $(xData.responseXML).find("[nodeName='z:row']").each(function() {
        //alert(xData.responseXML.xml);
        var myJson = $(xData.responseXML).SPFilterNode("z:row").SPXmlToJson({
          mapping: {
            ows_ID: {mappedName: "ID", objectType: "Counter"},
            ows_Title: {mappedName: "MdbaUrl", objectType: "Text"},
            ows_Process: {mappedName: "Process", objectType: "Text"},
            ows_Parent_URL: {mappedName: "ParentUrl", objectType: "Text"}
          }, // name, mappedName, objectType
          includeAllAttrs: false,
          removeOws: true
        });

        // Build up your treeItems object then call the buildTree function and pass treeItems
        $(document).ready(function() {
              buildTreeItems( treeItems );
        });
        // To read a field it is ALWAYS $(this).attr("ows_<internal field name>");
        var liHtml = "<li>" + $(this).attr("ows_Process") + " (" + $(this).attr("ows_Title") + ")</li>";
        $("#tasksUL").append(liHtml);
      });
    }
  });


function buildTree(treeItems) {
        // Get the div id's for each tree
        // --- Initialize first Dynatree
        $("#tree").dynatree({
            autoFocus: false, // Set focus to first child, when expanding or lazy-loading.
            minExpandLevel: 0,
            children: treeItems
    });
}
That's one way of building the tree w/o relying on a .json file somewhere on a server. So really now all you have to do is build up your treeItems object in the format you want and you'll be done.

Let me know if you need help on building the object correctly. It can be a little tricky depending on your requirements. It CAN be done though. :-P

Cheers,
Matthew
Apr 2, 2014 at 1:46 PM
I have a similar requirement, but the data comes from multiple lists. The links are related by lookup columns (there is a lookup column in the parent list [Entities] that has columns from the child list [Attributes]). To make things even more complicated, I have some Attributes which are not referenced from the Entities list. I want to have a treeview that displays Entities items with Attributes items under them. I also want to add items froma list called [Terms] on the same level as the Entities. I also need to make the whole thing searchable without going to a different page. I have access to SharePoint Designer. What's te easiest way to do this? Your help would be greatly appreciated.