Salesforce.com Winter 10 Release...What's in it for you?

This Tuesday, Salesforce.com announced the release of Winter 10 version and explored new features that soon will be added to the mix. Right off the bat I would like to declare that this new release has a lot of more to offer compare to the previous one and I thank Salesforce for that!

The highlight of the new features is the Realtime Quotes that will be available soon to all Salesforce.com customers. In any sales environment one of the aspects of the Sales process is to be able to track what goods potential and existing customers are interested to purchase and Salesforce supports that by the means of Opportunities.

The one thing that always bugged me though was that Salesforce did not have a feature to allow communication of that information (in terms of Quotes or Invoices) to those customers as soon as the deals reached to a more solid state (proposing or closing).

I believe Salesforce is very late in the game to introduce this feature and already many customers have sought other means to fill that gap and now most will face the question whether to migrate the existing solutions to what's provided out-of-the-box or stay with their current vendors...




Also the fact that Salesforce PriceBooks are not customizable hinders the possibility of tailoring Salesforce to any specific pricing calculation model. Concepts such as automated Volume Discounts calculation that could be applied to Opportunity line items, or any other custom pricing models.


Moving on, on the Custom Cloud side, Salesforce yet again is gaining momentum by introducing "Batch Code Processor" and "Code Scheduler".
Many admins in the past, in order to process event-driven data to be able to provide custom roll-ups, Analytics and better summary-data visibility of child objects in the system, were forced to max out their workflow rules or develop triggers which most of the time would hit the Governing Limits or just fail in bulk DML operations.



With these new features many of those scenarios can be easily addressed and even more complex logic can be applied to solve problems and fulfill business requirements!
Cases such as data de-dupping, data heath checks, rebuilding account hierarchies.... Sky is the limit!

Edit and Delete Command For Your Datatable In Visualforce


Most often that not you need to show data to the users in form of a table, such as Salesforce List Views or Related Lists.

Visualforce allows us to easily implement such page with a few lines of code. However, most often you would want to be able to add more interactivity/functionality to your page by supporting Edit or Delete command or any other custom operation that is required by design.

Today's article will show you how you can get that working for you.



Above picture depicts how the final result will look like, very much like Salesforce.com standard pages, isn't it?.

In this example I list the first twenty Account records that Apex finds and show then on the screen and then I would like to have actions such as "Edit" that forwards the user to Account edit page and brings the user back to my page again after the modifications are done and also "Delete" action that receives a confirmation from user and removes an Account record from Salesforce CRM.

So let's talk about the User Interface (UI) components required first and then we will look into the controller's code to see how it all works together.

Steps to add the page tags:
  • I first add a PageBlock component and set the title to "Accounts"
  • Then I want to put a PageBlockDataTable in the my Visualforce page.
  • In this step I simply add all the data columns I want to show to the user and leave the first column empty for the next step.
  • Now we are ready to add the action items to the first column of the dataTable.
Below is the page tags that I have used to make it all happen:


<apex:page controller="DataTableEditRemoveController">
<apex:form id="form" >
<apex:pageBlock title="Accounts">
<apex:pageMessages ></apex:pageMessages>
<apex:pageBlockTable value="{!accs}" var="row">
<apex:column >
<apex:outputLink title="" value="/{!row.id}/e?retURL=/apex/{!$CurrentPage.Name}" style="font-weight:bold">Edit</apex:outputLink>&nbsp;|&nbsp;
<a href="javascript:if (window.confirm('Are you sure?')) DeleteAccount('{!row.Id}');" style="font-weight:bold">Del</a>
</apex:column>
<apex:column value="{!row.Name}"/>
<apex:column value="{!row.BillingStreet}"/>
<apex:column value="{!row.BillingCity}"/>
<apex:column value="{!row.BillingPostalCode}"/>
<apex:column value="{!row.BillingCountry}"/>
</apex:pageBlockTable>
</apex:pageBlock>

<apex:actionFunction action="{!DeleteAccount}" name="DeleteAccount" reRender="form" >
<apex:param name="accountid" value="" assignTo="{!SelectedAccountId}"/>
</apex:actionFunction>
</apex:form>
</apex:page>



How It Is Done For Edit Action:
Since the standard Account edit page is good enough for me I used an outputLink component to link the record to its Standard Edit page. In Salesforce for standard objects you can follow this format to get the URL for their edit page: /{RecordId}/e

I also wanted this to work in such a way that would return the user back to my Visualforce page once the user clicks on "save" or "cancel" in the Account edit page. In order to do that I need to add the following to the URL: /{RecordId}/e?retURL={returnURL}

In the Page's source code (above) you see that for return URL I have used {!$CurrentPage.Name} merge field, where I could simply put my page name. I like writing code clean! By doing this if you later on decided to change your page name, you do not need to worry about breaking anything! You page will continue to work with no problems!

How It Is Done For Delete Action:
In order to support this action in your page you need to do a bit of coding. The key is to be able to find out which account was selected by the user to be deleted.

In this example I have used a actionFunction component that triggers a Controller's Apex method call "DeleteAccount".

Before getting more into the coding part I wanted this link to get a confirmation from the user about deleting the record before actually we remove it.
In order to do so, we need to use a little bit of Javascript "window.confirm", the javascript function returns true if the user clicks on OK and false if the user selects "Cancel".

In order to capture the user's selection as to which account should be deleted I have added a "param" tag to the actionFunction component which passes the Account ID to the controller and as soon as user clicks on the link.

Now let's take a look at the code:


public class DataTableEditRemoveController {

public List<Account> accs { get; set; }

//used to get a hold of the account record selected for deletion
public string SelectedAccountId { get; set; }

public DataTableEditRemoveController() {
//load account data into our DataTable
LoadData();
}

private void LoadData() {
accs = [Select id, name, BillingStreet, BillingCity, BillingPostalCode, BillingCountry from Account limit 20];
}

public void DeleteAccount()
{
// if for any reason we are missing the reference
if (SelectedAccountId == null) {

return;
}

// find the account record within the collection
Account tobeDeleted = null;
for(Account a : accs)
if (a.Id == SelectedAccountId) {
tobeDeleted = a;
break;
}

//if account record found delete it
if (tobeDeleted != null) {
Delete tobeDeleted;
}

//refresh the data
LoadData();
}


}




Funny thing is that in my tests if you do not set the "reRender" attribute of the "actionFunnction" component the param is not passed to the controller and the "SelectedAccountId" property is not populated. Go figure....

Also I really wanted to get it working with commandLink or commandButton components instead using actionFucntion and javascript, but was not so lucky!

Enjoy!