2

I have a two pages that share the same controller extension. The first page gathers some information for a record, builds a PDF from the second page and attaches it to the case. I have a lot of JavaScript that has to run before the PDF is created, so I need to use an ActionFunction. The pages also need to share the same controllers, otherwise the data won't be displayed on the PDF properly.

The problem is when I use an ActionFunction, the wrong page gets rendered as PDF (Case1 instead of Case2).

Here is a very simplified version of the controller and pages.

public class CaseExtension{

    public Case c;

    public CaseExtension(ApexPages.StandardController stdController) {
        c = (Case)stdController.getRecord();
    }

    public PageReference nextPage() {
        Attachment att = New Attachment(Name = 'Test.pdf');
        att.parentId = c.Id;
        PageReference page = new PageReference('/apex/Case2');
        att.Body = page.getContentAsPDF();
        insert att;
        return new PageReference('/' + att.Id);
    }
}

The first page (Case1). The button with the action works, the one that calls JS does not.

<apex:page standardController="Case" extensions="CaseExtension">
    <apex:form id="theForm">
        <apex:actionFunction name="buildPDF" action="{!nextPage}" reRender="theForm"/>
        <apex:pageBlock >
            <apex:pageBlockSection title="Page 1">
                <apex:inputField value="{!Case.Description}"/>
            </apex:pageBlockSection>
            <apex:pageBlockButtons >
                <apex:commandButton onclick="buildPDF(); return false;" value="Build PDF - JS"/>
                <apex:commandButton action="{!nextPage}" value="Build PDF"/>
            </apex:pageBlockButtons>
        </apex:pageBlock>
    </apex:form>
</apex:page>

The second page (Case2):

<apex:page standardController="Case" extensions="CaseExtension">
        <apex:pageBlock >
            <apex:pageBlockSection >
                <apex:outputText value="{!Case.Description}"/>
            </apex:pageBlockSection>
        </apex:pageBlock>
</apex:page>

I have come up with a very hacky solution that involves creating a hidden button that my JS clicks when all the other JS is done executing. It just feels wrong to me and there should be an easier way to do this.

5
  • Have you done your due diligence in checking for JavaScript errors? You stated this is pseudo code, so is there a possibility the onclick function is mistyped or even the incorrect case, which will also mess with the execution? A few more things.. I like to use PageReference pageRef = Page.MyPage for handling actions in managed packages as opposed to using the text version of new PageReference and lastly, you can remove the rerender attribute of your actionFunction. It's a moot point when you're directing the user to a different page. Dec 27, 2013 at 4:55
  • 1
    This code replicates the issue. There are no JS errors. Thanks for the other tips. In my real code, I need the rerender to pass values to the controller. Dec 27, 2013 at 5:21
  • Have you checked to see if the behavior is different using JavaScript remoting rather than actionFunction?
    – snugsfbay
    Dec 28, 2013 at 15:16
  • Also, I am not familiar with actionFunction, but the sample code in the manual has the actionFunction inside its own set of form tags, with nothing else in that form. Your event listener is inside the form tags with the actionFunction. Is there a difference?
    – snugsfbay
    Dec 28, 2013 at 15:43
  • I can't use JS Remoting because I need the controller variables. (Well, I guess I could, but I'd have to pass a lot of state through in the remoting call.) It doesn't make a difference in where the actionFunction is. Dec 29, 2013 at 4:08

0

You must log in to answer this question.

Browse other questions tagged .