Blog entry posted for: Ivan Melnikov
..
Overview
ExtJS javascript framework is becoming more and more popular among web site developers because of its simplicity and support of the most popular browsers in industry. Salesforce.com platform is not an exception. The newer 4th version of ExtJS can be utilized to enrich standard VisualForce functionality with flexible UI components and make data representation a lot more customizable.
However there are some custom tricks and hacks that have to be used to integrate standard Salesforce.com with ExtJS framework. In this article I’ll try to briefly explain how to integrate lookup fields with Ext buttons and use standard Salesforce popup window for searching records and adding them to the UI components on the page.
Implementation steps
- You will need a lookup field on your page. This lookup field is going to be used to show the popup window only. It is not necessary to create any records using this field. Let’s create a custom object Lookup_Object__c and one lookup field to User object and name it User__c.
- Create a controller class for the page. This class has to have “global” access modifier and implement standard controller because we’ll need to use remote action methods for asynchronous calls on this page.
- Then define a remote action method which would return User record information by its Id in JSON format. For doing so we utilize new class available from the Winter’12 release for serialization of Salesforce.com objects into JSON format.
Here is what we should get:
global with sharing class UserManagerController
{
public UserManagerController(){}
public UserManagerController(ApexPages.StandardController controller){}
/* Object used to populate reference to user */
public Lookup_Object__c lookupObject
{
get;
set;
}
@RemoteAction
global static String getUserData(String recordId)
{
List<User> user = [select FirstName, LastName, Title, CompanyName from User where Id = : recordId];
// These methods are for serializing Apex objects into JSON format available since Winter’12 release
// Find out more at http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_json.htm
String JSONString = JSON.serialize(user);
//Depends on your needs and way you want to format your result. Lets just hardcode the status value for now.
return ‘{\”Records\”:’ +JSONString+’, \”error\”: \”null\”, \”status\”:\”SUCCESS\”}’;
}
}
- Now create a VisualForce page. The lookup field should be hidden on the page. For doing that place it into the div under the form with style=”opacity:0; height:0;overflow:hidden;”. Please notice that we don’t use style=”display:none” in this case because it won’t work.
- So if you inspect this hidden field we created you may notice that in fact it is div which contains multiple fields ending with “_lkid”, “_lkold”, “_mod” to which we’ll need to get access to, read UserId from the “_lkid” and reset all of them afterwards. In order to open search window programmatically we’ll need to change window.location to the url stored at href property of hidden field.
- That is a basic concept. Please take a look at the code with comments inline. It is pretty straight forward and you can use it right away for you project needs.
VisualForce page code:
<apex:page controller=“UserManagerController”>
// Connects ExtJS library hosted at Sencha’s servers. However it can be stored locally as static resource.
<script type=“text/javascript” charset=“utf-8″ src=“http://cdn.sencha.io/ext-4.0.7-gpl/ext-all.js”></script>
<link rel=“stylesheet” type=“text/css“ href=“http://cdn.sencha.io/ext-4.0.7-gpl/resources/css/ext-all.css“ />
// Hidden form which contains lookup field to make standard salesforce lookup window work.
<apex:form >
<div style=“opacity:0;height:0;overflow:hidden;”>
<apex:inputField id=“userFieldId” value=“{!lookupObject.User__c}”/>
</div>
<div id=“pageView”></div>
</apex:form>
// Here is fun part begins…
<script type=“text/javascript”>
Ext.require([ 'Ext.form.*',
'Ext.grid.*',
'Ext.data.*'
]);
//Defines custom user model for the store
Ext.define(‘UserModel’, {
extend : ‘Ext.data.Model’,
fields: [{
name : 'LastName',
type : 'string'
}, {
name : 'FirstName',
type : 'string'
}, {
name : 'Title',
type : 'string'
}, {
name : 'CompanyName',
type : 'string'
}
]
});
// Defines custom user button which can be used multiple times
Ext.define(‘Ext.ux.UserButton’, {
alias : ‘widget.userButton’,
extend: ‘Ext.button.Button’,
// Handler function fires every time user clicks on the button.
handler : function() {
window.location = this.uA.getAttribute(“href”);
},
initComponent : function() {
var me = this;
var uField = Ext.get(Ext.DomQuery.selectNode(“input[id$=:userFieldId]“));
me.uId = uField.getAttribute(“id”);
me.uA = Ext.get(me.uId+‘_lkwgt’);
// Add on change event to the Salesforce user field.
uField.on(‘change’, function() {
// There is some delay required to let script set values to fields.
Ext.Function.defer(function(){
var nValue = me.getFieldValue();
if (nValue != ’000000000000000′)
{
me.addUserToStore(nValue);
}
}, 10, this);
});
this.callParent();
},
// Returns value from the Salesforce user field
getFieldValue: function() {
var v = Ext.get(this.uId+“_lkid”).getValue();
return v!=“000000000000000″?v:“”;
},
// Removes all values from hidden fields related to Salesforce user field
resetFieldValue: function() {
Ext.get(this.uId).dom.value = ”;
Ext.get(this.uId+“_lkid”).dom.value = ’000000000000000′;
Ext.get(this.uId+“_lkold”).dom.value = ‘null’;
Ext.get(this.uId+“_mod”).dom.value = 0;
},
// Adds user to the Grid store
addUserToStore : function(recordId) {
var grid = this.up(“grid”);
grid.setLoading(true);
// Get data from SalesForce
// Heres is apex remote action call, which allows user make request to APEX controller using Javascript.
UserManagerController.getUserData(recordId, function(result, er){
// Set loading mask on the grid.
grid.setLoading(false);
// Decode JSON string returned from the server.
var res = Ext.decode(result);
// If result field “status” contains word ”SUCCESS” then proceed with adding new user on the grid.
// Otherwise display popup with an error message.
if (res && res.status == “SUCCESS”)
{
// Take first and only record returned from the server. There might be multiple ones, depending on design requirements.
var userRec = res.Records[0];
// Add record to the grid store
grid.store.add(userRec);
} else {
// Display error message.
Ext.Msg.alert(“Error”,“An unexpected error occurred.”);
}
}, {
// This parameter is used to prevent auto escaping of special characters like &,@, quotes, double quotes etc.
escape: false
});
// Reset user field values for the next click.
this.resetFieldValue();
}
});
// Create an instance of grid.
var grid = Ext.create(‘Ext.grid.Panel’,
{
// tbar is toolbar element on the top of the grid.
tbar : Ext.create(‘Ext.toolbar.Toolbar’, {
// Creates one button in tbar
items: [{
xtype: 'userButton',
text: 'Add User'
}]
}),
// Creates store to keep user record for displaying on the grid.
store : Ext.create(‘Ext.data.Store’,
{
model: ‘UserModel’,
proxy : {
type : ‘memory’,
reader : {
type : ‘json’
}
},
data: []
}),
// Columns describe how records will be rendered on the grid.
columns: [{
text: "Title",
width: 100, dataIndex: 'Title', sortable: true
},{
text: "Name",
width: 200, dataIndex: 'Title', sortable: true,
renderer: function(value, p, record){
return record.data.LastName + ', ' + record.data.FirstName
}
},{
text: "Company", width: 100, dataIndex: 'CompanyName', sortable: true
}]
});
// Main panel contains grid panel and may potentially contain more panels in it. Renders to the ‘pageView’
// div tag, which we defined on the top of this page.
var mainPanel = new Ext.panel.Panel({
border: false,
renderTo : ‘pageView’,
width: 400,
items : [
// Only one panel, which is grid panel will be displayed on this parent panel.
grid
]
});
</script>
</apex:page>
What is good about it?
ExtJs can significantly extend any VisualForce functionality and add new features which Salesforce doesn’t have yet. All developers need is to customize and embed some standard functionality with custom JavaSript code.
Thank you for reading!
**
If you want to test out the sample from the post, please find below a link to the unmanaged package:
https://login.salesforce.com/packaging/installPackage.apexp?p0=04tU0000000DZd3
**
Contact Us


