Advanced Visualforce Webinar
-
Upload
salesforce-developers -
Category
Documents
-
view
2.287 -
download
2
description
Transcript of Advanced Visualforce Webinar
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