0

I'm having trouble passing data from my AngularJS controller on my Visualforce page to the Apex Controller.

I've created an actionFunction on the VF page:

<apex:form>
    <apex:actionFunction action="{!exportToPdf}" name="exportToPdf">
        <apex:param name="firstParam" assignTo="{!productData}" value=""/>
        <apex:param name="secondParam" assignTo="{!calculatedProductData}" value=""/>
    </apex:actionFunction>
</apex:form>

Then from within my AngularJS controller I do the following:

$scope.exportToPdf = function() {
    var productData = JSON.stringify($scope.productData);
    var calculatedProductData = JSON.stringify($scope.calculatedProductData);
    window.alert(productData);
    exportToPdf(productData, calculatedProductData);
};

The $scope.exportToPdf() is then executed when a user clicks a button on the Visualforce page:

<div class="slds-col slds-no-flex slds-grid slds-align-bottom">

    <button class="slds-button slds-button--neutral" ng-click="exportToPdf()">
        Export To PDF
    </button>

</div>

Apex Controller:

public with sharing class InvoiceCalculatorController {

  public String productData { get; set; }
  public String calculatedProductData { get; set; }

  public PageReference exportToPdf() {
      system.debug('PDATA:' + this.productData);
      system.debug('CALCDATA:' + this.calculatedProductData);

      PageReference printView = Page.InvoiceCalculatorPrintView;

      return printView;
  }
}

The end result is productData and calculatedProductData are both null in the system.debug statement.

Any ideas on what's going on here?

0

It turns out this is a bug with Visualforce. In order for the actionFunction params to be set to anything other than null, the reRender attribute on the actionFunction has to be set (even if its blank).

Since my application needed to forward to a new page and not just reRender a section on the page, I built a workaround to accomplish this task.

Visualforce:

<apex:form>
    <apex:actionFunction action="{!savePdfParams}" name="savePdfParams" reRender="displayPdfPanel">
        <apex:param name="firstParam" assignTo="{!productData}" value="" />
        <apex:param name="secondParam" assignTo="{!calculatedProductData}" value="" />
    </apex:actionFunction>
    <apex:actionFunction action="{!exportToPdf}" name="exportToPdf"></apex:actionFunction>
</apex:form>

<apex:outputPanel id="displayPdfPanel">
    <script>
        var displayPdf = {!displayPDF};
        console.log('Display PDF?', displayPdf);

        if(displayPdf == true) {
            exportToPdf();
        }

        function showProgressCursor() {
            document.getElementsByTagName('body')[0].style.cursor = 'progress';
        }
    </script>
</apex:outputPanel>

Apex Controller:

public with sharing class InvoiceCalculatorController {

  public String productData { get; set; }
  public String calculatedProductData { get; set; }
  public Boolean displayPDF { get; set; }

  public PageReference savePdfParams() {
        this.displayPDF = true;
        return null;
    }

    public PageReference exportToPdf() {
        system.debug('PDATA:' + this.productData);
        system.debug('CALCDATA:' + this.calculatedProductData);

        PageReference printView = Page.InvoiceCalculatorPrintView;

        return printView;
    }
}

I now first call the savePdfParams actionFunction which sets the controller parameters as desired. Then in the controller is set the displayPDF flag to true. When the actionFunction re-renders the displayPdfPanel outputPanel and then executes the exportToPdf function which sends me to the desired page.

Kind of roundabout approach, but it works.

| improve this answer | |

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.