Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save douglascayers/aab0d360c4ecc5abc0cfe91b1502d96a to your computer and use it in GitHub Desktop.
Save douglascayers/aab0d360c4ecc5abc0cfe91b1502d96a to your computer and use it in GitHub Desktop.
Example of embedding analytics:reportChart in visualforce and making when the user clicks the chart that it takes user to the report, not load report nested in the iframe.
<apex:component >
<!--
Visualforce pages added to page layouts are embedded via iframes.
That means the default link behavior of content in the iframe (aka, this page)
loads within that iframe rather than changing the browser's actual address bar.
We want when the users click the report charts that the entire page redirects
to the report chart rather than simply loading the report data in the iframe.
To do this we wrap the report charts in an outputLink with onclick handler.
Anytime the user clicks in that region to interact with the report then our handler
runs which updates the iframe's parent frame's URL.
To make this trick work we also need two reports instead of one for each chart
we want to show. This is because of how the analytics:reportChart tag filter attribute
behaves and how we specify report filters via URL.
1. The filter attribute of the analytics:reportChart tag is a filter in addition to
the filter of the saved report. It does not replace any filter already on the report.
This means to provide context on the report to dynamically filter by the case's contact
then the report must be saved without a Contact ID filter and then apply a Contact ID
filter via this tag in the visualforce page.
2. However, to provide context on the report to dynamically filter by the case's contact
via URL then we need the report saved with a Contact ID blank filter. In this manner
we can use URL hack to specify report parameters as ?pv0=<somevalue>&pv1=<somevalue>.
In addition, the Contact ID that pulls into the report is the 18 character ID, but the
report is filtered on the 15 character ID. So the parameter has been changed to include
LEFT functionality telling it to only count the 15 left-most characters.
The conflict is that no single report can both "filter by" and "not filter by" the same field.
Our only workaround is to save one report that filters by the Contact ID for use by the URL trick
and save a second report that does not filter by the Contact ID for use by the analytics:reportChart tag.
Further, because our click handler intercepts any click on the report chart then
if we show the 'Refresh' report button then rather than refresh the report right there
like normal the user is instead redirected to the view report page. To avoid confusion,
we don't show the refresh button on the report charts.
https://developer.salesforce.com/forums/?id=906F0000000AbKNIA0
-->
<apex:attribute name="contactId" description="ID of the contact whose charts to display" required="true" type="String"/>
<table width="100%">
<tr>
<td width="25%">
<!--
We use a custom setting, Report_Settings__c, to store the actual ID of the report to view.
This allows our code to not have to be reconfigured when deployed between environments as
the report ID might be different depending on what we are testing.
As mentioned above, we need TWO reports per report chart to display:
1. that we link to from this page and can accept the URL filter parameter, and
2. that we embed via analytics:reportChart tag which uses a filter expression and not URL filter parameter
In my custom setting, per report, I create two custom fields.
One prefixed with LINK_ and another prefixed with CHART_.
-->
<apex:outputLink onclick="changeURL('/{!$Setup.Report_Settings__c.LINK_Some_Report__c}?pv1={!LEFT(contactId, 15)}');">
<analytics:reportChart reportId="{!$Setup.Report_Settings__c.CHART_Some_Report__c}"
size="tiny"
cacheResults="false"
showRefreshButton="false"
filter="[{column:'CONTACT_ID', operator:'equals', value:'{!contactId}'}]"/>
</apex:outputLink>
</td>
</tr>
</table>
<script>
function changeURL( url ) {
window.parent.location.replace( url );
}
</script>
</apex:component>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment