Now display Visual Card Pickers in dual columns in the quickChoiceFSC screen component

I have added a new parameter to the quickChoiceFSC component. You can now choose to display visual card pickers in a single column or side by side in dual columns.

Single Column

Dual Columns

Contributing to the Code in Flow Projects

One of the coolest things I’m seeing as UnofficialSF grows is admin turning into beginner developers and beginner developers turning into better and better developers.

A key milestone on this pathway is creating your first pull request. Pull Requests are named terribly, for technical reasons. They should be called Code Submissions. They represent someone saying “I’ve improved at least one code file, and here are the improvements”.

For the Flowhana to achieve its full potential, we need more members to break through and get comfortable creating pull requests.

Here’s the basic trail….

Before Starting

  1. First of all, don’t worry that you’ll mess things up. Pull Requests sit atop a framework that has been developing over the last 20 years called git, and it ensures that no matter what happens, any change you make to the code can always be undone.
  2. Secondly, don’t worry that your code isn’t good enough. Every developer starts out as a beginner. This will be a very friendly environment and you’ll learn a ton.

Learning the Basics

  1. Go to the repo (repository of code) up on Github that most interests you and look around. Get a feel for the features and how it’s structured. Get a github account if you don’t already have one.

2) Go through this tutorial, which provides a quick, simple introduction to the three core concepts: repos, branches, and pull requests.

3) Make an initial decision about what tools you’re going to use on your computer to manage your local copies of various code repositories. The big choice is whether you want to go with the command line or use a visual tool, and, if you want to use a visual tool, whether you want to us the VSCode tool that Salesforce recommends for development or a more git-centric tool like Github for Desktop. My recommendation is to use the command line if you’re already comfortable with managing things via the command line, but otherwise try Github for Desktop. VSCode is great for development but not quite as easy to get started with.

4) Next, explore the idea of remote and local repos. Github maintains the current master copy of several UnofficialSF repos. When you want to work with one of them, you work with it on your local computer (from where you’ll do a bunch of deploys to Salesforce orgs). The process of creating a copy on your own computer so you can work with it is called cloning.

5) Next, study up on Branches. Branches are the heart of the collaborative model. Each branch is essentially a pointer to particular series of code changes. When you create a new branch, it ‘allows’ you to start changing an existing code line. An intersection is created and there are subsequently two different code lines. The rest of the community continues down the original branch while you get to make changes on your own code line. Ultimately, a Pull Request represents a request to merge your customizations into some existing code line that you originally branched off of. The number one thing that will make your initial experiences with code collaboration work better is to get a good understanding of branches and always know what branch you currently are on. To get a really good grounding of Branches, I recommend working through the git book up through chapter 3.5. Even if you’re not using the command line, the diagrams alone are worth checking this out. It’s really useful to grok the idea that even though we metaphorically talk about codelines and tree-like branches, a ‘Branch’ is really just a pointer to a specific commit.

At this point, you’re ready to start contributing code to flow projects.

A quick note on forking. Forking a repo into your github account allows you to make changes without getting any access to the original repo. However, if you are interested in making contributions, don’t hesitate to ask for contributor rights on projects. When you’re a contributor, you still create branches and pull requests, but it’s a little simpler because you’re working with the main repo and not a forked copy. I welcome contributors to all of my repos.

So now we can discuss the core workflow you’ll use:

  1. identify a needed change in an existing project/repo
  2. if you don’t already have a local copy of the repo from a previous clone or fork, do a clone or fork.
  3. deploy your local copy to a dev org where you can work with it (see “Deployment, Orgs and SFDX” below)
  4. Create a working branch, make changes to the code and flows, and deploy the changes to your dev org. Frequently commit and check your code changes into your local repo, and periodically push your local repo to your github repo so you’ve got a safe copy up there. Iterate until you’re done.
  5. if your work includes apex code, add one or more test methods to test your work
  6. when you’re done, make sure all of your changes are pushed up to the github master repository on your working branch.
  7. create a pull request, indicating that you’re suggesting that any changes between your working branch and the current master branch be resolved by merging in your changes.
  8. wait for a review. someone like me will look at the code and possibly give you feedback.
  9. Ultimately, when the code is ready, someone with merge rights will merge your changes into the master branch of the master repository.

Deployment, Orgs and SFDX

We highly recommend using SFDX as part of your development process. It’s important to keep SFDX and all of the above stuff distinct, though. The above stuff is about code management and git, and sfdx is about salesforce org and metadata management. They work together really well, but you have to take it one step at a time.

If you’re like me, when you get to step 4 and deployment, you’ll use sfdx to create temporary dev orgs called scratch orgs where you can deploy and test in isolation. YOu’ll take advantage of super useful tracking built into sfdx that allows you push code up from your local machine and also make declarative changes (like building a flow on the org in Flow Builder) and then pull the metadata down into your local machine’s repo, so that all the changes are always together.

It’s also possible to do deployments the old way with packages and workbench.

To learn more about sfdx, start here.


There’s a lot here. Don’t rush it. I would recommend looking at this as a sort-of 1 year course of learning. When you get frustrated, take a break. search stack exchange when you run into problems. Enjoy the journey.

Rich Text Input – Flow Screen Component

Updated 1/20. Cleanup. converted to LWC.

This is an extremely simple port of the standard inputRichText control to work as a Flow Screen Component.

screen shot 2018-01-24 at 9 01 56 pm

Install this Component Into Your Org

Install this Component.

How It Works

This component exposes a single attribute called “value”. It can be used both as an input parameter to set the starting values and as an output parameter to pass out the selected time.

You can display the rich text output of these components in Flows, using either the standard Display Text Field or the new formattedRichText Flow Screen Component

Note, though, that the standard Flow Display Text field is capable of displaying some of the rich text effects, but not all:

screen shot 2018-01-24 at 9 05 12 pm

Variable Handling Notes

When added to a screen, this screen component currently has Manually Specify Variables (Advanced) turned on. to get the value out of it, you’ll want to map the value to a variable of type Text. However, you can also turn off manual specification of variables and use automation output handling. Some of the tradeoffs are discussed here.


Unmanaged 1.51


View Source

Post Rich Chatter – Process Action

This action posts to chatter in a way similar to the built-in Post to Chatter action. It supports the subset of rich text that Chatter supports. You can pass it a Text Template with rich text formatting, or simply provide it with some HTML text.

This is an invocable action, also known as a process action, and runs in Flow Builder, Process Builder, Bot Builder, and Strategy Builder.

Handling is as follows:

Bold, Underline, List (Bullets and Numbers), Italics get displayed in Chatter without any modification.

URLs and Images get displayed in Chatter but are modified. Both are rendered in Chatter as clickable links (there’s probably a way to improve this action’s Apex to display these more effectively inline, if there are any Apex Chatter experts out there reading this).

Formatting Support

The following rich text formatting elements available in Flow are not supported in Chatter, so they get stripped out:

  • Indenting
  • Font Size
  • Font Family
  • Font Color

bodyStringCan be HTML, which also means a Flow Text Template with formatting. See documentation for information on how various formatting is affected.
targetIdStringCan be the id of a User or Group, the string ‘me’ (which represents the current user) or the name of a user or group. The action will first try and match this value to a known name and then assume it’s an Id.
communityIdStringIf null, the user’s current community is used.

Support for @Mentions

This action will attempt to convert any recordId it sees in the Body that is in braces to an @mention. So if you put this in a Flow Text Template:

Hey! {{!curGroup}}

and curGroup is a flow variable of type Text that contains a recordId, you’ll get an @mention in the Chatter:


Unmanaged Package V1.0

Source Code

View Source


This action makes extensive use of ConnectionApiHelper.

Wire Service Considerations when using LWC and Flow

Wire services fire initially before any flow data is loaded into an lwc’s public properties. If you’re using flow inputs to drive those wire services, like this:

import getObjectApiName from '@salesforce/apex/AddChildObjectToConfigController.getObjectApiName';
export default class AddChildObject extends LightningElement {
    @api recordId;
    @api objectApiName;
    @wire(getObjectApiName,{recordId:'$recordId'})  //the first time this fires, recordId will be undefined

…keep in mind that your function will have to deal with that initial result that comes back, which will often be something like undefined. What you want to watch out for is throwing an error message instead of just letting that first firing quietly sink. For example, this code will always stop processing with an error message:

        @wire(getPicklistValues, {
		recordTypeId: "$recordTypeId",
		fieldApiName: "$objectAndFieldName"
		//fieldApiName: "$calculatedObjectAndFieldName"
	picklistValues({ error, data }) {
		if (data) { useful stuff
		} else if (error) {
			throw new Error("something went wrong with the request to get picklist Values!");

In the normal course of action, wire services like the one above will fire a second time once the flow values have arrived.

It can be useful to make use of getters to provide finer grain control. Here’s an example:

import { LightningElement, wire, api } from 'lwc';
import { getPicklistValues } from 'lightning/uiObjectInfoApi';
export default class Example extends LightningElement {
    @api rtId;
    @api objectApiName; // string eg 'Account'
    @api fieldApiName; // string eg 'Type' 
    @wire(getPicklistValues, {
        recordTypeId: '$rtId',
        fieldApiName: '$calculatedFieldApiName'
    get calculatedFieldApiName() {
        if (isString(this.objectApiName) && isString(this.fieldApiName)) {
            return `${this.objectApiName}.${this.fieldApiName}`;
        return undefined;
function isString(value) {
    return typeof value === 'string';

In the example above, the code ultimately has to concatenate two strings into a single combined string and provide that to the getPicklistValues wire service. When the wire service first fires though, and both of those initial strings are undefined, the concatenation attempt will fail spectacularly. The getter above ensures that if the data is not present, a simple undefined will be passed to the wire service.

More information on adding LWC’s to Flow Screens

Packaging Invocable Actions

Author Credit: Eric Smith assisted in the development of this material

Because invocable actions make great building blocks, there’s an increased risk that you’ll have a collision if you’re using unmanaged packages, so managed packages are generally recommended (and unless you have IP you want to keep confidential, we also recommend you simultaneously make the source code public and post about it).

It’s easy to create managed packages. If you’re not familiar with it, the basic process is:

  1. create a new free developer edition org to serve as the host for your package. Don’t use this org for anything else and give it a My Domain name that makes its purpose clear, like ‘managedFindRecordsHost’.
  2. deploy your project to this org.
  3. create an unmanaged package on this org and test it out. (When orgs are created, they create unmanaged packages. Once you convert the org to be a builder of a managed package version of your project, you can’t create unmanaged versions of that project on that org any more. )
  4. decide on a namespace. This will be highly visible to everyone who installs and uses your action. It’s an opportunity for branding, but try not to make it too long or cryptic, and keep in mind that every project you package will get its own namespace and they all have to be unique (so if you give the namespace ‘alexprojects’ to your very first package org, you won’t be able to use that for your second project. Therefore alexprojects_quick or alexprojects_1 might be a better bet)
  5. In Package Manager, convert the org to be a managed package host of your project, using the unmanaged project you built and your chosen namespace.
  6. Test out the resulting package by installing it on another org. I often spin up more free developer edition orgs to create clean environments for verification. Make sure that your actions can be seen in Flow Builder (see Troubleshooting below)

Troubleshooting Action Packaging

My package installs fine, but I don’t see my action in Flow Builder!

First, verify that the action does show up in Developer Console. If it doesn’t something went wrong with deployment and packaging. If the action is visible in Developer Console but not in Flow Builder, the problem probably lies in the interface between Apex and Flow.

One reason this might happen is that you didn’t use global for your class and methods. Only global invocable methods appear in Flow Builder and Process Builder in the subscriber org. More info.

You might be using a variable type that is legal in Apex but not in Flow, like Map or Set. Generally, this will be caught earlier in the process. Try simplifying your inputs and outputs until your class does show up in Flow. If your package is unmanaged, you can make the changes directly in Developer Console, an example of why Step 3 above recommends starting with an unmanaged package.

Note that you also have to use global on your invocableVariable input and output variables if you want them to show up. That’s discussed here.

More information on Invocable Actions

New Options available for the Quick Choice Flow Screen Component

In my org, we are working on a new way for our service agents to select Case resolution options. To improve data consistency and accuracy we are adding descriptions to our Case resolution options. The initial thought was to create and display a datatable with a column for the resolution and another for the description. I wanted a better way to visaully display these two items. I found something I liked in the Lightning Design System called Visual Picker. At the same time I saw the new Quick Choice Flow Screen Component which offered an easy way to present and select choices using Radio Buttons or a Picklist. I decided to enhance the Quick Choice component to also support some Visual Picker options.

I added a new Input Mode called “Visual Text Box” and used the existing collection parameters to pass in the choice labels and choice descriptions.

To extend this even further I added new options Include Icons in Text Box? and Icon Size and created a third collection parameter (Choice Icons) for the icon names. See the complete icon selection at

Click here for a complete description of what this great new component can do.

New Collection Processor Actions: 1) Count Fields and Records, and 2) Extract Fields from Records

PREVIEW Requires Spring ’20 Org

The first upgrade to the Collection Processor package is available.

Count Records And Fields takes a collection of records and returns a count. Optionally also takes a field name and a field value, and then also counts the number of records that have that particular value for that particular field. Returns both the number of matches and the total number of records.

Extract Fields from Records takes a collection and a field name, and returns a list of strings containing the values of those fields for the records. For example, if you pass in a list of Accounts and a fieldName of “Name”, you’ll get back a list of Account names. You can do this twice (once for names and once for ids) and then pass those two collections in to a Quick Choice picklist or radio button group

Flow Form Factor Helper Lightning Web Component

Ever needed to have access to the form factor of the client in which your flow is executing? Today that’s not (yet) natively possible. But with a simple Lightning web component we can determine the form factor. And as bonus, have ability to make the flow to progress automatically.

Use-case? Think of a Flow invoked by a Lightning action. The flow works fine on the desktop. But that same flow might not be fit-for-purpose for a mobile device. But there is no straight-forward way to hide the action (until we get Lightning Dynamic Forms later in ’20). You want to simply inform the user, the flow is not designed to run on a small form factor. Just Install the package or visit the Github repo. Drop the Flow Form Factor Helper Lwc component in a screen element. Tell the component whether to auto-navigate forward (default = false) and save the determined form factor in a Flow variable. There’s no more to it!

Install in a sandbox
Github repo
Blog post