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?

  • 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. – spevilgenius Oct 3 '14 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 – Michael Colbs Oct 3 '14 at 16:45
  • Do you have a sample that I could try? – Michael Colbs Oct 3 '14 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. – spevilgenius Oct 3 '14 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. – Michael Colbs Oct 3 '14 at 20:07
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, privacy policy and cookie policy

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