+ Start a Discussion
App_Dev1App_Dev1 

Calling functions in expressions

Is it possible to call functions on expressions? Let's say my custom controller returns an Account object (through a getAccount() method), and I want to URLEncode one of its fields, Url__c. So ideally my page looks something like this:

{!EncodingUtil.urlEncode(account.Url__c, 'UTF-8')}

... but that doesn't work. It says function not defined. I tried defining my own urlEncode function in my controller and still no luck.

My workaround is to build a custom object, move all of the field values of Account into it, and then do the encoding in there.

I understand we don't want logic polluting the view (page), but this is just a simple function call for the purposes of formatting. Another use-case is formatting DateTime fields.

Thoughts?

dchasmandchasman
Interestingly enough we will be adding urlEncode() to the page formula language soon (release is still TBD).

The ability to invoke methods on your controller like this is on our roadmap but is not currently supported. What we typically do (and ends up being at least a clean if not more so in many situations) is to switch perspectives from thinking in terms of a push into a method to a pull through a getter.

In the specific case below I would expose a new property accountUrl:

public class MyController {
  public String getAccountUrl() {
    return EncodingUtil.urlEncode(account.Url__c, 'UTF-8');
  }
  ...
}

{!accountUrl}

Things get a bit more complex if you have to handle collections of objects, deeply nested object trees, etc. In those cases we will normally introduce a wrapper or view model class that takes the thing to delegate to as an argument to its constructor and exposes your calculated props.
App_Dev1App_Dev1
Thanks. Yeah I should have been more clear - I'm using an apex:repeat tag to iterate through a collection. So rather than a single Account, I have an array of them. In that scenario I'd need to be able to pass the current Account (var from the repeat) as an argument to a controller method. Since I can't do that right now, I build a new collection of custom objects which bake in any sort of transformations I need to do on the data for the view.

Looking forward to the new stuff!

dchasmandchasman
Your collection of "custom objects" is implemented using an apex code "wrapper" class, right?
App_Dev1App_Dev1
Exactly - it's a custom apex class which just has a bunch of getters, most pass-through, but when I need to apply a transformation for the view (such as urlencode) I can code that in the getter. It seems like a lot of extra work to build these wrapper classes, but I haven't found a better way to massage data in collections for display in a VF page.

dchasmandchasman
We're looking at providing a couple of different features that would make this easy:

- adding the ability to mixin/add traits/or otherwise extend and sobject via some type of apex code behavior mechanism (this is being discussed/designed now). This would make the current pull approach elegant.

- adding support for invoking method on your controller (e.g. might only be class level. static, methods with very specific rules about supported data types for arguments and return values). This would make the expression approach or push style easy/possible to do also.

Both of these proposed features have yet to be scheduled for a specific release but this forum is one very important source of info when we prioritize the contents of our releases so I would expect one or both in the not too distant future - stay tuned...