2

I have a VF page which is called on click of a custom List Button on a custom objects standard list view. this is supposed to download all the selected records in the page. Now the functionality is working fine, but I need to redirect the page back to the standard page I was initially on so that the end User does not see the blank VF page which gets created.

Below is my code:

VF Page

<apex:page standardController="Custom_Object__c" extensions="Custom_Object_Controller" recordSetVar="recs" contentType="text/csv#filename.csv" action="{!callDownloadRecordsMethod}">COLUMN1, COLUMN2, COLUMN3, COLUMN4
<apex:repeat value="{!wrapList}" var="rec"> 
{!rec.col1},{!rec.col2},{!rec.col3},{!rec.col4}
</apex:repeat>
</apex:page>

Controller:

public class Custom_Object_Controller {

public ApexPages.StandardSetController standardController;
public List<Id> selectedRecIds{get;set;}
public List<objectWrapper> wrapList{get;set;}
public Map<Custom_Object__c, List<Custom_Object__Child__c>> ParentToChildMap = new Map<Custom_Object__c, List<Custom_Object__Child__c>>();

public Custom_Object_Controller(ApexPages.StandardSetController standardController) {
    this.standardController = standardController;
    selectedRecIds = new List<Id>();
    List<Custom_Object__c> selectedRecords = (List<Custom_Object__c>) standardController.getSelected();

    for(Custom_Object__c objectRec : selectedRecords) {
        selectedRecIds.add(objectRec.Id);
    }


}

public void callDownloadRecordsMethod() {
    downloadRecords();
}

public PageReference downloadRecords () {
    for(Custom_Object__c objectRec : [SELECT field1,field2,field3, (SELECT field1, field2 FROM Custom_Object__Child__r) FROM Custom_Object__c WHERE Id IN : selectedRecIds]) {
       List<Custom_Object__Child__c> childList = objectRec.Custom_Object__Child__r;
       ParentToChildMap.put(objectRec,childList);
    }
   system.debug('ParentToChildMap=----------->'+ParentToChildMap);

    objectWrapper = new List<objectWrapper>();

    for(Custom_Object__c parRec : ParentToChildMap.keyset()){
        if(ParentToChildMap.get(parRec).size()==0){
            system.debug('Map does not has Values --> Inside NO map value list' );
            objectWrapper wrapRec = new objectWrapper(parRec.field1, parRec.field2,parRec.field3,null,null);
            objectWrapper.add(wrapRec);
        }else{
            for(List<Custom_Object__Child__c> childList : ParentToChildMap.values()){
                system.debug('Map has Values --> Inside map value list' );
                for(Custom_Object__Child__c childRec : childList) {
                    if(childRec.Custom_Object__c == parRec.Id){
                        objectWrapper wrapRec = new objectWrapper(parRec.field1, parRec.field2,parRec.field3,childRec.field1,childRec.field2);
                        objectWrapper.add(wrapRec);
                    }
                }
            }
        }
    }
    system.debug('objectWrapper=----------->'+objectWrapper);


    PageReference newpg = new PageReference('/'+Custom_Object__c.sobjecttype.getDescribe().getKeyPrefix()+'/o');
    //newpg.getParameters().put('nooverride', '1');  
    newpg.setRedirect(true);
    return newpg;

    //return null;
}

public class objectWrapper {
    public String field1wrap{get;set;}
    public String field2wrap{get;set;}
    public String field3wrap{get;set;}
    public String field4wrap{get;set;}
    public String field5wrap{get;set;}

    public objectWrapper(String field1Param, String field2Param,String field3Param,String field4Param, String field5Param) {

        this.field1wrap = field1Param;
        this.field2wrap = field2Param;
        this.field3wrap = field3Param;
        this.field4wrap = field4Param;
        this.field5wrap = field5Param;   
        this.field5wrap = field5Param;   
    }   
}
}

Please let me know in case I am missing out on anything. The VF Page is called based on a List Button which in turn generates a csv file of all the records which are part of the wrapper list and gets downloaded automatically. As mentioned the list of records and download is happening perfectly, but the User is faced with a blank page in the end (the VF page) - which needs to be changed to go back to the original list view page (from where the button was pressed).

2 Answers 2

2

You can avoid the blank VF page with the use of the following

(example taken from a download PDFs button I used in a custom component). Hence, you can avoid the redirect.

Some CSS

<style type="text/css">
    .hideDownloadTarget { position:absolute; top:-1px; left:-1px; width:1px; height:1px; }
</style>

Your button

<apex:commandLink id="downloadLink" value="Download" action="{!URLFOR('/apex/mypage',null)}"  
                  target="hiddenFrame" />

and, elsewhere on the page (mine is at the bottom):

<!-- hidden frame causes download action to remain on same page as far as user is concerned, 
     no new tab opened. see target="hiddenFrame" -->   
<iframe id="downloadTargetIF" name="hiddenFrame" class="hideDownloadTarget"/>  
3
  • Thanks for the reply. But as mentioned in my question, my page is already being called via a custom button on a standard list view (meaning there's no commandLink involved), so how do I pass the {!URLFOR('/apex/mypage',null)} parameter as when i create this button, I only get the page name as a drop down list without having an option to specify any parameters!
    – Sid
    Commented Aug 25, 2016 at 5:12
  • @Sid --edit your OP with the essence of your VF page - I misunderstood your question. You can use the button type = URL and code an expression like /apex/mypage?paramX=foo&paramY={!somemergefield} - this will invoke the VF page
    – cropredy
    Commented Aug 25, 2016 at 14:32
  • But I dont need a button or any other html code in the page as when it renders as csv the file which gets downloaded has the html code as well in it. The page structure which i have provided in my post is the only way it seems to generate the correct file with only column headers and the required data!
    – Sid
    Commented Aug 26, 2016 at 0:02
1

I don't see where you're using a PageReference method to get the relative URL of the Referrer page to use with your redirect so you can return the user back to that page from your button. It's preferable that you send that information to your page as a parameter via the button in the Headers.

Edit

What you're looking for is called the Referer and will sometimes be found in the Request Header (it's optional). Otherwise, you can include it in your parameters when you direct a user to the page.

Depending on whether or not it's included, you could one of a couple things like below that you'd want to call from your constructor to get the Return URL. You can then use later use the saved pageRef to return the user to the source page.

public PageReference getRetPageRef(){

    // if in headers
    String RetPage = ApexPages.currentPage().getHeaders().get('Referer');

    PageReference RetPageRef = new PageReference(RetPage);

    return RetPageRef;
}

If it's not being included in the headers (unlikely that it is), you'd want to pass it in your params with a param name like MySrcPage where all you need is the value of the /apex/pagename that you could use something like below with:

    String RetPage = ApexPages.currentPage().getParameters().get('MySrcPage');

    PageReference RetPageRef = new PageReference(RetPage);

    return RetPageRef;

Note: you'd still have your other record Id parameters, but would also have this additional MySrcPage parameter as well that your button would be passing with it too.

1
  • I am not sure what you mean here. Initially I had all the code in the constructor as I didnt see the need to have an additional function. Now that I need to redirect back to the standard page, I added an additional Pagereference function to get the redirect part - this is the part where I actually need help!!
    – Sid
    Commented Aug 24, 2016 at 14:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .