Monthly Archives: October 2013

Tab Order and Visualforce

I was trying recently to get the tab order to work on my Visualforce page. I wanted the order to go down the first column, and then back to the top of column 2, and tab down that column. Easy enough right? There is an attribute called taborderhint on inputfields that sets the order of fields selected when you tab:

<apex:pageBlockSection >
<apex:inputField taborderhint="1" value="{!contact.FirstName}"/>
<apex:inputField tabindex="3" value="{!contact.Email}"/>
<apex:inputField taborderhint="2" value="{!contact.LastName}"/>
<apex:inputField taborderhint="4" value="{!contact.Phone}"/>
</apex:pageBlockSection>

But then I needed to add some inputText fields as well. There is no taborderhint attribute on inputtext, but there is an attribute called tabindex which looks like it should do the same thing. But when you do something like this, it doesn’t work:

<apex:pageBlockSection >
<apex:inputField taborderhint="1" value="{!contact.FirstName}"/>
<apex:inputText tabindex="3" value="{!contact.Email}"/>
<apex:inputField taborderhint="2" value="{!contact.LastName}"/>
<apex:inputField taborderhint="4" value="{!contact.Phone}"/>
</apex:pageBlockSection>

After scratching my head for while, and reading about various JS solutions, I finally uncovered this post on the community boards. After some impressive digging in the dev console, the user discovered that taborderhint multiples the hint by 10 – so 1 is actually being set as 10. But the same behavior is not used for tabindex. So you have to account for that when you set the values – and when you do, it all works:

<apex:pageBlockSection >
<apex:inputField taborderhint="1" value="{!contact.FirstName}"/>
<apex:inputText tabindex="30" value="{!contact.Email}"/>
<apex:inputField taborderhint="2" value="{!contact.LastName}"/>
<apex:inputField taborderhint="4" value="{!contact.Phone}"/>
</apex:pageBlockSection>

Seems odd behavior to me, but at least it works I guess!

Phone Formatting in APEX

Another problem we often face when integrating with other systems is formatting phone numbers. If you enter a phone number via the SFDC UI, it will apply standard US phone formatting to the number if it a 10 digits number. But that is being applied by the browser using JS script. If you load data into phone number fields via the API, it leaves them as they are, which doesn’t look great when a user sees the record in the UI, and it can break any phone integrations such as Skype or Google Voice that expect numbers to be formatted in a certain way.

To get round that problem, we can use another utility with a simple REGEX pattern:

public static String formatphonenumber(String cphone) {
String fphone = cphone.replaceAll('\\D','');

if (fphone.length() == 10) {
fphone = formatphonenum(fphone);
return fphone;
}
else {
return cphone;
}

}

static String formatphonenum (String s) {
s = '(' + s.substring(0, 3) + ') ' + s.substring(3, 6) + '-' + s.substring(6);
return s;
}

This one will look at the original string passed to it, remove any character that is not a digit, and if it is 10 digits long, apply the US style phone format to it to make it consistent with the UI formatted numbers.
So if we can do something like this:

String sPhoneRaw = '202-555-1234';
String sPhoneFormatted = UtilitiesDemo.formatphonenumber (sPhoneRaw);
system.assertequals('(202) 555-1234', sPhoneFormatted);

The key line is this one:

String fphone = cphone.replaceAll('\\D','');

replaceall is a standard string function in APEX, but it can use a REGEX as the pattern to search for – in this case, an NON digit. So it doesn’t matter what we get passed from another system/loaded in via the API – we can strip it back to just the digits, and then apply the format if required.

And you can see a working demo here

Email Validation in APEX

If you enter an email address into an ’email’ type field in Force.com, it will validate that the value entered is a valid email, and won’t let you save the record with a bad email. But when you are integrating Salesforce with another system, that system may not perform the same level of verification. You often need to import the record into Salesforce regardless of whether the email is valid, but need to be able to handle bad emails so you don’t try and save a record with a bad email address.

So I always create a static method in a Utility class that I can use to check an email and return a boolean to tell me if the email is valid or not. If not, I can then save the email address to a non-email text field, and flag the record for review by a business user. The method uses a pattern match with a REGEX for matching against emails. I have always used the example from this post. But if you search for Email and Regex, you’ll find lots of examples. The one below seems to handle most scenarios though.


public static Boolean checkEmail (String semail) {
String InputString = semail;
String emailRegex = '([a-zA-Z0-9_\\-\\.]+)@((\\[a-z]{1,3}\\.[a-z]{1,3}\\.[a-z]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})';
Pattern MyPattern = Pattern.compile(emailRegex);

// Then instantiate a new Matcher object "MyMatcher"
Matcher MyMatcher = MyPattern.matcher(InputString);

if (!MyMatcher.matches()) {
return FALSE;
}
else {
return TRUE;
}
} //end email check

And then in my integration code, a simple check

if (UtilitiesDemo.checkEmail (sEmail) ) {
//Use email
}
else {
handle bad email
}

You can see a working example here

Next up, formatting phone numbers from another system…

New Schema Method for Describing Multiple sObjects

If you are building ISV packages on Force.com, you quickly end up needing to do Describe calls on sObjects. Prior to Winter 14, you could either request the Describe results for a single sObject, or get the describe results for all sObjects. Most people then end up writing utility classes to cache those results into a static Map so you could retrieve the results from a Map as you needed them, and not breach any describe call limits.

But in Winter 14, there is a new Schema Method which let’s you pass in a string [] of sObjects names you want describe results for, and get back an Schema.DescribeSobjectResult [] for the results, which will prove really helpful when you need the results for two or three sObjects and a full describe seems like overkill. As ever with new Force.com releases, I also now get to go back and update all those utility classes I built/borrowed from others…

Here’s the sample code from the docs

// sObject types to describe
String[] types = new String[]{'Account','Merchandise__c'};
// Make the describe call
Schema.DescribeSobjectResult[] results = Schema.describeSObjects(types);
System.debug('Got describe information for ' + results.size() + ' sObjects.');
// For each returned result, get some info
for(Schema.DescribeSobjectResult res : results) {
System.debug('sObject Label: ' + res.getLabel());
System.debug('Number of fields: ' + res.fields.getMap().size());
System.debug(res.isCustom() ? 'This is a custom object.' : 'This is a standard object.');
// Get child relationships
Schema.ChildRelationship[] rels = res.getChildRelationships();
if (rels.size() > 0) {
System.debug(res.getName() + ' has ' + rels.size() + ' child relationships.');
}
}