Discover Lightning on Trailhead!

Lightning-1024x512Unless you’ve been living under a rock lately in the Salesforce community, you’ve heard about the new Lightning Experience (“LEX”) due out in Winter ’16!  (queue elated yet half-scared applause and amazement)

Also, unless you’ve been living under a rock or have not read my previous posts, I’m a pretty rabid fan of Salesforce Trailhead as well – and they have come through with bright shiny colors on delivering FOUR NEW TRAILS all around migrating, administering, and developing around the initial release of LEX.  If you are a developer, administrator, or even end-user – there are trails for you!

My biggest questions have been around “what works and what doesn’t so I can accurately advise my clients”.  I’m slowly digesting the new Winter ’16 pre-release notes that dropped at the end of last week, but as I’ve said before – Trailhead content is written in a way to cut right to the quick; give me contextually-appropriate major chunks of information and test me to ensure I comprehended it right.  There are many times where a Trailhead challenge has given me information in JUST SLIGHTLY a different light that (full pun intended) sets off the light bulb in my brain.

Without further ado, I wanted to introduce you to the four new Trailhead trails and my take on each.  You’ll see some overlap between some of the trails – some modules and challenges cross trails to ensure maximum contextual assistance.

Trail 1:  “Admin Trail – Migrating to Lightning Experience”

Where:  https://developer.salesforce.com/trailhead/trail/lex_admin_migration

Who:  Admins and Developers

What:  Four modules walk you through topics such as:

  • What is LEX and is it right for your organization?
    • Yes!  There are things that work and don’t work – this is “version 1” ya know…
  • How to enable LEX for discovery and testing
  • Navigating setup and new LEX-exclusive enhancements
  • Customizing the LEX UI and a re-introduction to Actions
    • Bye-bye URL hacks!
    • Bye-bye Javascript buttons!
    • Bye-bye raw URL navigation!
  • Setting yourself up for a successful deployment

When:  Do this one first.

Why:  Unless your users are a group of supermen and superwomen that can handle any blip that comes their way, LEX is going to be a tough rollout – specifically in user training and “Salesforce Classic” feature parity.  Start your education here.

Trail 2:  “Admin Trail – Starting with Lightning Experience”

Where:  https://developer.salesforce.com/trailhead/trail/lex_admin_implementation

Who:  Admins and Developers

What:  Three modules walk you through topics such as:

  • Introduction to Salesforce and Lightning
  • Diving into the new Opportunity Workspace
  • Customizing Layouts, Actions, Objects, and Fields
  • Executing a LEX education plan and strategy for your company
  • Dropping the hammer:  LEX Rollout

When:  Do this one second.

Why:  LEX is the #1 largest UI-based change in over a decade.  The underlying administration concepts and foundational abilities aren’t changing, but how you and your users access them are.  You need to learn the gaps that do exist in LEX v1 and how to appropriately mitigate or delay each area so you aren’t left high and dry.

NOTE!  This trail was originally designed for brand new admins who are walking into a Winter ’16 org with LEX enabled, but EVERYONE can learn from this module.

Trail 3:  “Developer Trail – Lightning Experience”

Where:  https://developer.salesforce.com/trailhead/trail/lex_dev

Who:  Developers primarily, but Admins can learn a LOT from this as well

What:  Five modules walk you through topics such as:

  • What is LEX and is it right for your organization?
    • Yes!  There are things that work and don’t work – this is “version 1” ya know…
  • How to enable LEX for discovery and testing
  • UI framework and approach
  • How LEX impacts Visualforce overall
  • How LEX impacts ISVs, Packaging, and the AppExchange
    • How to tell if your 3rd party packages are ready for LEX
  • What else is changing with development tools?
  • How to use Visualforce within the LEX framework
    • Overall expectations
    • Navigation
    • Styling
    • What NOT to do in LEX
  • How to use Lightning Components with the LEX framework
    • Components and Attributes
    • Standard and Force.com Components
    • Events and JavaScript handling
  • Lightning Design System (LDS)
    • SURPRISE!
    • Salesforce has released a Salesforce bootstrap framework
    • How to use it
    • How NOT to use it…

When:  Do this one third overall, or if you’re a dev – do it first just for LDS.

Why:  Because you’re a developer and have questions about how your knowledge will convert into the LEX world – flat out.  Salesforce does not have any delusions that LEX will be perfect on “day 1”, nor do they expect that everyone will be able to transition over even within the next few releases.  What they do expect is that you will take the lessons learned here and start making smart design decisions so that when you are ready to move, you can.

Trail 4:  “Sales Rep Trail – Using Lightning Experience”

Where:  https://developer.salesforce.com/trailhead/trail/lex_end_user

Who:  Admins, Developers, and END USERS (yes!  I said END USERS!)

What:  Two modules walk you through concepts such as:

  • What is Salesforce?
  • What is LEX?
  • Working with your Admins
  • Working with Leads and Opportunities in LEX
  • Leveraging Reports & Dashboards (and more) in LEX

When:  This is a great follow-up to the other trails, or a must for your users as part of your rollout strategy – even if you have seasoned veteran users.

Why:  One thing that admins and devs often skip over is the user experience – or how users will be introduced and trained on the system.  We’re so often mired in the details of fields, triggers, and workflow that we completely space that someone will have to advance their Opportunity through the new Sales Path in LEX.  This module is KEY for getting some good ol’ fashioned context.  =)

IN SUMMARY!  (Yes, I’m finally done!)

  • LEX is BIG.  Not like DF keynote/Benioff’s shoes big – like impacting your career big.
  • Trailhead = awesome.  I can’t pick a better word for it.
  • Salesforce has gifted you a fast-track with Trailhead.  Use it.
  • If you want a Winter ’16 LEX org before your sandbox window – you have to do these modules
    • Pre-release org activation is queued and prioritized based on your Trailhead progress
  • Sound off on Twitter!  Mention me (@andyboettcher) when you complete a badge!  I want to hear from all of you!
Advertisements

Passing Variables to Local Application from Salesforce.com

shiftyCreating solutions for a living often puts you in situations where business needs sometimes just don’t align to “how technology normally works”.  One of these situations came up today.

Requirement:  We have information in Salesforce.com that we need to pass to a local (on the Workstation) Access Database and then open it up.

My brain starts screaming “WHAT?!?!  You can’t do that…the browser won’t let you interact with the local file system!”  After some noodling around, my brain reaches WAAAAY back to VB6 days – Microsoft VBScript.  We could use old school ADO and VBScript commands to open up the Access Database, insert records, and then open that same database through a Shell Run command!

Now – only if Salesforce could be manipulated to build the VBScript file and then the user could just execute it!

After a little messing around, here’s the code!  This code generates the VBS, downloads it with a specific name, and the user can just execute it.

**NOTE – It works with one click in IE, but in Chrome and FF you have to execute the file manually from the downloaded location (clicking on the file via the browser throws an error for some reason)

Visualforce Page

<apex:page standardController="Account" extensions="VBScriptGeneratorController" showHeader="false" sidebar="false" contentType="application/vbs#OpenWord.vbs">
<apex:outputText escape="false" value="{!strOutput}" />
</apex:page>

Controller

public VBScriptGeneratorController(ApexPages.StandardController scController) {
 // TODO
 this.soObject = (sObject)scController.getRecord();
Account acct = [SELECT Id, Name FROM Account WHERE Id = :(Id)this.soObject.get('Id')];
strOutput = '';
strOutput+= 'Set conn = CreateObject("ADODB.Connection") \r\n';
 strOutput+= 'conn.Open "Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\\Users\\Andy\\TestADO.accdb;" \r\n';
 strOutput+= 'strSQL = "INSERT INTO tblData (Var1, Var2) VALUES (\'' + acct.Id + '\',\'' + acct.Name +'\')" \r\n';
 strOutput+= 'Set rs = conn.Execute(StrSQL) \r\n';
 strOutput+= 'conn.Close \r\n';
 strOutput+= 'CreateObject("WScript.Shell").Run "C:\\Users\\Andy\\TestADO.accdb" \r\n';
 }

Flow and FinishLocation

pulling-hair-out-321x300Have you tried using Flows with Visualforce pages and tried to set the finishLocation to a dynamic value?  Odds are yes, and odds are even better that you had (or are having) no end of frustrations trying to get it to fire right.

The key to get your dynamic finishLocation to fire right is to factor your PageReference in such a way where as you are progressing through the flow and while the wrapper Visualforce page is rerendering, you can effectively capture and utilize Flow output variables.

To start, let’s embed a flow in a Visualforce page:

<apex:page controller="flowController">
<flow:interview name="DemoFlow" interview="{!flDemo}" finishLocation="{!prFinishLocation}" />
</apex:page>

You’ll note that the “interview” attribute is in use.  That is one of the necessary steps to make this work – you need to link your Flow to the controller.

public class flowController{
// Instanciate the Flow for use by the Controller - linked by VF "interview" attribute
 public Flow.Interview.DemoFlow flDemo {get;set;}

 // Factor your PageReference as a full GET/SET
 public PageReference prFinishLocation {
 get {
 PageReference prRef = new PageReference('/your/page/location?var1= + strOutputVariable);
 prRef.setRedirect(true);
 return prRef;
 }
 set { prFinishLocation = value; }
 }

 // Factor your Flow output variable pull as a full GET / SET
 public String strOutputVariable {
 get {
 String strTemp = '';

 if(flDemo != null) {
 strTemp = string.valueOf(flDemo.getVariableValue('your flow output variable name');
 }

 return strTemp;
 }

 set { strOutputVariable = value; }
 } 

}

You’ll see that both the finishLocation’s PageReference as well as the variable that captures the Flow’s output variable are all in fully broken out GET/SET logic.  Factoring your code in this manner is the trick; as you move through the flow, the Visualforce page re-renders each time the user progresses through a Flow Screen.

**NOTE!  There is also a trick to how your actual Flow is set up.  For instance – if your Flow is creating a Contact and you want to direct the user to that Contact’s standard detail record upon completion of the Flow, you will need to have one last screen at the end to force the Visualforce page re-render so your controller can grab that Contact’s Id.

**ANOTHER NOTE!  You will NOT be able to get 100% test coverage when you link Flow to a controller like this.  Because Flow requires user-interaction, if you try and reference the “flDemo” variable from the example above without first checking to see if it’s null (which it will be in the Unit Test), your test will fail.  There is NO way right now (confirmed by Salesforce) to full test a Flow using this method…don’t pull your hair out trying.

Good luck!  Hit me up in the comments if you have other great Flow hacks or if you have issues getting this method to work.

Thanks for reading!

Visualforce Page Printable View

f02a62983ebcHow many times have you been asked to “can you make that a printable view, ya know, without the top and sidebar?” when you create a Visualforce Page?

If you have, you know the deal.  If not, oh don’t worry, you will before too much longer.

There is a quick and easy way to use the same VF page and APEX Controller that you already have built, using some Page variables, OutputPanels, some minor Javascript, and your “action” page attribute.

Step 1:  Create a Boolean variable and an “init” void method in your Controller

Something to the tune of:

public Boolean bolPrintableView {get;set;}

– and –

public void init() {
 String strPrintableView = ApexPages.currentPage().getParameters().get('print');
 bolPrintableView = (strPrintableView == '1');
}

Step 2:  Modify your VF Page attributes

<apex:page controller="YourPageController" showHeader="{!bolPrintableView}" sidebar="{!bolPrintableView}" action="{!init}">

Step 3:  Add a “Printable View” link to your VF Page

I will usually do this with an OutputPanel with the “rendered” attribute being set to the opposite of my controller’s printable view flag.  Doing this gets rid of the silly link for “Printable View” on your printed page along with any silly users clicking on the button again.

<apex:outputPanel rendered="{!NOT(bolPrintableView)}">
    <a href="/apex/YourVFPage?print=1" target="_blank">Printable View</a>
</apex:outputPanel>

Step 4:  Use a quick Javascript function to immediately call the print dialog on load

Again I’ll usually wrap this in another OutputPanel with the “rendered” attribute being set to what the printable view flag is – we don’t want this firing on the normal view of the page!

<apex:outputPanel rendered="{!bolPrintableView}">
 <script>
  window.print()
 </script>
</apex:outputPanel>

Optional Step 5:  Some pages just look better in Landscape mode – let’s use some CSS so it pops up like that by default.

<style type="text/css" media="print">
 @page { size: landscape; }
</style>

That’s it!  Works like a charm.  Questions?  Hit me below in the comments!

Salesforce and jQuery – now available as a package!

Hello!  Due to a large number of requests, I’ve published my files used in the San Francisco Cloudstock 2012 jQuery presentation to a private link on the AppExchange.

https://sites.secure.force.com/appexchange/listingDetail?listingId=a0N30000008Z4moEAC

Enjoy!

jQuery – Cloudstock 2012 – Part 2

Howdy!  Sorry about the lag in putting up “Part 2” here – why the world doesn’t just go “on pause” for me when I duck out for a few days is beyond me.  =)

In Part 2 – we’re talking jQuery modal forms and dialogs.  I’m not really one to really trick-out a solution – I’m more of an augmenter.  jQueryUI has a wonderful little dialog feature that can give your solution just a little extra pizzazz.

Example 1:  Status Dialog

Salesforce has some great native tools to rerender page sections which can bolt into “apex:actionStatus” objects to give your user some heads-up when you’re processing something.  It totally works and I’ve deployed that exact setup myself on numerous occasions, but then I stumbled on this little gem…

For the Cloudstock presentation, I created a Visualforce page with two buttons at the top – “Refresh / Rerender Native” and “Refresh / Rerender jQuery”.  My controller method that each of these buttons invoked was just to rerender a large apex:outputPanel with some datatables bound to some GETers.  Nothing too complicated, but enough to show jQuery’s pizzazz.

Pressing the “Native” button just called the controller’s page refresh method and rerendered the apex:outputPanel and an apex:pageBlock:

<apex:commandButton id=”cmdRefreshNative” value=”Refresh / Rerender Native” action=”{!doNothing}” rerender=”pbMain, opHelper” />

Again, totally works and leverages what Salesforce gives you right out of the box.

The “jQuery” button augmented the Native process by adding in a jQuery modal div – with a little Javascript “show” and “hide” invoked via an apex:actionStatus object.

j$(document).ready(function(){

j$( “#dialog-modal” ).dialog({
autoOpen: false,
height: 150,
width: 400,
modal: true,
resizable: false,
draggable: false
});
}

// Native Javascript hooks into jQuery .dialog

function statusShow() {
j$( “#dialog-modal” ).dialog( “open” );
}

function statusHide() {
j$( “#dialog-modal” ).dialog( “close” );
}

//// ACTIONSTATUS WITH JAVASCRIPT HOOK ////

<apex:actionStatus id=”asShowInterstitial” onstart=”statusShow();” onstop=”statusHide();” />

//// COMMANDBUTTON WITH STATUS HOOK ////

<apex:commandButton id=”cmdRefreshjQuery” value=”Refresh / Rerender jQuery” action=”{!doNothing}” rerender=”pbMain, opHelper” status=”asShowInterstitial” />

//// HTML DIV WITH IMAGE FROM DOCUMENTS ////

<div id=”dialog-modal” title=”Refreshing Demo Page”>
<p align=”center”>
<img src=”/servlet/servlet.ImageServer?id=015C00000014GUj&oid=00DC0000000Q7ku” border=”0″ />
</p>
</div>

Again, nothing extra fancy, but a nice little professional looking window that also serves to block user input while your screen is refreshing!  =)

Example 2:  Action Confirmation

I think Salesforce is an awesome and highly capable platform, but one of the things that really bugs me is the lack of simple confirmation dialogs – specifically on record deletes.  Yes, I know I can go into the Recycle Bin and recover it, but you know that as the Administrator it’s YOU that will be asked to go find it in there.  Whoo.

Another very simple implementation…

In an HTML table, I added a new column with a “Delete” hyperlink.  That hyperlink invokes some Javascript that presented a confirmation box, and then either allowed or cancelled the user’s action.  Again, very simple but very effective.

j$(document).ready(function(){

j$( “#dialog-confirm” ).dialog({
autoOpen: false,
resizable: false,
height:200,
modal: true,
buttons: {
“Delete Account”: function() {

// Call ActionFunction to Delete Account
afDeleteAccount(strDeleteAccountId);

j$( this ).dialog( “close” );
},
Cancel: function() {
j$( this ).dialog( “close” );
}
}
});
});
}

// Native Javascript hooks into jQuery .dialog

function deleteAcct(strAccountId) {

strDeleteAccountId = strAccountId;

j$( “#dialog-confirm” ).dialog( “open” );

}

//// ACTIONFUNCTION WITH JAVASCRIPT HOOK ////

<apex:actionFunction id=”afDeleteAccount” name=”afDeleteAccount” action=”{!deleteAccount}” rerender=”pbMain, opHelper”>
<apex:param name=”strAccountId” assignTo=”{!strAccountId}” value=”” />
</apex:actionFunction>

//// A HREF INSIDE OF APEX:REPEAT ////

<a href=”#” onClick=”deleteAcct(‘{!a.Id}’);”>Delete</a>

//// HTML DIV WITH CONFIRMATION MESSAGE ////

<div id=”dialog-confirm” title=”Delete this Account?”>
<p>
<span class=”ui-icon ui-icon-alert” style=”float:left; margin:0 7px 20px 0;”></span>
This Account will be deleted if you continue!&nbsp;&nbsp;Are you sure?
</p>
</div>

Just like with the first example – a nice professional-looking delete confirmation dialog box.

 

I’ve got one more of these posts in me – stay tuned for some modal forms in “Part 3”!

Thanks for taking the time to read my blog – check out Part 1 for more in the meantime…

Formatting time in APEX

Great article I stumbled upon.  Odds are if you’re reading this and do Salesforce work – you’ve cursed a blue streak when trying to format time on a VF page.  Nice link – http://paulforce.wordpress.com/2009/08/27/formatting-time-in-apex/