Visualforce is a powerful tool for building custom user interfaces, but with great power comes great responsibility. Making your pages lean and fast is essential to a great user experience and high adoption rates. This webinar will focus on some advanced Visualforce topics to help you improve page efficiency. This session is tailored for experienced developers who are already familiar with the Visualforce framework.
Watch this webinar to learn about:
:: Viewstate
:: JavaScript Remoting
:: Asynchronous Apex
:: Streaming API
4. This Advanced Webinar Assumes...
...you have used Visualforce and are comfortable with it.
...you have used Apex and are comfortable writing it.
...you understand HTML, JavaScript, and AJAX concepts.
Join the conversation: #forcewebinar
5. Your Frienemy:
View State
Join the conversation: #forcewebinar
6. Q: What is View State?
A: An encrypted, hidden <input> field on a Visualforce page that
keeps track of Apex controller state & Visualforce page state
between server requests. This field is only generated when
there is an <apex:form> tag present on a page.
Join the conversation: #forcewebinar
7. Visualforce Lifecycle
A
HTTP GET
A. URL Requested
E B. Apex Controller Instantiated on Server
HTTP POST
C. Controller State Serialized & Encrypted to View State
D. Page Markup Sent to Browser & Rendered
D
B E. View State Decrypted & Deserialized (for Postbacks)
<input type="hidden" value="..."/> C
Join the conversation: #forcewebinar
8. View State: Your Frienemy
Why it’s Great :-) Why it’s Not So Great :-(
• Automatically keeps track of field • Can be bulky, affecting performance.
values for you. • It has size limitations.
• Allows for easy AJAX functionality. • Doesn’t allow for complex AJAX
• Provides easy way to re-render page functionality.
components.
Join the conversation: #forcewebinar
9. View State is Required for...
<apex:action*>
<apex:command*>
<apex:inlineEditSupport>
<apex:input*>
<apex:select*>
Join the conversation: #forcewebinar
11. How Can I Manage My View State?
A. Reduce Number of Components
B. Use the transient Keyword
C. Use JavaScript Remoting
D. Use the Streaming API
Join the conversation: #forcewebinar
12. Option A: Reduce Number of Components
<apex:outputPanel layout="inline"...> <span...>
<apex:outputPanel layout="block"...> <div...>
<apex:panelGrid...> <table...>
<apex:outputLink...> <a...>
<apex:outputText styleClass="..."...> <span...>
Join the conversation: #forcewebinar
13. Option B: Use the transient Keyword
public with sharing class EditClientController {
public Contact client { get; set; }
transient public List<Contact> connections { get; set; }
transient public List<Account> previousEmployers { get; set; }
transient public Set<String> hashTags { get; set; }
...
}
Join the conversation: #forcewebinar
14. Option B: Use the transient Keyword
BEFORE
AFTER
58%
Join the conversation: #forcewebinar
15. Option C: Use JavaScript Remoting
Q: What is JavaScript Remoting?
A: Stateless way to call Apex controller methods from JavaScript.
Join the conversation: #forcewebinar
17. JavaScript Remoting Lifecycle
JS Function
Apex Method
Client-side
JS Callback Server-side
Join the conversation: #forcewebinar
18. JS Function
Apex Method
JS Callback
Join the conversation: #forcewebinar
19. Option C: JavaScript Remoting: The Page
<apex:page controller="FindCustomerController">
<input id="searchField" type="text" placeholder="Enter Last Name"/>
<button onclick="handleButtonClick();">Search</button>
<table>
<tbody id="results"></tbody>
</table>
JS Function
</apex:page> Apex Method
JS Callback
Join the conversation: #forcewebinar
20. Option C: JavaScript Remoting: The Page
<apex:page controller="FindCustomerController">
<input id="searchField" type="text" placeholder="Enter Last Name"/>
<button onclick="handleButtonClick();">Search</button>
<table>
<tbody id="results"></tbody>
</table>
JS Function
</apex:page> Apex Method
JS Callback
Join the conversation: #forcewebinar
21. Option C: JavaScript Remoting: The JavaScript
function handleButtonClick() {
var searchTerm = document.getElementById("searchField").value;
FindCustomerController.doSearch(searchTerm, renderResults);
}
JS Function
Apex Method
JS Callback
Join the conversation: #forcewebinar
22. Option C: JavaScript Remoting: The JavaScript
function handleButtonClick() {
var searchTerm = document.getElementById("searchField").value;
FindCustomerController.doSearch(searchTerm, renderResults);
}
Apex Class Apex Method Apex Method Parameter JS Callback Function
JS Function
Apex Method
JS Callback
Join the conversation: #forcewebinar
23. Option C: JavaScript Remoting: The Apex Class
public with sharing class FindCustomerController {
@RemoteAction
public static List<Contact> doSearch(String customerLastName) {
customerLastName = '%' + customerLastName + '%';
return [
SELECT id, FirstName, LastName
FROM Contact
WHERE LastName LIKE :customerLastName
LIMIT 200
]; JS Function
} Apex Method
JS Callback
}
Join the conversation: #forcewebinar
24. Option C: JavaScript Remoting: The Apex Class
public with sharing class FindCustomerController {
@RemoteAction
public static List<Contact> doSearch(String customerLastName) {
customerLastName = '%' + customerLastName + '%';
return [
SELECT id, FirstName, LastName
FROM Contact
WHERE LastName LIKE :customerLastName
LIMIT 200
]; JS Function
} Apex Method
JS Callback
}
Join the conversation: #forcewebinar
25. Option C: JavaScript Remoting: The Callback
function renderResults(results, event) {
var container = document.getElementById("results"),
html = [];
for (var i=0, j=results.length; i<j; i++) {
html.push("<tr><td>");
html.push(results[i].LastName + ", " + results[i].FirstName);
html.push("</td></tr>");
}
container.innerHTML = html.join(""); JS Function
} Apex Method
JS Callback
Join the conversation: #forcewebinar
26. Option C: JavaScript Remoting: The Results
JS Function
Apex Method
JS Callback
Join the conversation: #forcewebinar
27. Option C: JavaScript Remoting: The Results
BEFORE AFTER
234ms 152ms
35%
Join the conversation: #forcewebinar
28. Option D: Use the Streaming API
Q: What is the Streaming API?
A: A highly performant way to get near-real-time updates from
a Salesforce instance without polling.
Join the conversation: #forcewebinar
29. Option D: Use the Streaming API
BEFORE
<apex:page controller="NewAccountsController">
<apex:form>
<apex:actionPoller action="{!find}" rerender="wrapper" interval="15"/>
<h1>Streaming API Example</h1>
<h2>New Accounts</h2>
<apex:outputPanel id="wrapper"></apex:outputPanel>
</apex:form>
</apex:page>
Join the conversation: #forcewebinar
30. Option D: Use the Streaming API
AFTER
<apex:page controller="NewAccountsController">
<apex:includeScript value="..."/> <!-- 4 js files needed -->
<h1>Streaming API Example</h1>
<h2>New Accounts</h2>
<div id="wrapper"></div>
<script>... $.cometd.init(...) $.cometd.subscribe(...) ...</script>
</apex:page>
Join the conversation: #forcewebinar
31. Option D: Use the Streaming API: Steps
Determine Your SOQL Query
Create a PushTopic Record
Include Necessary JavaScript Libraries on Visualforce Page
Call cometd’s init(...) and subscribe(...) Functions (Inline JS)
Watch Magic Happen
Join the conversation: #forcewebinar
33. Asynchronous Apex
public with sharing class SendInvoiceController{
@RemoteAction
public static String requestAllInvoices(String customerId) {
sendAllInvoices(customerId);
return('All invoices have been requested.');
}
@future
private static void sendAllInvoices(String customerId) {
EmailHelper.emailCustomerInvoices(customerId);
}
}
Join the conversation: #forcewebinar
34. Survey
Your feedback is crucial to the success of our webinar programs.
Thank you!
http://bit.ly/advancedvfsurvey
Join the conversation: #forcewebinar
35. Q&A
Eric Wilson
Director, Product Management
UI Platforms
Join the conversation: #forcewebinar
36. Upcoming Events
December 11, 2012
AppExchange for Developers Webinar
http://bit.ly/XnFERP
December 12, 2012
Apex CodeTalk Live Q&A
http://bit.ly/apexct-vf
Check out the Developer Force calendar for upcoming local events such as meetups,
workshops, and user group meetings: http://developer.force.com/Calendar
Join the conversation: #forcewebinar