2

I am generating a link to a List Item's attachments using the following code. It works perfect, but it is slowing down the loading / paging of my List view significant. Does anybody know of a more efficient way in doing this? Can this be done OOB, or would I have to switch to a document library instead of a custom list?

overrideContext.Templates.Fields =
{
    'Attachments': { 'View': GenerateAttachmentLink }
};

function GenerateAttachmentLink(ctx) {
    var itemId = ctx.CurrentItem.ID;
    var listName = ctx.ListTitle;
    return getAttachments(listName, itemId);
}

function getAttachments(listName, itemId) {
    var url = _spPageContextInfo.webAbsoluteUrl;
    var requestUri = url + "/_api/web/lists/getbytitle('" + listName + "')/items(" +    itemId + ")/AttachmentFiles";
    var str = "";
    // execute AJAX request
    $.ajax({
        url: requestUri,
        type: "GET",
        headers: { "ACCEPT": "application/json;odata=verbose" },
        async: false,
        success: function (data) {
        for (var i = 0; i < data.d.results.length; i++) {
            str += "<a target='_blank' href='" + data.d.results[i].ServerRelativeUrl + "'>" +
                    "<img border='0' width='16' src='/_layouts/15/images/attach16.png?rev=23'></a>";
                if (i != data.d.results.length - 1) {
                    str += "<br/>";
                }
            }
        },
        error: function (err) {
            //alert(err);
        }
    });
    return str;
}

EDIT: I have Even tried moving this to OnPostRender but the DOM still locks up. Any way to make this asynchronous?

7
  • So is your view in JSLink already? I don't think you can avoid the custom javascript to do this either way. However, you could use a promise so the page loads and then updates the links when ready. Commented Oct 3, 2014 at 16:25
  • Yes the jslink is attached to my view already. I guess a promise is an async operation? I tried this with the above code but the links wouldn't update Commented Oct 3, 2014 at 16:45
  • Do you have a sample that I could try? Commented Oct 3, 2014 at 17:59
  • What I do for something like that, is to set the field that I want to an anchor tag with an id that matches the id of the list item. I also add a specific class and then you can use a loop to loop that class and do the lookup that way after your page loads. It may be cludgy but it does work and you have full control of what your link does. Commented Oct 3, 2014 at 18:01
  • Set the link on every item manually? I have full control of the link now, I'm just looking for a more efficient async way of doing it. Commented Oct 3, 2014 at 20:07

1 Answer 1

3

The Question contains a workable solution to make List Attachments clickable. But it isn't feasible when loading dozens of columns and rows, the performance is noticeably affected.

Instead, the link should be generated on demand, when the user clicks. Here is a modification on the above code to make it work. This shaved about 3.5 seconds of my loading and paging times:

function GenerateAttachmentLink(ctx) {
    var itemId = ctx.CurrentItem.ID;
    var listName = ctx.ListTitle;

    var link = "<a href='javascript:getAttachments(" + itemId + ",\"" + listName + "\")'>" +
    "<img border='0' width='16' src='/_layouts/15/images/attach16.png?rev=23'></a>";

    return link;
}

//Now When the user click the PaperClip, the JS function will be called with the REST service

function getAttachments(itemId, listName ) {

    var url = _spPageContextInfo.webAbsoluteUrl;
    var requestUri = url + "/_api/web/lists/getbytitle('" + listName + "')/items(" + itemId + ")/AttachmentFiles";
    var str = "";

    // execute AJAX request
    $.ajax({
        url: requestUri,
        type: "GET",
        headers: { "ACCEPT": "application/json;odata=verbose" },
        async: false,
        success: function (data) {
            for (var i = 0; i < data.d.results.length; i++) {
                str = data.d.results[i].ServerRelativeUrl;
            }
        },
        error: function (err) {
            //alert(err);
        }
    });
    window.open(str);
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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