Showing posts with label Apex. Show all posts
Showing posts with label Apex. Show all posts
Sunday, July 3, 2016
System.CalloutException: Server chose TLSv1, but that protocol version is not enabled or not supported by the client
This summary is not available. Please
click here to view the post.
Tuesday, May 31, 2016
Setup MavensMate for salesforce - Windows 10
Recently I got a chance to setup MavensMate at windows 10 machine for salesforce. I tried but there were couple of issues which I faced. Just sharing the blog post to get rid of those issues & setup MavensMate on Windows 10 Machine.
#1-Install Sublime text 3 from below link –
#2-Click on the red marked link.
#3-Download & install this, restart sublime text after
it is installed.
#4-open url - https://packagecontrol.io/installation
#5-Copy
red marked text
#6-Open console in sublime text. You can find this option at
View à
Show Console.
#7-Paste this long text in console & hit enter.
#8-If it is failed try one more time. Once this is done
restart sublime text.
#9-Go to preferences à
package control
Type install MavensMate & hit enter
#10-Restart Sublime text
#11-Create a folder in your directory for workspace.
For Eg – D:\ Mavensmate_Workspace
#12-open sublime text, go to MavensMate à Setting à User
You will see a node – “mm_workspace", put your
workspace path here.
#13-To create a new project, go to MavensMate à New Project
#14-It will open url in Edge browser. This may show you
below error, when you enter the login detail & try to create project.
#15-To resolve this issue, copy url (which is in Edge) & open firefox & paste it here, hit enter. Put all the login details & create project from here.
#16-You may see another error after this, error would be [XXX]
- Access is denied.
To resolve this go to your workspace folder, right click, go to security & give all permissions to current user & all other user as well & then try
to create.
This will solve your issue & will create a new project!!
Update - 11 Sept 2016
----------------------------------------------------------------------------------------
Result: [ERROR]: Request to the local MavensMate server failed. please ensure the MavensMate-app is installer and running.
In version 7+ of MavensMate for Sublime Text, there is a new companion app called MavensMate-app. You must download, install, and run this application in order for the MavensMate for Sublime Text plugin to operate. For more information, please visit https://github.com/joeferraro/MavensMate-app
Update - 11 Sept 2016
----------------------------------------------------------------------------------------
Result: [ERROR]: Request to the local MavensMate server failed. please ensure the MavensMate-app is installer and running.
In version 7+ of MavensMate for Sublime Text, there is a new companion app called MavensMate-app. You must download, install, and run this application in order for the MavensMate for Sublime Text plugin to operate. For more information, please visit https://github.com/joeferraro/MavensMate-app
To resolve this issue, open url https://github.com/joeferraro/MavensMate-Desktop/releases
Go to download section & download the exe according to OS.
install this, & whenever you want to run sublime text + mavensmate, you need to run this app first. after installation go to search & click on Mavensmate app first & then open sublime text.
Labels:
Apex,
Force.com IDE,
MavensMate,
Salesforce,
Salesforce IDE,
Windows 10
Thursday, April 30, 2015
Avoid simultaneous update/ Control same record if already opened by someone in edit mode & show a message to end user
Recently I came across a requirement where client wanted to track if any other user also open the same record to edit, in this case he wanted to show a message to second user so he can edit the same record latter.
To solve this I created a custom setting let’s say Control_Record_Edit__c. Created few other fields to track edit mode –
Name
Edit_DateTime__c
User_Id__c
Name:- field will save record id which is opened in edit mode by someone.
Edit_DateTime__c:- field will tell us how long someone open a record in edit mode
User_Id__c:- field will tell us who open that record in edit mode.
Now let’s say we want to track lead record. We will create a new VF page that will be called LeadEdit.page. In this page we will have a function called init which will basically insert a record in our custom setting, so next time whenever someone open the same lead it edit mode we can check in code & show a message that another user is already opened this lead in edit mode.
Class code is as below
Here after this one other issue appear when user click on cancel, if user open a lead & click on cancel we should remove his record from custom setting but the problem is cancel override is not available in salesforce. To handle this we created another page that is called LeadCancel & we are passing it in the retURL parameter.
now in the class code there is a method initCancel, that is basically deleting the record from custom setting if a user open a lead & click on cancel button. also we are passing this cancel page in retuURL parameter so when user click on cancel it will be back to our page.
There is only one point here which is important, if a user open a lead & close it by browser close button then we can not track that action & in that case no one can edit the same lead until that record does not removed from custom setting.
To solve this I created a custom setting let’s say Control_Record_Edit__c. Created few other fields to track edit mode –
Name
Edit_DateTime__c
User_Id__c
Name:- field will save record id which is opened in edit mode by someone.
Edit_DateTime__c:- field will tell us how long someone open a record in edit mode
User_Id__c:- field will tell us who open that record in edit mode.
Now let’s say we want to track lead record. We will create a new VF page that will be called LeadEdit.page. In this page we will have a function called init which will basically insert a record in our custom setting, so next time whenever someone open the same lead it edit mode we can check in code & show a message that another user is already opened this lead in edit mode.
<apex:page standardController="lead" extensions="LeadEditController" action="{!init}"> <apex:form id="form1"> <apex:outputPanel rendered="{!isNeedToShowMsg}"> <apex:pageMessages id="error"/> <apex:commandButton value="Go To Lead" action="/{!objLead.Id}" style="margin-left: 20px;"/> </apex:outputPanel> </apex:form> </apex:page>
Class code is as below
public with sharing class LeadEditController { public Lead objLead {get;set;} public boolean isNeedToShowMsg {get;set;} public LeadEditController(ApexPages.StandardController stdController){ objLead = (Lead)stdController.getRecord(); } public PageReference init(){ isNeedToShowMsg = false; PageReference pr = NULL; ListlistOfControlLeadUpdate = [SELECT Id,User_Id__c,Edit_DateTime__c from Control_Lead_Update__c where Name=:objLead.Id and User_Id__c !=:Userinfo.getUserId() LIMIT 1]; if(listOfControlLeadUpdate != NULL && !listOfControlLeadUpdate.isEmpty()){ List listOfUser = [Select Id, Name from User where Id=:listOfControlLeadUpdate.get(0).User_Id__c LIMIT 1]; if(listOfUser != NULL && !listOfUser.isEmpty()){ String Msg = 'Another User ' + listOfUser.get(0).Name + ' already start editing the same lead at '+ listOfControlLeadUpdate.get(0).Edit_DateTime__c.format() +', Please wait for sometime & click on edit button again!'; ApexPages.Message apexmsg = new ApexPages.Message(ApexPages.Severity.INFO, Msg); ApexPages.addMessage(apexmsg); isNeedToShowMsg = true; } }else{ Control_Lead_Update__c objControlLead = new Control_Lead_Update__c(); objControlLead.Name = objLead.Id; objControlLead.Edit_DateTime__c = datetime.now(); objControlLead.User_Id__c = Userinfo.getUserId(); try{ insert objControlLead; }catch(Exception ex){ system.debug('exception::-->>>' + ex); } pr = new PageReference('/' + objLead.Id + '/e?nooverride=1&retURL=/apex/LeadCancel?Id=' + objLead.Id); } return pr; } public PageReference initCancel(){ LeadHandler.ReleaseEditModeForOthers(new List {objLead}); PageReference pr = new PageReference('/' + objLead.Id); return pr; } }
Here after this one other issue appear when user click on cancel, if user open a lead & click on cancel we should remove his record from custom setting but the problem is cancel override is not available in salesforce. To handle this we created another page that is called LeadCancel & we are passing it in the retURL parameter.
<apex:page standardController="lead" extensions="LeadEditController" action="{!initCancel}"> </apex:page>
now in the class code there is a method initCancel, that is basically deleting the record from custom setting if a user open a lead & click on cancel button. also we are passing this cancel page in retuURL parameter so when user click on cancel it will be back to our page.
There is only one point here which is important, if a user open a lead & close it by browser close button then we can not track that action & in that case no one can edit the same lead until that record does not removed from custom setting.
Tuesday, August 12, 2014
Small Utilities Method
Hi friends, I am back from long time, in between this I could not get a chance to post anything new.
In this post I am showing you small utility methods which we use everyday. This can help if you are looking any quick tip or help -
In this post I am showing you small utility methods which we use everyday. This can help if you are looking any quick tip or help -
Maphere if you debug mapOfUserRoleWithHierarchy map you will see something like below -mapOfUserRole = new Map ([SELECT Id, Name, ParentRoleId FROM UserRole]); Map mapOfUserRoleWithHierarchy = new Map (); public void processRoles(){ String level = ''; List ListOfUserRole = [SELECT Name, Id FROM UserRole]; if(ListOfUserRole != NULL && ListOfUserRole.Size()>0){ for(UserRole u:ListOfUserRole){ level = processParentRole(u.Id,''); if(level != ''){ mapOfUserRoleWithHierarchy.put(u.Id,level); } } } } public String processParentRole(Id role, String hierarchyString){ UserRole userrole = mapOfUserRole.get(role); if(userrole.ParentRoleId != NULL){ hierarchyString += '>>' + userrole.Name; return processParentRole(userrole.ParentRoleId,hierarchyString); }else{ hierarchyString += '>>'+userrole.Name; return hierarchyString; } } processRoles();
00EXXXXXXXX=>>Team1>>Team2>>Team3>>Team4>>CEOhere I am assuming that hierarchy in your system something like
-CEO -Team4 -Team3 -Team2 -Team1Hope this can help if you are doing some code & need something related to user role hierarchy! will keep adding other util method in this post so this can be used kind of quick reference:)
Wednesday, August 7, 2013
How to give a name while export a file in csv/xls
Hi friends, recently I came across a situation where client want's to give a name while exporting a file in csv/xls. In salesforce we can not code in such a way that it will ask you any name before save the file at your local drive. Alternate solution is we can pass different names from the different pages, so we can distinguish in between two exported files from different pages. Here is the detail how you can do this.
We need to create below resources for it-
#1-BlogCSV.page
#2-BlogCSV.component
#3-BlogCSVController.cls
#4-ExportTestPage.page
let me take this one by one & tell you how we can pass name while export in this.
#1-BlogCSV.page
This is a VF page which generate a xls file for given table.
here the important thing is we will pass contenttype attribute something like below
contentType="application/vnd.ms-excel#{!SUBSTITUTE($CurrentPage.parameters.page,'XXXXXX__','')}_YOUR_POSTFIX_HERE.xls"
in this the exported file name will be build by Page Name from where it is exported + your postfix whatever you give in above content type attribute.
here is the complete code for this-
#2-BlogCSV.component
this component is simply rendering the account table which will be going to export.
#3-BlogCSVController.cls
this class is common controller class for both component & page. here is the code for this -
#4-ExportTestPage.page
finally this is the page where will provide export button which will initiate export.Here is the code-
here notice that we are passing current page name in action function.
Now when you click on export this will be exported with your page name & given postfix.
You can see a demo here
We need to create below resources for it-
#1-BlogCSV.page
#2-BlogCSV.component
#3-BlogCSVController.cls
#4-ExportTestPage.page
let me take this one by one & tell you how we can pass name while export in this.
#1-BlogCSV.page
This is a VF page which generate a xls file for given table.
here the important thing is we will pass contenttype attribute something like below
contentType="application/vnd.ms-excel#{!SUBSTITUTE($CurrentPage.parameters.page,'XXXXXX__','')}_YOUR_POSTFIX_HERE.xls"
in this the exported file name will be build by Page Name from where it is exported + your postfix whatever you give in above content type attribute.
here is the complete code for this-
<apex:page language="en-US" cache="false" readonly="true" sidebar="false" showHeader="false" pageStyle="false" contentType="application/vnd.ms-excel#{!SUBSTITUTE($CurrentPage.parameters.page,'PackagePrefix__','')}_YOUR_POSTFIX_HERE.xls"> <c:BlogCSV id="csvComponent1" /> </apex:page>
#2-BlogCSV.component
this component is simply rendering the account table which will be going to export.
<apex:component controller="BlogCSVController" id="component1"> <apex:pageBlock > <apex:pageBlockTable value="{!lstOfAccount}" var="lst" width="100%" rendered="{!IF(lstOfAccount.Size>0,true,false)}"> <apex:column > <apex:facet name="header" > Name </apex:facet> <apex:outputLink value="{!lst.id}" >{!lst.Name}</apex:outputLink> </apex:column> <apex:column > <apex:facet name="header" > AccountSource </apex:facet> <apex:outputLabel value="{!lst.AccountSource}" /> </apex:column> </apex:pageBlockTable> </apex:pageBlock> </apex:component>
#3-BlogCSVController.cls
this class is common controller class for both component & page. here is the code for this -
public with sharing class BlogCSVController { public string currentPage {get;set;} public String redirectURL {get;set;} public PageReference Export(){ PageReference pr = Page.BlogCSV; pr.getParameters().put('page',currentPage); redirectURL = pr.getUrl(); return null; } public ListlstOfAccount{get;set;} public BlogCSVController(){ lstOfAccount = [Select Id,Name, AccountSource from Account LIMIT 10]; } }
#4-ExportTestPage.page
finally this is the page where will provide export button which will initiate export.Here is the code-
<apex:page controller="BlogCSVController"> <apex:form id="form1"> <apex:pageMessages id="msg" /> <apex:sectionHeader Title="Export" subtitle="XLS Sample" /> <apex:pageBlock id="block1"> <apex:pageBlockButtons location="top"> <input type="button" class="btn" value="Export" onclick="Export('{!$CurrentPage.Name}');" /> <apex:actionStatus id="statusLoadingMain"> <apex:facet name="start"> <span style="font-weight:bold; color: red;"> Please wait while exporting...<img src="/img/loading.gif" /> </span> </apex:facet> </apex:actionStatus> </apex:pageBlockButtons> <script> function Export(pagename){ jsExport(pagename); } </script> <apex:outputPanel id="pnlExport"> <script> if("{!redirectURL}" != ""){ window.location.href="{!redirectURL}"; } </script> </apex:outputPanel> <apex:actionFunction status="statusLoadingMain" name="jsExport" action="{!Export}" rerender="pnlExport,msg"> <apex:param name="currentPage" id="currentPage" value="" assignto="{!currentPage}" /> </apex:actionFunction> </apex:pageBlock> <c:BlogCSV id="csvComponent1" /> </apex:form> </apex:page>
here notice that we are passing current page name in action function.
Now when you click on export this will be exported with your page name & given postfix.
You can see a demo here
Labels:
Apex,
Export CSV,
Export file,
name in export,
Salesforce,
xls
Wednesday, February 27, 2013
SOQL Injection
Hi friends,
While writing dynamic SOQL query, I came to know that we should care about the injection script. I tried to get the way how one can write this kind of script so code starts giving unexpected result. I did a lot of rnd on internet but I found the same sample everywhere which is given in salesforce pdf file, but still I was not getting the practical example that satisfy my SOQL injection doubt.
Because of this reason I created a sample to clear my self what is SOQL injection & how this can give you unexpected result. Here I am sharing it with you so you will get an idea what does SOQL injection means.
You can see demo here. There are four buttons in this page. these are quite simple & self explanatory but let me explain in detail if you have any doubt-
Button -1 Execute
This button shows how simple dynamic query works if we use Equal comparison
Button -2 Execute Like
This button shows how simple dynamic query works if we use LIKE comparison
Button -3 Execute Escape
This button show how dynamic query works if we use String.escapeSingleQuotes method in case of equal comparison
Button -4 Execute Like Escape
This button show how dynamic query works if we use String.escapeSingleQuotes method in case of LIKE comparison
salesforce recommend to use String.escapeSingleQuotes method if you are writing dynamic query.
Now If you open this page & enter the text just after the button "Account1' OR name<>'abc" & click on all four buttons & see the output difference.
In the first two buttons we are not using escapeSingleQuotes while in the last two buttons we are using escapeSingleQuotes method.
here when we give injection script (Account1' OR name<>'abc) first two button show all account in the system, that should not be. while in the last two buttons because we are using escapeSingleQuotes method that does not allow to execute this injection script.
here is the code of page & class-
SOQL.page
& class code.. SOQLController.cls
While writing dynamic SOQL query, I came to know that we should care about the injection script. I tried to get the way how one can write this kind of script so code starts giving unexpected result. I did a lot of rnd on internet but I found the same sample everywhere which is given in salesforce pdf file, but still I was not getting the practical example that satisfy my SOQL injection doubt.
Because of this reason I created a sample to clear my self what is SOQL injection & how this can give you unexpected result. Here I am sharing it with you so you will get an idea what does SOQL injection means.
You can see demo here. There are four buttons in this page. these are quite simple & self explanatory but let me explain in detail if you have any doubt-
Button -1 Execute
This button shows how simple dynamic query works if we use Equal comparison
Button -2 Execute Like
This button shows how simple dynamic query works if we use LIKE comparison
Button -3 Execute Escape
This button show how dynamic query works if we use String.escapeSingleQuotes method in case of equal comparison
Button -4 Execute Like Escape
This button show how dynamic query works if we use String.escapeSingleQuotes method in case of LIKE comparison
salesforce recommend to use String.escapeSingleQuotes method if you are writing dynamic query.
Now If you open this page & enter the text just after the button "Account1' OR name<>'abc" & click on all four buttons & see the output difference.
In the first two buttons we are not using escapeSingleQuotes while in the last two buttons we are using escapeSingleQuotes method.
here when we give injection script (Account1' OR name<>'abc) first two button show all account in the system, that should not be. while in the last two buttons because we are using escapeSingleQuotes method that does not allow to execute this injection script.
here is the code of page & class-
SOQL.page
<apex:page controller="SOQLController" tabStyle="Account"> <apex:form id="form1"> <apex:pageBlock id="block1"> <apex:inputText value="{!name}" /> <apex:commandButton value="Execute" action="{!Execute}" rerender="pnl" /> <apex:commandButton value="Execute Like" action="{!ExecuteLike}" rerender="pnl" /> <apex:commandButton value="Execute Escape" action="{!ExecuteEscape}" rerender="pnl" /> <apex:commandButton value="Execute Like Escape" action="{!ExecuteLikeEscape}" rerender="pnl" /> <apex:outputLabel value="Account1' OR name<>'abc"></apex:outputLabel> <apex:outputPanel id="pnl"> <apex:pageBlockTable value="{!lstAccount}" var="lst" id="tbl"> <apex:column value="{!lst.Name}" /> </apex:pageBlockTable> <apex:pageBlockSection title="Query" columns="1"> <apex:outputLabel value="{!query}" id="qry"/> </apex:pageBlockSection> </apex:outputPanel> </apex:pageBlock> </apex:form> </apex:page>
& class code.. SOQLController.cls
public with sharing class SOQLController { public List<Account> lstAccount{get;set;} public string query {get;set;} public String name {get;set;} public void Execute(){ String StrName = '=\'' + name + '\''; query = 'Select Id, Name from Account where name ' + StrName ; lstAccount = Database.Query(query); //input -- Account1' OR name<>'xxx } public void ExecuteLike(){ String StrName = 'LIKE \'%' + name + '%\''; query = 'Select Id, Name from Account where name '+ StrName; lstAccount = Database.Query(query); } public void ExecuteEscape(){ String StrName = '=\'' + String.escapeSingleQuotes(name) + '\''; query = 'Select Id, Name from Account where name ' + StrName; lstAccount = Database.Query(query); } public void ExecuteLikeEscape(){ String StrName = 'LIKE \'%' + String.escapeSingleQuotes(name) + '%\''; query = 'Select Id, Name from Account where name ' + StrName ; lstAccount = Database.Query(query); } }
Labels:
Apex,
Dynamic Query,
escapeSingleQuotes,
Salesforce,
SOQL,
SOQL Injection
Thursday, February 21, 2013
Show Star Rating as Salesforce Standard Field
Hi friends, this time I am coming with a solution for star rating. if you want to show star rating in a standard salesforce layout in form of column.
Take a look of below image. in this I am showing some rating as like this is a stanadrd field in salesforce.
Take a look of below image. in this I am showing some rating as like this is a stanadrd field in salesforce.
In above image notice that you rating field is appear same as standard field on UI. here is how you can do this-
Step-1
Create a new page named "StarRating" & a new controller class "StarRatingController" in salesforce.
Step-2
Get a jquery star plugin files from net & upload these files in salesforce static resource. I will also tell you the path one of my page latter from where you can download these files.
Step-3
I assuming that you uploaded two static resource -
a-OrgResource
b-jQueryStarRatingPlugIn
in first zip file we are having all jquery js & css files. although we are going to use few of them.
second one zip file is having all files which we downloaded from jquery plugin site.
Step-4
Copy & paste below code in VF page
Step-6
Click on account tab, this will show you list of account. Open one account & click on Edit Layout link at top left.
Step-7
Add a new section from the layout. Give any name to this section.Uncheck Display Section Header On two check box (Detail page & Edit page). In Layout option select 1-Column option & click on save.
Step-8
Add starRating VF page to this section & set height 20 & width 100%.
<apex:page id="page1" sidebar="false" showHeader="false" standardController="Account" extensions="StarRatingController"> <apex:styleSheet value="{!URLFOR($Resource.OrgResource,'development-bundle/themes/base/jquery.ui.all.css')}" /> <apex:styleSheet value="{!URLFOR($Resource.jQueryStarRatingPlugIn,'jquery.ui.stars.css')}" /> <apex:includeScript value="{!URLFOR($Resource.OrgResource,'js/jquery-1.5.1.js')}" /> <apex:includeScript value="{!URLFOR($Resource.OrgResource,'development-bundle/ui/jquery.ui.core.js')}" /> <apex:includeScript value="{!URLFOR($Resource.OrgResource,'development-bundle/ui/jquery.ui.widget.js')}" /> <apex:includeScript value="{!URLFOR($Resource.jQueryStarRatingPlugIn,'jquery.ui.stars.min.js')}" /> <style> .detailList{ width:94%; } .pbBody, .pbBody a, .pbBody td, .lbBody a, .lbBodyDescription, .list .headerRow .noRowsHeader { border-bottom: 0 none !important; } </style> <apex:form id="form1"> <apex:pageBlock > <div id="ep" class="bDetailBlock bPageBlock secondaryPalette"> <div class="pbSubsection"> <table cellspacing="0" cellpadding="0" border="0" class="detailList" style="border-bottom:none !important;" > <tbody> <tr> <td class="labelCol">Rating</td> <td class="dataCol col02"> <apex:outputPanel > <div class="divRating"> <apex:selectList value="{!rating}" size="1"> <apex:selectOptions value="{!listOfRatingOptions}" /> </apex:selectList> </div> </apex:outputPanel> </td> <td class="labelCol"> </td> <td class="dataCol col02"> </td> </tr> </tbody> </table> </div> </div> <script> jQuery(document).ready(function(){ jQuery(".divRating").stars({ inputType: "select", cancelShow: false, disabled:true }); $(".accountBlock").children().attr('class',''); $(".detailList").css('width','94%'); }); </script> </apex:pageBlock> </apex:form> </apex:page>Step-5 Copy & paste below class code in controller which you create few steps back
public with sharing class StarRatingController { public integer rating {get;set;} public List<SelectOption> listOfRatingOptions {get;set;} public StarRatingController(ApexPages.StandardController controller){ listOfRatingOptions = new List<SelectOption>(); rating = 3; string val = ''; for(integer i=1;i<=5;i++){ val = string.valueOf(i); listOfRatingOptions.add(new SelectOption(val,val)); } } }now you can include this page in account stadarad layout. To add this follow next steps.
Step-6
Click on account tab, this will show you list of account. Open one account & click on Edit Layout link at top left.
Step-7
Add a new section from the layout. Give any name to this section.Uncheck Display Section Header On two check box (Detail page & Edit page). In Layout option select 1-Column option & click on save.
Step-8
Add starRating VF page to this section & set height 20 & width 100%.
Save layout & see that rating is available same as a standard field on account detail.
here is the link of star rating page if you want to see how this looks like.You can also download the static resource files by view source.
The same thing you can also do on any VF page. here is demo page. the code of this demo page is as below-
<apex:page standardController="Account" extensions="SiteStarRatingController" id="page1"> <apex:sectionHeader title="Site" subTitle="Star Rating Sample" /> <apex:pageBlock id="block1"> <apex:pageBlockSection columns="1"> <apex:pageBlockSectionItem > <apex:outputLabel value="Account Name" /> <apex:outputField value="{!act.Name}" /> </apex:pageBlockSectionItem> </apex:pageBlockSection> <apex:pageBlockSection columns="1"> <apex:iframe src="/apex/StarRating" height="20px" /> </apex:pageBlockSection> <apex:pageBlockSection columns="1"> <apex:pageBlockSectionItem > <apex:outputLabel value="Type" /> <apex:outputField value="{!act.Type}" /> </apex:pageBlockSectionItem> <apex:pageBlockSectionItem > <apex:outputLabel value="Description" /> <apex:outputField value="{!act.Description}" /> </apex:pageBlockSectionItem> <apex:pageBlockSectionItem > <apex:outputLabel value="Fax" /> <apex:outputField value="{!act.Fax}" /> </apex:pageBlockSectionItem> </apex:pageBlockSection> </apex:pageBlock> </apex:page>controller class is as below-
public with sharing class SiteStarRatingController { public Account act{get;set;} public SiteStarRatingController(ApexPages.StandardController controller){ act = [Select Id,Name,Type, Industry, Fax, Description from Account limit 1]; } }Done..!! :)
Labels:
Apex,
jquery,
jQyery Rating,
Salesforce,
Star Rating
Sunday, August 12, 2012
Salesforce Deployment - Delete a file through ANT
When we use ant deployment here is the folder hierarchy which we use-
ANT Sample Folder
>>mypkg Folder
>>retrieveUnpackaged Folder
>> removecodepkg Folder [Create this new folder to delete the files]
>>build.properties files
>>build.xml
To delete a resource you need to add a destructiveChanges.xml file in removecodepkg folder. The destructiveChanges.xml file is same as package.xml. format of this file is as below-
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>LoginController</members>
<members>LoginControllerTest</members>
<name>ApexClass</name>
</types>
<version>19.0</version>
</Package>
You also need to have a blank package.xml file in the same removecodepkg folder. Format of the file will be-
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<version>19.0</version>
</Package>
Now you have two xml files in removecodepkg folder –
1-destructiveChanges.xml
2-package.xml
ant is having build.xml file which have all commands can be executed. There will be a command to delete the code-
<target name="undeployCode">
<sf:deploy username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" deployRoot="removecodepkg"/>
</target>
Now mention the name of the resource in destructiveChanges.xml file & delete the file from destination org. in our example I am deleting a class LoginController & it’s test class.
You just need to execute below command on ant
>>ant undeployCode
Wednesday, May 30, 2012
JS Remoting in Salesforce with Mustache
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
Labels:
Apex,
js remoting,
JS templates,
mustache,
Salesforce
Subscribe to:
Posts (Atom)