Upload
salesforce-developers
View
2.290
Download
2
Embed Size (px)
DESCRIPTION
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
Citation preview
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
Force.com Webinar:Advanced Visualforce
Eric WilsonDirector, Product ManagementUI Platforms
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
Agenda
1. Assumptions2. Your Frienemy: View State3. Managing View State4. Asynchronous Apex
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
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.
Q: What is View State?
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
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.
Visualforce Lifecycle
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
A. URL Requested
B. Apex Controller Instantiated on Server
C. Controller State Serialized & Encrypted to View State
D. Page Markup Sent to Browser & Rendered
E. View State Decrypted & Deserialized (for Postbacks)
<input type="hidden" value="..."/>
HTTP POST
HTTP GET
A
B
C
D
E
View State: Your Frienemy
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
Why it’s Not So Great :-(
• Can be bulky, affecting performance.
• It has size limitations.
• Doesn’t allow for complex AJAX functionality.
Why it’s Great :-)
• Automatically keeps track of field values for you.
• Allows for easy AJAX functionality.
• Provides easy way to re-render page components.
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
View State is Required for...
<apex:action*><apex:command*><apex:inlineEditSupport><apex:input*><apex:select*>
How Can I Manage My View State?
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
A. Reduce Number of Components
B. Use the transient Keyword
C. Use JavaScript RemotingD. Use the Streaming API
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
Option A: Reduce Number of Components
<apex:outputPanel layout="inline"...>
<apex:outputPanel layout="block"...>
<apex:panelGrid...>
<apex:outputLink...>
<apex:outputText styleClass="..."...>
<span...>
<div...>
<table...>
<a...>
<span...>
Option B: Use the transient Keyword
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
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: #forcewebinarJoin the conversation: #forcewebinar
Option B: Use the transient Keyword
58%
BEF
OR
EA
FTER
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
Option C: Use JavaScript Remoting
Q: What is JavaScript Remoting?A: Stateless way to call Apex controller methods from JavaScript.
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
Option C: Use JavaScript Remoting
Find Customer:
<apex:actionFunction ... /><apex:actionRegion ... /><apex:actionSupport ... />
JavaScript Remoting
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
JavaScript Remoting Lifecycle
JS Function
Apex Method
JS CallbackClient-side
Server-side
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
JS Function
Apex Method
JS Callback
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
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>
</apex:page>JS Function
Apex Method
JS Callback
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
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>
</apex:page>JS Function
Apex Method
JS Callback
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
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: #forcewebinarJoin the conversation: #forcewebinar
Option C: JavaScript Remoting: The JavaScript
function handleButtonClick() { var searchTerm = document.getElementById("searchField").value; FindCustomerController.doSearch(searchTerm, renderResults);}
JS Callback FunctionApex Method ParameterApex Class Apex Method
JS Function
Apex Method
JS Callback
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
Option C: JavaScript Remoting: The Apex Classpublic 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: #forcewebinarJoin the conversation: #forcewebinar
Option C: JavaScript Remoting: The Apex Classpublic 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: #forcewebinarJoin the conversation: #forcewebinar
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: #forcewebinarJoin the conversation: #forcewebinar
Option C: JavaScript Remoting: The Results
JS Function
Apex Method
JS Callback
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
Option C: JavaScript Remoting: The Results
234ms 152ms35%
BEFORE AFTER
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
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: #forcewebinarJoin the conversation: #forcewebinar
Option D: Use the Streaming API
<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>
BEFORE
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
Option D: Use the Streaming API
<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>
AFTER
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
Option D: Use the Streaming API: Steps
Determine Your SOQL QueryCreate a PushTopic RecordInclude Necessary JavaScript Libraries on Visualforce PageCall cometd’s init(...) and subscribe(...) Functions (Inline JS)Watch Magic Happen
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
Asynchronous Apexpublic 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: #forcewebinarJoin the conversation: #forcewebinar
SurveyYour feedback is crucial to the success of our webinar programs.
Thank you!
http://bit.ly/advancedvfsurvey
Join the conversation: #forcewebinarJoin the conversation: #forcewebinar
Q & A
Eric WilsonDirector, Product ManagementUI Platforms
Join the conversation: #forcewebinar
Upcoming Events
December 11, 2012AppExchange for Developers Webinarhttp://bit.ly/XnFERP
December 12, 2012Apex CodeTalk Live Q&Ahttp://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