I have a VF page that uses <apex:repeat> to show a List<Attachment>, and I want the list to return different attachments based on {!opportunity.stageName} .

VF Page code :

<apex:page standardController="Opportunity"  extensions="QueryAttachments"> 
    <apex:repeat value="{!attachmentList}" var="att">
          <apex:image styleClass="bigImage" url="{!URLFOR($Action.Attachment.Download, att.id)}" rendered="true"/>

Controller code:

public class QueryAttachments {

    public ApexPages.StandardController controller;
    public String stageName{get;set;}    
    public List <Attachment> attachmentList {
        get {
            return getAttachmentId();

    public QueryAttachments(ApexPages.StandardController controller) {
        this.controller= controller;

    public List <Attachment> getAttachmentId () {
        System.debug('stageName : ' + stageName);
        return attachmentList = [Select Id,Name,ParentId,Parent.Name,CreatedDate from Attachment Where Description =: stageName ]; 

I can retrieve value="{!opportunity.stageName}" in VF, what I want is to pass it to QueryAttachments controller and query based on it's value.

I don't want to use apex:actionFunction or apex:commandButton, I only want to pass opportunity.stageName when the stage on opportunity sObject is saved and show the associated attachments.

| improve this question | | | | |

There's no need to explicitly pass anything between your visualforce and your controller extension here. The standardController, which you're placing into this.controller in your constructor has a copy of the same Opportunity that you have access to in the visualforce page through merge expressions like {!Opportunity.StageName}.

You can access this by using the getRecord() method of ApexPages.StandardController.

A brief example would be this

public class MyExtension{
    private Opportunity theOpp;

    public MyExtension(ApexPages.StandardController con){
        // The getRecord() method returns a generic SObject.
        // Typecasting is required if you want to store the record
        //   in a 'concrete' SObject like Opportunity
        theOpp = (Opportunity)con.getRecord();

    public List<Attachment> getAttachments(){
        // Standard caveats apply here
        // theOpp will only contain fields referenced on your visualforce page
        return [SELECT Id FROM Attachment WHERE someField = :theOpp.StageName];
| improve this answer | | | | |
  • theOpp.StageName will return an error SObject row was retrieved via SOQL without querying the requested field , I had to query Opportunity object to get the stageName since theOpp object only had id as an attribute. public List <Attachment> getAttachmentId () { String stages = [Select stageName from Opportunity Where Id =: theOpp.Id limit 1].get(0).stageName; return attachmentList = [Select Id from Attachment Where Description =: stages ]; } Other than that it works like a charm ! – Has Nah Jul 6 '17 at 21:52
  • @user46892 Like I mentioned in my example code, theOpp only has fields available that you use on your visualforce page. You could avoid the query by including <apex:variable var="throwaway" value="{!Opportunity.StageName}"/> somewhere in your visualforce page (which would cause your page to reference the field without rendering some HTML to also display the value). – Derek F Jul 6 '17 at 23:01

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.