threeheadsonapike

Salesforce frustrations? Ask one of our heads on a pike !

Tag Archives: APEX

Salesforce URL Hacking the right way – Prepopulate fields, Record Type Selection and No hard-coded ID’s (deployable)

This post was inspired by an article found here:  http://raydehler.com/cloud/clod/salesforce-url-hacking-to-prepopulate-fields-on-a-standard-page-layout.html

And also:

http://blog.deliveredinnovation.com/2012/09/17/create-a-custom-new-button-on-a-related-list-to-return-to-the-parent-record-after-clicking-save/

With credits to Wes on:

http://force201.wordpress.com/2012/01/22/hack-to-find-field-ids-allows-a-default-ui-new-page-to-be-pre-populated/

Everyone has the solution how to pre-populate fields after clicking on a custom ‘New’ button but no one has addressed the issue of hard coded IDs  in such a way that making new buttons easy and re-usable!

It’s a great way to populate fields on a Salesforce page however the problem with this method is that we are hardcoding the ID’s of the various labels on the record. If you are used to working on a sandbox before deploying on a production environment you will soon realize that having to change all these ID’s because you hard coded these, it is not only time-consuming, it is bad practice.

Attached to this post is a little script that I wrote that allows you create buttons without hard-coding anything, you can deploy the code between org’s and all will work !

Examples how to pre-populate different fields using the script (just add this into a Visualforce button), ofcourse you can add more fields to the URL if you need to prepopulate more than one:

1. Pre-populate a text field having API label: ‘Text__c’ on a custom object called: ‘Custom__c’:

  • /apex/RedirectWithVariables?object=Custom__c&Text__c=Text Value

2. Pre-populate a picklist having API label: ‘Picklist__c’ on a custom object called ‘Custom__c’:

  • /apex/RedirectWithVariables?object=Custom__c&Picklist__c=Picklist Value

3. Create a new record of a given record type (use the label of the record type instead of the name):

  • /apex/RedirectWithVariables?object=Custom__c&RecordType=Custom Record Type

4. Pre-populate an example lookup field having API label ‘Lookup__c’ on a custom object called: ‘Custom__c. Important to note that a lookup field requires two parameters, the ID of the record that it references and the text value of the field as seen by the user. To set the text value use the API name of the lookup and to set the ID value of the lookup append ‘ID_’ to the API name of the lookup as seen in the following example:

  • /apex/RedirectWithVariables?object=Custom__c&Lookup__c=Text Value&ID_Lookup__v=ID_Value

Hope this will anyone out there !!

Classed used in this post:

RedirectWithVariables.class

StaticFunctions.class

Page used in this post:

RedirectWithVariables.page

Key manipulation of an APEX Map on a Visualforce page

One of the features of using maps in Salesforce is their ability to be used on a Visualforce page by looping of their keys and using the key to fetch whatever is stored at that position in a map. For example, assume we have a map called mapMenu and each key (defined as a string) is pointing to a string. We could loop over the contents printing all menu items by doing the following:

<apex:repeat value="{!mapMenu}" var="key ">
    <apex:repeat value="{!mapMenu[key]" var="item">

{!item}

    </apex:repeat>
</apex:repeat>

Now, not taking into account that the keys are returned in arbitrary order we have used this method in various ways to display data. However, one of the issues I would like to address is the manipulation of the key on the Visualforce page. Let us assume we would like to use the key not only the fetch the item, but also use it to create a link with a query string that will display some kind of sub category page:

<apex:repeat value="{!mapMenu}" var="key ">

<apex:repeat value="{!mapMenu[key]" var="item">

    <a href="{!$Page.SubCategory}?category={!key}"> {!item} </a>

    </apex:repeat>
</apex:repeat>

Great! Now we have a link pointing to some kind of sub category page with the ‘item’ as its title. But what if need to manipulate the key, for example strip out spaces when passing it as a query string? Now here is the issue. Since a key in a map can be any primitive type it is considered an object, so doing:

<a href="{!$Page.SubCategory}?category={!SUBSTITUTE(key,’ ’,’’)}">
{!item}
</a>

Will result in:
Error: Incorrect parameter for function ‘SUBSTITUTE()’. Expected Text, received Object

Ok, that’s fine we say, since we know the key is actually a string we can try and cast it:

<a href="{!$Page.SubCategory}?category={!SUBSTITUTE( TEXT(key) ,’ ’,’’)}"> {!item} </a>

But this will result in:
Error: Incorrect parameter for function ‘TEXT()’. Expected Number, Date, DateTime, received Object

Blast. It seems we are unable to perform any manipulation on the keys of the map as it is considered an object by all functions. However, we can still cast it into a string by assigning it to a Visualforce variable:

<apex:repeat value="{!mapMenu}" var="key ">

<apex:repeat value="{!mapMenu[key]" var="item">

<apex:variable value="{!key} " var="strParsedKey" />
<a href="{!$Page.SubCategory}?category={!SUBSTITUTE(strParsedKey,’ ‘,’’}">

     {!item}
</a>

    </apex:repeat>

</apex:repeat>

Notice how we assign it to the variable strParsedKey and we add an extra space t0 the value: value=”{!key} “. By adding this extra character (any character) we are forcing Visualforce to cast it into a string and now we can use any of the manipulation functions.

Hope this helps!

Controller functions fire twice on an AJAX postback on a Visualforce page.

During one of our developments we noticed the following behaviour which initially did not make sense at all. Every AJAX postback fired from a visualforce page would cause some specific functions that are used to rerender a set of outputpanels to be triggered twice. For example, our debug logs were showing it would call getMenuItems (used to load the menu) twice:

First call at 14:32:21.728, unnecessary call:

14:32:21.728 (728701000)|CODE_UNIT_STARTED|[EXTERNAL]|01pD0000000rSlG|Collaborate_CreateOrderBrandController get(getMenuItems)

Second call at 14:32:22.151, used to rerender part of the page:

14:32:22.151 (1151036000)|CODE_UNIT_STARTED|[EXTERNAL]|01pD0000000rSlG|Collaborate_CreateOrderBrandController get(getMenuItems)

Mind you, we are simply firing an AJAX request for a removal of an item. So what is happening here?

For some reason during the AJAX request, after the viewstate deserializes and the controller class gets instantiated, all functions that are used on the visualforce page to rerender specific aspects of the page, get fired before the actual AJAX function call is executed, for example removing an item in our case. Initially we figured this may be due to the fact our functions have mostly been written as properties (get, set properties). Currently we are still unsure what is causing this but here is our solution:

Salesforce has a nice property called ‘Transient’. Declaring any property transient means it will not be sent as part of the Viewstate and therefore will be null during an AJAX postback. Now we have a way of identifying which request is an AJAX postback, and which request isn’t. So somewhere in our class we declare:

public Transient Boolean doRerender = true;

The first time the page loads, this value is true. However because it is declared ‘Transient’, it will be null on any AJAX postback.

Now, if we check our debug logs and we find any function being run twice on an AJAX postback (mostly always those parts on a Visualforce page that get rerendered after the AJAX postback), we can now apply the following fix assuming the getMenuItems function is the function that is being fired twice:

public  List<Menu_Item>  getMenuItems(){

List<Menu_Item> lMenuItems = new List<Menu_Item>();

if(this.doRerender!=null)

lMenuItems = this.buildMenu();

return lMenuItems;

}

We now solved the issue for the first function call. It will detect the value is null and will not execute any logic. However, the 2nd time it fires the function we do need it to execute the logic as we want the specific parts of the page to rerender properly.
To do this we need to set this.doRerender = true in the function that is executing the AJAX request, in our example removeItem:

function void removeItem(){

this.doRerender = true;
Id idSOI = Apexpages.currentPage().getParameters().get('idSOI');
this.remove(idSOI);

}

Now the second time the getMenuItems is called (for the rerender) it will execute the logic needed. Applying this solution will make sure specific functions needed to rerender specific parts of the Visualforce page will only execute once. If anyone can shed some light on why this is happening in the first place, please leave a comment.