0

I'm working on a custom HTML Form in Sharepoint 2010 and for that I want to read the structure of a list with JavaScript, which contains items and folders.

What I did was loading all the Items ignoring the folder structure and then trying to get the parent folders from the items. The problem I run into is that I don't see any method that gives me all the parent folders or just an absolute or relative path, from which I could extract the folder names. I also tried to get the file of the ListItem and get a path from there but when I try to load the file I get Cannot invoke method or retrieve property from null object. Object returned by the following call stack is null. "File". So my question is: Is it possible to get the path or the parent folders of a ListItem and if so how?

Here is my code:

var clientContext;
function retrieveListItems() {

    clientContext = new SP.ClientContext(siteUrl);
    var oList = clientContext.get_web().get_lists().getByTitle('Skills');

    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml('<View Scope="Recursive"><Query></Query></View>');
    this.collListItem = oList.getItems(camlQuery);

    clientContext.load(collListItem, 'Include(Id, DisplayName, HasUniqueRoleAssignments, FileSystemObjectType)');

    clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));        

}

function onQuerySucceeded(sender, args) {
    var listEnum = collListItem.getEnumerator();
    var listItemInfo = '';
    while(listEnum.moveNext()) {
        var $current = listEnum.get_current();
        $current.refreshLoad();
        console.dir($current);
        listItemInfo += "\n" + $current.get_displayName();

        var $file = $current.get_file();

        $("#LOG").append("\nCurrent " + print_r($current));
        $("#LOG").append("\nCurrent Path " + print_r($current.get_path()));
        $("#LOG").append("\nCurrent Path ID " + print_r($current.get_path().get_identity()));
        $("#LOG").append("\nFile: " + print_r($file));  
        clientContext.load($current.get_file(), "File");
        clientContext.executeQueryAsync(function() {
            $("#LOG").append("\nLevel: " + $current.get_file().get_level());
        }, function(sender, args) {
            $("#LOG").append("\nFailed: " + args.get_message());
        });

    }

    $("#LOG").append(listItemInfo);
}

Also if my approach is totally wrong I would appreciate a way to iterate through the List folder structure from the root folder.

Thanks in Advance

Patrick

  • Is that a list or library? For a list item it will be attachments. You question seems confusing! – Atish Dipongkor - MVP Sep 16 '15 at 10:12
  • @AtishDipongkor It's a list. So you mean the get_file() will get you the file attached to the ListItem not a file that IS the ListItem? – Patrick Ziegler Sep 16 '15 at 11:14
0

Get the file path of a list item: Make an ajax request in following end-point.

http:/yoursiteurl/_vti_bin/listdata.svc/InductionAcknowledgement(1)/Attachments

Replace InductionAcknowledgement with your list name. Put item id inside first bracket (). Then you will get following response

{
  "__metadata": {
    "uri": "https://yourSiteUrl/_vti_bin/listdata.svc/Attachments(EntitySet='InductionAcknowledgement',ItemId=1,Name='ACM%20Problem.docx')",
    "type": "Microsoft.SharePoint.DataService.AttachmentsItem",
    "edit_media": "https://yourSiteUrl/_vti_bin/listdata.svc/Attachments(EntitySet='InductionAcknowledgement',ItemId=1,Name='ACM%20Problem.docx')/$value",
    "media_src": "https://yourSiteUrl/Lists/Induction Acknowledgement/Attachments/1/ACM Problem.docx",
    "content_type": "application/octetstream",
    "media_etag": "\"{7992A4BD-AA01-4C4C-8FE3-8511F7CCF249},1\""
  },
  "EntitySet": "InductionAcknowledgement",
  "ItemId": 1,
  "Name": "ACM Problem.docx"
}

__metadata.media_src is your file path and Name is the file name.

  • I think I didn't explain properly what I wanted. I have a List that contains folders, subfolders and List Items (no attachments). I want to figure out where inside the folder structure an Item is located. But your example was very helpful nevertheless. I thought you only could get data from Sharepoint with executeQueryAsync, but with just a simple ajay request it's so much easier and you don't have to deal with requesting properties of objects and everything. – Patrick Ziegler Sep 16 '15 at 13:34
  • I have asked for so many things in a single question. I have answer one! – Atish Dipongkor - MVP Sep 16 '15 at 16:15
0

Okey so I figured out how to do it with the help of the example from @AtishDipongkor, though his example goes in another direction, it brought me on the right track. I didn't know that you could use basic AJAX requests to get the data and it makes it a lot easier. What I did, was to use the directions from Atish to get the right URL and then make a simple GET Request to that URL (I added accept: application/json to the header so that I get JSON instead of an ATOM XML Feed). The data I get from that contains all the Items with their Id, Title and absolute path w/o the domain name, so I just can search and replace.

$.ajax(siteUrl + "/_vti_bin/ListData.svc/Skills", {
    headers: {"accept": "application/json"},
    success: function(data) {
        $.each(data.d.results, function(i, skill) {
            addSkill(skill);
        });
        loadedAllItems();
    },
    error: function(jqXHR, textStatus, msg) {
        $("#LOG").append("\nErro: " + msg);
    },
});

function addSkill(data) {
    if(data["ContentType"] != "Item") {
        return;
    }

    var $path = data.Path;
    $path = $path.replace(siteUrl + "/Lists/Skills/", "");
    $folders = $path.split("/");
    var $level = allSkills;
    $.each($folders, function(i, $folder) {
        if(!$level.hasOwnProperty($folder)) {
            $level[$folder] = {};
        }
        $level = $level[$folder];
    });

    $level[data.Title] = data;
    $("#LOG").append("\n" + $path + "/" + data.Title);
}
  • You got the solution from my example but your answer is accepted! How come?? – Atish Dipongkor - MVP Sep 22 '15 at 17:41
  • Because this is about finding a solution to the problem I asked about. And while your response was tremendously helpful, I documented how I solved the problem, thus making this the "right answer". I would have liked to select both as the accepted answer, since yours contains a core component of the solution, but it is unfortunately not possible. – Patrick Ziegler Sep 23 '15 at 19:24
  • You could update your question how you have solved rather than answering own question! – Atish Dipongkor - MVP Sep 23 '15 at 19:59
  • You're not supposed to do that – Patrick Ziegler Sep 23 '15 at 20:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.