Monday, June 10, 2013

Using Visualforce Components Defined in a Managed Package

As part of our KXEN Predictive Offers package, we define a couple of Visualforce components.  This has two purposes.  First, it fosters code reuse: we reuse these components on pages within our package that apply to Contacts, Leads and PersonAccounts, so we don't have to duplicate a bunch of Visualforce code.  Then, our customers may want to embed the capability to show an offer into a larger Visualforce page, so they can use these components themselves in their own pages.

In testing the latter capability today, I ran into a buzzsaw of incomplete and hard-to-find documentation on the side, so I am going to address it here so that folks googling this topic in the future might find this.

The first issue was that, in attempting to use our component in a target org, it was not found.  I was specifying it just as we do in our own pages, like this:

<c:ShowOfferConsole userId="{!Contact.Id}"/>

This was buzzsaw #1: within our package, we can refer to the component using the standard c: notation.  The component was global, so I should be able to use it, right?  I also tried c:Offers__ShowOfferConsole, thinking maybe the kind of namespacing you do in Apex would work, but no dice there.  Finally I figured it out: outside our package I had to refer to it via its package namespace (which in this case is "Offers"), like this:

<Offers:ShowOfferConsole userId="{!Contact.Id}"/>

Great!  That only took me about an hour to figure out!  But it still didn't work, now for a different reason.  Now I get this error:

Error: Cannot use attribute userid (in component offers:showofferconsole) without global access in a component/page that is not in the same namespace as the component in my_visualforce_page at line 117 column 61

This took a while to track down.  The component is global, yes, so I should be able to use it; but in components, like in Apex classes, you also have to make the individual attributes global in order to access them from outside the package.  Fortunately this is our own package so we can modify the code, and here we needed to modify the component to make the userId attribute global.  Now, finally, I can use the component outside the package!

No comments:

Post a Comment