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

AttributeTypeNotes
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:

Installation

Unmanaged Package V1.0

Source Code

View Source

Credits

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;
    error;
 
    @wire(getObjectApiName,{recordId:'$recordId'})  //the first time this fires, recordId will be undefined
    initializeObjectApiName

…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) {
			...do 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'
    })
    picklistValues;
 
    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 https://lightningdesignsystem.com/icons/.

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

Expert Flow Topics – Genetic Flow Patterns & Flow Metaprogramming

Every Flow is completely represented by a single piece of XML metadata, and you can download a Flow xml file, modify it, and redeploy it.

But of course, you don’t. Because it’s dangerous to hand-modify the XML. It’s easy to break things down there in the basement. So we try to provide Flow users with all the tools they’ll ever need right in Flow Builder and/or via public, well-defined APIs.

It is possible, though, to start with a flow (‘templateflow’), modify it using basic text parsing and substitution, and deploy the resulting flow (‘generated flow’).

Suppose that you resolved to start with an existing Flow XML file, and write some Apex code to modify it. You then deploy the modified version of the file up to an org, as a working generated Flow.

You are now programming Flows in Apex. So far so good.

Now suppose that you take that Apex code and turn it into an invocable action that you can insert into a Flow. You then create a Flow that gathers configuration data from a user using standard Flow screens, passes those inputs into your invocable action, and the invocable action then generates a Flow using the inputs the user provided? You now have a Flow Generator. You’re using Flows to generate other Flows. This is a powerful concept known as metaprogramming.

I did some experimentation this year with this, and have published a page of information about it here. There’s a repo you can look at with a working example of flow metaprogramming, used to generate custom Lead Conversion flows.

Consider another scenario: you want to change Flow Stages resources dynamically. Currently you can’t access them with conventional tools like Assignment elements. However, in a flow metadata file, they are simply represented like this:

<stages>
        <name>Stage1</name>
        <isActive>false</isActive>
        <label>Stage1</label>
        <stageOrder>1</stageOrder>
    </stages>
    <stages>
        <name>StageB</name>
        <isActive>false</isActive>
        <label>StageB</label>
        <stageOrder>2</stageOrder>
    </stages>

You could start with a template flow as your baseline, and then use a Flow Generator to read Custom Metadata values, swap in the values for things like the stages name element, and deploy the resulting customized flow.

Good hunting.

New Wiki Page on Flow Stages

We’ve added a new wiki page covering Flow Stages. As is the case with most buildouts of the wiki, this isn’t about a bunch of new content but more of an aggregation of all of the known existing good content on a single focused topic page. As such, everyone should feel encouraged to add good links to wiki pages like this one. The link at the bottom of the page explains how to do it, and it’s totally safe: all edits are put in a review queue so you don’t have to worry you’ll mess anything up.

From ForcePanda: The first Invocable Action that can perform SOQL on any kind of input

Narender builds on his “world’s first” blog post on invocable actions that use the new Spring ’20 generic SObject support with a new post that shows, for the first time, an action that carries out SOQL and can be used declaratively in any object scenario.

The heart of his action is this line:

string query = 'Select '+ queryParams[0].fieldsToQuery + ' FROM ' + queryParams[0].objectApiName + ' LIMIT ' + queryParams[0].numberOfRecords;

As you can see, that’s a SOQL query. Now you’ve always been able to do that with a Flow invocable action, but you always have had to get into the Apex code and specify the exact object you wanted to use. For example, when I posted this tutorial on injecting advanced soql into flows, you can see that my code specifically declared User and Contact variables.

But Narender’s code doesn’t have to do that. And that means that you can take his action and deploy it declaratively against any kind of input.

ForcePanda’s example, powerful though it is, only scratches at the surface of the powerful SOQL actions that will be packaged up into building blocks once Spring ’20 ships. And eventually, we’ll start seeing those actions with friendly configuration UI’s, powered by Custom Property Editors.

A New Datatable Component that supports ALL Custom Objects from Tigerface Systems

Tigerface has posted a free version on AppExchange of their upcoming Datatable solution. The thing that really jumps out at me is that they’ve addressed the core limitation of the existing unpackaged datatable flow screen components: its inability to support more than a modest set of standard object types.

Tigerface appears to be solving this via metaprogramming: they actually generate the component on-demand to fit a particular specified object type. That’s a clever approach.

Comment thread here: https://success.salesforce.com/0D53A00004inprz