Js
remoting is very useful & interesting feature. By this the page
is not posted back to server & you will get result in less than a
second...!!!
let's
start with an example how this works. I am also going to use
Mustache.js template in the VF page. Mustache is a js templates &
can be used if you want to generate the html dynamically. It means
you will define the template first & the data will be rendered as
per the defined templates.
To
know more about mustache you can check below url
to
implement the js remoting first we need to create a controller class
in apex.
Please
notice that the apiVersion
for controller class must be 23 or above.
global
class
JSremotingController {
@RemoteAction
global
static
OuterWrapper getOuterWrapperObject(string oppId){
return
null;
}
@RemoteAction
global
static
OuterWrapper setOuterWrapperObject(String jsonString, string oppId){
return
null
}
global
class
InnerWrapper{
public
string name {get;set;}
public
string description {get;set;}
public
InnerWrapper(String strName, String strDesceription){
this.name
= strName;
this.description
= strDesceription;
}
}
global
class
OuterWrapper{
public
String oppName {get;set;}
public
String oppDescription {get;set;}
public List<InnerWrapper> listOfInnerWrapper {get; set;}
public List<String> listOfStr_SelectOptions {get; set;}
public
OuterWrapper(Opportunity
o){
listOfStr_SelectOptions
= SelectOptions_Global;
listOfInnerWrapper
= new List<InnerWrapper>();
oppName
= o.Name;
oppDescription
= o.Description;
}
}
}
let's
dig the code step by step-
@RemoteAction
global
static
OuterWrapper getOuterWrapperObject(string oppId){
}
this
method is defined as remote action by @RemoteAction tag
it
must be declared with global & static keyword because the
function is related to class instance. It will be called by js
remoting to get the data on VF page.
@RemoteAction
global
static
OuterWrapper setOuterWrapperObject(string oppId){
}
this
method is same as above just the difference is we will use this to
update the opportunity description.
There
are two wrapper class. One is main class & other class list used
in main class. The reason why I took this wrapper class structure to
explain how we can deserialize
the input (json string) directly to wrapper class.
Now
again taking the implementataion part for the methods-
@RemoteAction
global
static
OuterWrapper getOuterWrapperObject(string oppId){
Opportunity
opp = [Select
o.Name,
o.Id, o.Description From
Opportunity
o WHERE
Id=:oppId];
OuterWrapper
objOuterWrapper = new
OuterWrapper(Opp);
List<InnerWrapper> WrapperT = new List<InnerWrapper>();
listOfInnerWrapperT.add(new
InnerWrapper('TEST1','DESC1'));
objOuterWrapper.listOfInnerWrapper
= listOfInnerWrapperT;
return
objOuterWrapper;
}
in
this method we will pass a opp od from the VF page, the code will get
the detail from the database create wrapper & return this.
In
JS we will get a js object of OuterWrapper, we can directly access
it's field same as we get the value we get in javascript code. You
will get it more clearly as I will add the vf page in nect couple of
lines.
@RemoteAction
global
static
OuterWrapper setOuterWrapperObject(String jsonString, string oppId){
OuterWrapper
objOuterWrapper =
(OuterWrapper)System.JSON.deserialize(jsonString,OuterWrapper.Class);
Opportunity
opp = new
Opportunity(Id=oppId);
opp.Description
= objOuterWrapper.oppDescription;
update
opp;
return
objOuterWrapper;
}
this
method simply updateting the opp description. This method will be
called from the VF page buttton.
Now
let's move on the VF page detail-
first
of all you need to include the js files for this. There are two js
files-
<apex:includescript value="{!URLFOR($Resource.JS,'jquery-1.4.2.min.js')}" />
<apex:includescript value="{!URLFOR($Resource.JS,'mustache.js')}" />
I
have to include these files because I am using the mustache in the
page, you can avoid this if not required.
function
getOuterWrapperObjectByJSRemoting(oppId) {
JSremotingController.getOuterWrapperObject(oppId,
function(result,
event){
if
(event.status) {
result_Global=
result;
var
template = "<b><span>Opportunity Name:</span> {{oppName}}</b><br/><br/><span>Opportunity Description</span> {{oppDescription}}";
var
html = Mustache.to_html(template, result);
$('#SPANOppName').html(html);
}
else
if
(event.type === 'exception')
{
alert("exception");
document.getElementById("responseErrors").innerHTML
= event.message;
} else
{
alert("else");
document.getElementById("responseErrors").innerHTML
= event.message;
}
},
{escape:true});
}
by
this js method we will pass a opp id & will get the detail in
jsObject result. You can check/run result_Global on the console to
check the structure of the js object.
function
SetOuterWrapperObjectByJSRemoting(jsonString, oppId){
JSremotingController.setOuterWrapperObject(jsonString,
oppId, function(result,
event){
if
(event.status) {
result_Global2 = result;
alert('updated..!!');
}
else
if
(event.type === 'exception')
{
alert("exception");
document.getElementById("responseErrors").innerHTML
= event.message;
}
else
{
alert("else");
document.getElementById("responseErrors").innerHTML
= event.message;
}
},
{escape:true});
}
this
method simply udate the opp description by js remoting.
function
getJSONObject(){
//Outer Wrapper
var
objOpportunityWrapper = new
Object();
objOpportunityWrapper["oppDescription"]
= $("#inputOppDescription").val();
var
InnerWrapper = new
Object();
var
InnerWrapperArray = new
Array();
InnerWrapper["name"]
= 'TEST Name1';
InnerWrapper["description"]
= 'TEST Description1';
InnerWrapperArray[0]
= InnerWrapper;
objOpportunityWrapper["listOfInnerWrapper"]
= InnerWrapperArray;
JSON_STR
= JSON.stringify(objOpportunityWrapper);
SetOuterWrapperObjectByJSRemoting(JSON_STR,Opp_Id);
}
I
think this is the most important method on the js. this method is
going to create structure same as the wrapper class. it there is any
difference in between the object you created on JS & controller
class than the json string will not be serialized in controller.
let's
put the whole code in one place-
class
code will be
global
class
JSremotingController {
private
static List<String> SelectOptions_Global =
getFieldDescibe(Opportunity.LeadSource.getDescribe());
public
static
List getFieldDescibe(Schema.DescribeFieldResult Res){
if(pe
!= NULL
&& pe.SIZE()>0){
for(Schema.PicklistEntry
p:pe){
listOfOpt.add(p.getLabel());
}
}
return
listOfOpt;
}
@RemoteAction
global
static
OuterWrapper getOuterWrapperObject(string oppId){
Opportunity
opp = [Select
o.Name,
o.Id, o.Description From
Opportunity
o WHERE
Id=:oppId];
OuterWrapper
objOuterWrapper = new
OuterWrapper(Opp);
listOfInnerWrapperT.add(new
InnerWrapper('TEST1','DESC1'));
objOuterWrapper.listOfInnerWrapper
= listOfInnerWrapperT;
return
objOuterWrapper;
}
@RemoteAction
global
static
OuterWrapper setOuterWrapperObject(String jsonString, string oppId){
OuterWrapper
objOuterWrapper =
(OuterWrapper)System.JSON.deserialize(jsonString,OuterWrapper.Class);
Opportunity
opp = new
Opportunity(Id=oppId);
opp.Description
= objOuterWrapper.oppDescription;
update
opp;
return
objOuterWrapper;
}
global
class
InnerWrapper{
public
string name {get;set;}
public
string description {get;set;}
public
InnerWrapper(String strName, String strDesceription){
this.name
= strName;
this.description
= strDesceription;
}
}
global
class
OuterWrapper{
public
String oppName {get;set;}
public
String oppDescription {get;set;}
public List<InnerWrapper> listOfInnerWrapper {get; set;}
public List<String> listOfStr_SelectOptions {get; set;}
public
OuterWrapper(Opportunity
o){
listOfStr_SelectOptions
= SelectOptions_Global;
listOfInnerWrapper
= new List<InnerWrapper>();
oppName
= o.Name;
oppDescription
= o.Description;
}
}
}
VF
Page
<apex:page controller="JSremotingController" sidebar="false" showHeader="false">
<apex:form id="form1">
<apex:includescript value="{!URLFOR($Resource.JS,'jquery-1.4.2.min.js')}" />
<apex:includescript value="{!URLFOR($Resource.JS,'mustache.js')}" />
<script type="text/javascript">
var result_Global;
var Opp_Id = '006900000071POn';
function getOuterWrapperObjectByJSRemoting(oppId) {
JSremotingController.getOuterWrapperObject(oppId, function(result, event){
if (event.status) {
result_Global= result;
var template = "<b><span>Opportunity Name:</span> {{oppName}}</b><br/><br/><span>Opportunity Description</span> {{oppDescription}}";
var html = Mustache.to_html(template, result);
$('#SPANOppName').html(html);
} else if (event.type === 'exception') {
alert("exception");
document.getElementById("responseErrors").innerHTML = event.message;
} else {
alert("else");
document.getElementById("responseErrors").innerHTML = event.message;
}
}, {escape:true});
}
$(document).ready(function(){
getOuterWrapperObjectByJSRemoting(Opp_Id);
});
var result_Global2;
function SetOuterWrapperObjectByJSRemoting(jsonString, oppId){
JSremotingController.setOuterWrapperObject(jsonString, oppId, function(result, event){
if(event.status) {
result_Global2 = result;
alert('updated..!!');
} else if (event.type === 'exception') {
alert("exception");
document.getElementById("responseErrors").innerHTML = event.message;
} else {
alert("else");
document.getElementById("responseErrors").innerHTML = event.message;
}
}, {escape:true});
}
var JSON_STR;
function getJSONObject(){
//Outer Wrapper
var objOpportunityWrapper = new Object();
objOpportunityWrapper["oppDescription"] = $("#inputOppDescription").val();
var InnerWrapper = new Object();
var InnerWrapperArray = new Array();
InnerWrapper["name"] = 'TEST Name1';
InnerWrapper["description"] = 'TEST Description1';
InnerWrapperArray[0] = InnerWrapper;
objOpportunityWrapper["listOfInnerWrapper"] = InnerWrapperArray;
JSON_STR = JSON.stringify(objOpportunityWrapper);
SetOuterWrapperObjectByJSRemoting(JSON_STR,Opp_Id);
}
</script>
<apex:pageBlock title="GET DATA BY JS REMOTING">
<apex:pageBlockSection >
<span id="SPANOppName"></span>
</apex:pageBlockSection>
</apex:pageBlock>
<apex:pageBlock title="SET/UPDATE DATA BY JS REMOTING">
<apex:pageBlockSection >
<apex:pageBlockSectionItem >
<span>Opportunity Description</span>
<input type="text" id="inputOppDescription" />
</apex:pageBlockSectionItem>
<apex:pageBlockSectionItem >
<input type="button" onclick="getJSONObject()" value="Update" class="btn"/>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>
to run this example you just need to copy & paste & change the Opp id in in the top of the vf page.
var Opp_Id = '006900000071POn';
the page ui will be as below
really nice to see this gr8 article on Mustache
ReplyDeletethanks for sharing !!!
Akhilesh