0

After a great deal of searching and effort, I've finally got a working controller that can show ContentVersion documents and paginate them. Upon testing it, though, I found that the Next button wouldn't send me to the next set of ContentVersion objects to display. Below is my code, and feel free to use it where you may need it, because I DON'T want anyone to have to go through the steps to get to this point again. ContentVersionController:

public with sharing class ContentVersionController {
    private ApexPages.StandardSetController controller;
    private List<ContentVersion> content;
    private List<ContentVersion> pageContent;
    private Integer pageNumber;
    private Integer pageSize;
    private Integer totalPageNumber;

    public ContentVersionController() {
        //controller = new ApexPages.StandardSetController();
        pageNumber = 0;
        totalPageNumber = 0;
        pageSize = 20;
        ViewData();
    }

    public ContentVersionController(ApexPages.StandardSetController con) {
        controller = con;
        pageNumber = 0;
        totalPageNumber = 0;
        pageSize = 20;
        ViewData();
    }

    public static List<ContentVersion> getContentVersions() {
        return [SELECT Id, Title, ContentDocumentId FROM ContentVersion
                WHERE IsLatest = true LIMIT 1000];
    }

    public Integer getPageNumber() {
        return pageNumber;
    }

    public List<ContentVersion> getContent() {
        return pageContent;
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public Boolean getPreviousButtonEnabled() {
        return !(pageNumber > 1);
    }

    public Boolean getNextButtonDisabled() {
        if (content == null) {
            return true;
        } else {
            return ((pageNumber * pageSize) >= content.size());
        }
    }

    public Integer getTotalPageNumber() {
        if (totalPageNumber == 0 && content !=null) {
            totalPageNumber = content.size() / pageSize;
            Integer mod = content.size() - (totalPageNumber * pageSize);
            if (mod > 0) {
                totalPageNumber++;
            }
        }
        return totalPageNumber;
    }

    public PageReference ViewData() {
        content = null;
        totalPageNumber = 0;
        BindData(1);
        return null;
    }

    private void BindData(Integer newPageIndex) {
        try {
            if (content == null){
                content = [SELECT Id, Title, ContentDocumentId FROM ContentVersion
                           WHERE IsLatest = true LIMIT 1000];
            }
            pageContent = new List<ContentVersion>();
            transient Integer counter = 0;
            transient Integer min = 0;
            transient Integer max = 0;
            if (newPageIndex > pageNumber) {
                min = pageNumber * pageSize;
                max = newPageIndex * pageSize;
            } else {
                max = newPageIndex * pageSize;
                min = max - pageSize;
                //min = min <>
            }
            for(ContentVersion c : content) {
                counter++;
                if (counter > min && counter <= max){
                    pageContent.add(c);
                }
            }
            pageNumber = newPageIndex;
            if (pageContent == null || pageContent.size() <= 0) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, 'Data not available for this view.'));
            }
        } catch(Exception ex) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.FATAL, ex.getMessage()));
        }
    }

    public PageReference nextBtnClick() {
        BindData(pageNumber + 1);
        return null;
    }

    public PageReference previousBtnClick() {
        BindData(pageNumber - 1);
        return null;
    }
}

ContentVersionFiles (VisualForce page):

<apex:page docType="html-5.0" controller="ContentVersionController" showChat="false" showHeader="false" showQuickActionVfHeader="false" sidebar="false">
  <apex:form >
    <div align="center" style="display:{!IF(NOT(ISNULL(content)), 'block', 'none')}">
      <font size="1pt">Page #:&nbsp;<apex:outputLabel value="{!PageNumber}"/>&nbsp;out of&nbsp;<apex:outputLabel value="{!totalPageNumber}"/>&nbsp;&nbsp;&nbsp;&nbsp;</font>
      <apex:commandButton value="Previous" action="{!previousBtnClick}" disabled="{!previousButtonEnabled}" reRender="pageBlock"></apex:commandButton>
      <apex:commandButton value="Next" action="{!nextBtnClick}" reRender="pageBlock" disabled="{!nextButtonDisabled}" ></apex:commandButton>
    </div>
  </apex:form>
  <apex:pageBlock title="" id="pageBlock">
    <apex:panelBar >
      <apex:repeat var="cv" value="{!contentVersions}">
          <apex:panelBarItem label="{!cv.Title}"><a href="/{!cv.Id}"><img id="image" height="600px" src="/sfc/servlet.shepherd/version/download/{!cv.Id}" title="{!cv.Title}" /></a></apex:panelBarItem>
      </apex:repeat>
    </apex:panelBar>
  </apex:pageBlock>
</apex:page>

I'm so close to making this work properly, please help me :(

2

In your VF page you have:

<apex:pageBlock title="" id="pageBlock">
<apex:panelBar >
  <apex:repeat var="cv" value="{!contentVersions}">
      <apex:panelBarItem label="{!cv.Title}"><a href="/{!cv.Id}"><img id="image" height="600px" src="/sfc/servlet.shepherd/version/download/{!cv.Id}" title="{!cv.Title}" /></a></apex:panelBarItem>
  </apex:repeat>
</apex:panelBar>

The repeat fetches from {!contentVersions} which is defined in your controller as:

public static List<ContentVersion> getContentVersions() {
    return [SELECT Id, Title, ContentDocumentId FROM ContentVersion
            WHERE IsLatest = true LIMIT 1000];
}

So, it doesn't matter what the Next button does, you ignore its work when you rerender the pageBlock

I think you want the apex:repeat to bind to a public property pageContent

|improve this answer|||||
  • This does fix the pagination. However: now the images don't display. What if pageContent needs to be the recordSetVar for the page, and then set the binding to content? Is that likely to cause a change? – Lee S Oct 8 '15 at 19:43
  • image display sounds like a separate issue - if you type in the browser /sfc/servlet.shepherd/version/download/someContentversionId does it display an image suitbale for rendering with HTML img tag? recordSetVar applies to standardSetController – cropredy Oct 8 '15 at 21:30
  • It sort of works...Strangely, it only works from https://c.<domain>.visual.force.com/sfc/servlet.shepherd/version/download/<someContentVersionId>, and not from the top-level domain. – Lee S Oct 9 '15 at 14:18
  • post the question about images in a separate question on SFSE – cropredy Oct 9 '15 at 16:13
1

I was correct with my guess: the recordSetVar had to be set to content. The images do display now, and paginates up to 2,000 records of ContentVersion object. I'm hoping I can tweak this to use queryMore() to bypass the 2,000 record threshold. Thank you very much for your help. :) Below is the updated code for anyone who ever needs this sort of functionality.

ContentVersionFiles.page:

<apex:page docType="html-5.0" recordSetVar="{!content}" readOnly="true" controller="ContentVersionController" showChat="false" showHeader="false" showQuickActionVfHeader="false" sidebar="false">
  <apex:includeScript id="console-js" value="/support/console/35.0/integration.js" />
  <apex:variable var="count" value="{!0}" />
  <apex:form id="topForm">
    <div align="center" style="display:{!IF(NOT(ISNULL(content)), 'block', 'none')}">
      <font size="1pt">Page #:&nbsp;<apex:outputLabel value="{!PageNumber}"/>&nbsp;out of&nbsp;<apex:outputLabel value="{!totalPageNumber}"/>&nbsp;&nbsp;&nbsp;&nbsp;</font>
      <apex:commandButton value="Previous" action="{!previousBtnClick}" reRender="pageBlock" disabled="{!previousButtonEnabled}"></apex:commandButton>
      <apex:commandButton value="Next" action="{!nextBtnClick}" reRender="pageBlock" disabled="{!nextButtonDisabled}" ></apex:commandButton>
    </div>
  </apex:form>
  <apex:pageBlock title="Registration Scans" id="pageBlock">
    <apex:panelBar id="scans">
      <apex:repeat var="cv" value="{!pageContent}">
        <apex:variable var="count" value="{!count+1}" />
        <apex:panelBarItem id="barItem" label="{!cv.Title} - #{!count} of {!pageContent.size}" onenter="autoResize(this.id)"><a href="/{!cv.Id}"><img id="image" src="/sfc/servlet.shepherd/version/download/{!cv.Id}" title="{!cv.Title}" /></a></apex:panelBarItem>
      </apex:repeat>
    </apex:panelBar>
  </apex:pageBlock>
  <apex:form id="bottomForm">
    <div align="center" style="display:{!IF(NOT(ISNULL(content)), 'block', 'none')}">
      <font size="1pt">Page #:&nbsp;<apex:outputLabel value="{!PageNumber}"/>&nbsp;out of&nbsp;<apex:outputLabel value="{!totalPageNumber}"/>&nbsp;&nbsp;&nbsp;&nbsp;</font>
      <apex:commandButton value="Previous" action="{!previousBtnClick}" disabled="{!previousButtonEnabled}" reRender="pageBlock"></apex:commandButton>
      <apex:commandButton value="Next" action="{!nextBtnClick}" reRender="pageBlock" disabled="{!nextButtonDisabled}" ></apex:commandButton>
    </div>
  </apex:form>
</apex:page>

ContentVersionController.apxc:

public with sharing class ContentVersionController {
    public List<ContentVersion> pageContent { get; set; }
    private ApexPages.StandardSetController controller;
    private List<ContentVersion> content;
    private Integer pageNumber;
    private Integer pageSize;
    private Integer totalPageNumber;

    public ContentVersionController() {
        //controller = new ApexPages.StandardSetController();
        pageNumber = 0;
        totalPageNumber = 0;
        pageSize = 20;
        ViewData();
    }

    public ContentVersionController(ApexPages.StandardSetController con) {
        controller = con;
        pageNumber = 0;
        totalPageNumber = 0;
        pageSize = 20;
        ViewData();
    }

    public static List<ContentVersion> getContentVersions() {
        return [SELECT Id, Title, ContentDocumentId FROM ContentVersion
                WHERE IsLatest = true LIMIT 1000];
        /* Be sure to use "AND OwnerId = '<Id>'"
         * so it will filter out any publicly shared
         * content, like from Chatter. For anything
         * else, you may need to specify what
         * workspace the content is coming from.
         */
    }

    public Integer getPageNumber() {
        return pageNumber;
    }

    public List<ContentVersion> getContent() {
        return pageContent;
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public Boolean getPreviousButtonEnabled() {
        return !(pageNumber > 1);
    }

    public Boolean getNextButtonDisabled() {
        if (content == null) {
            return true;
        } else {
            return ((pageNumber * pageSize) >= content.size());
        }
    }

    public Integer getTotalPageNumber() {
        if (totalPageNumber == 0 && content !=null) {
            totalPageNumber = content.size() / pageSize;
            Integer mod = content.size() - (totalPageNumber * pageSize);
            if (mod > 0) {
                totalPageNumber++;
            }
        }
        return totalPageNumber;
    }

    public PageReference ViewData() {
        content = null;
        totalPageNumber = 0;
        BindData(1);
        return null;
    }

    private void BindData(Integer newPageIndex) {
        try {
            if (content == null){
                content = [SELECT Id, Title, ContentDocumentId FROM ContentVersion
                           WHERE IsLatest = true LIMIT 1000];
            }
            pageContent = new List<ContentVersion>();
            transient Integer counter = 0;
            transient Integer min = 0;
            transient Integer max = 0;
            if (newPageIndex > pageNumber) {
                min = pageNumber * pageSize;
                max = newPageIndex * pageSize;
            } else {
                max = newPageIndex * pageSize;
                min = max - pageSize;
                //min = min <>
            }
            for(ContentVersion c : content) {
                counter++;
                if (counter > min && counter <= max){
                    pageContent.add(c);
                }
            }
            pageNumber = newPageIndex;
            if (pageContent == null || pageContent.size() <= 0) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, 'Data not available for this view.'));
            }
        } catch(Exception ex) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.FATAL, ex.getMessage()));
        }
    }

    public PageReference nextBtnClick() {
        BindData(pageNumber + 1);
        return null;
    }

    public PageReference previousBtnClick() {
        BindData(pageNumber - 1);
        return null;
    }
}
|improve this answer|||||
  • where is recordSetVar on page definition? It is certainly true that without it - VF doesn't realize that standardSetController is used – cropredy Oct 12 '15 at 18:53
  • I might have added the file too soon :x I'll have to edit it later – Lee S Oct 12 '15 at 19:06
  • I'll also add the readOnly="true" attribute, since this lets the List<ContentVersion> expand from 1,000 objects to 10,000. For anything beyond 10,000 files, you'll have to use the queryMore() method for querying beyond what limits Salesforce enforces. – Lee S Oct 13 '15 at 13:30

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.