Search code examples
salesforceapexapex-codevisualforcesalesforce-lightning

Is there a way to update a VisualForce Page's Content Type through an IF-Condition?


Been looking for a way to update an apex:page content type but don't see any source about it AHAHA. I have this ATM:

<apex:page standardController="sObject" extensions="<apexClass>"
</apex:page> 

the apex class in the extension has a lot of functionalities and i have an href in the middle of the page that is linked to a template which when clicked can be viewed and saved as a CSV file. but instead of viewing a template, I wanted to upgrade the functionality into a downloadable one. So i want to find a way to update the header that when the link gets clicked it adds this contenttype="application/vnd.ms-excel to the header of the apex:page.

you guys have an idea if there's such a thing in VF?


Solution

  • Yes, you can put expressions in pretty much any Visualforce parameter including apex:page's contentType. Something like this:

    <apex:page lightningstylesheets="true" standardController="Contact" recordSetVar="contacts" extensions="SomeClass"
        showHeader="{!showForm}" sidebar="{!showForm}" applyHtmlTag="{!showForm}" standardStylesheets="{!showForm}"
        id="p" contentType="{!IF(showForm, 'text/html', 'application/vnd.ms-excel#Contactss.xls')}" readonly="true">
    
    <apex:outputPanel layout="none" rendered="{!showForm}">
    <apex:form >
        <apex:pageBlock>
            <apex:pageBlockButtons location="top">
                <apex:actionStatus id="status">
                    <apex:facet name="stop">
                        <apex:outputPanel >
                            <apex:commandButton value="{!$Label.preview}" action="{!preview}" rerender="controls,preview" status="status"/>
                            <apex:commandButton value="{!$Label.export}" action="{!export}" status="status"/>
                            <apex:commandButton value="{!$Label.cancel}" action="{!cancel}" immediate="true" />
                        </apex:outputPanel>
                    </apex:facet>
                    <apex:facet name="start">
                        <apex:outputPanel >
                            <apex:commandButton value="{!$Label.preview}" disabled="true"/>
                            <apex:commandButton value="{!$Label.export}" disabled="true"/>
                            <apex:commandButton value="{!$Label.cancel}" action="{!cancel}" immediate="true" />
                            <img id="status" src="/img/loading.gif" alt="Loading..." title="Loading..."/>
                        </apex:outputPanel>
                    </apex:facet>
                </apex:actionStatus>
            </apex:pageBlockButtons>
            
            <apex:pageBlockSection columns="1" id="controls">
                put some form here, input fields...
            </apex:pageBlockSection>
        </apex:pageBlock>
        <apex:pageBlock title="Preview" id="preview">
            optionally display first 10 rows or something
        </apex:pageBlock>
    </apex:form>
    </apex:outputPanel>
    
    <apex:outputPanel id="o" layout="none" rendered="{!!showForm}">
    {!csv} Payload here
    </apex:outputPanel>
    </apex:page>
    

    But be sure to check how it behaves in Lightning Experience (if you use it). Last time I played with it there was some extra output in LEX and eventually I cheated. I output CSV to hiddent html element, grab it with JavaScript.

    <apex:commandButton value="{!$Label.export}" action="{!downloadCsv}" rerender="out" oncomplete="javascript:downloadComplete();return false;" status="status"/>
    
    ...
    
    <apex:outputPanel id="out" style="display:none">
        <span class="payload">{!csvBody}</span>
        <script>
        function downloadComplete(){
            let payload = document.getElementsByClassName('payload')[0].innerText.replaceAll('<br/>', '\n');
            let filename =  'Equipment Utilization Report.csv';
    
            let link = document.createElement('a');
            link.href = 'data:text/csv;charset=utf-8,' + encodeURIComponent(payload);
            link.target = '_self';
            link.download = filename;
            link.click();
            return false;
        }
        </script>
    </apex:outputPanel>