Traditionally, Flow likes to work with structured data. That’s stuff like Case and Account. Flow also likes simple primitives like Text and Number. Additionally, when the data type is know, you can use Apex Types.
Starting in 2019, it became possible to specify types at ‘Design Time’, in the Flow Builder. This is the experience you get when you use a component or action that supports generic inputs. For example, the Upsert action found in Collection Actions extension lets you upsert any object you want, so long as you specify the specific object at Design Time. In the example below, the person building the flow has ‘locked in’ Account as the kind of object that will be upserted:
In our Quick Query use case, we have a new situation. There, an interplay takes place when the flow is running, between the Quick Query component with its filter buttons and Export to CSV capability, and the Datatable component. The user can specify the object they want to query for by selecting it in Quick Query:
So here, we have the object being selected not at Coding-Time (where the developer might specify that it’s an Account, and it could never be changed by the admin), and also not at Design-Time (where the admin might specify that it’s an account, but it would then be locked in and would not be changeable by the user), but at Run-Time, by the user.
This is cool and powerful, but it creates some challenges. Flow component inputs like Datatable have to be locked in at design-time. Flow just doesn’t have a way to say ‘this input can be changed on the fly by the user’, and there’s nothing like that on the roadmap.
To work around this, the latest version of the components used in the Quick Query demonstration (Quick Query and Datatable) and the Upsert Records action that this flow uses all support a new unofficial mechanism called Record Datastrings. A Record Datastring is simply a JSON representation of a Salesforce record.
Let’s look at an example. Quick Query will perform a query of whatever object the user selects, and output it in several formats. Meanwhile Datatable now has the ability to accept data in Record Datastring format as well as the Sobject Collection that it already supported. And the new Quick Query has the ability to output Record Datastrings. Here’s what the inputs look like in Datatable’s property editor:
The most important thing to notice is that Input data is Serialized is checked. When that’s checked, all of the normal Datatable inputs are ignored, and only the two inputs immediately below the checkbox are used. Notice how the ‘recordDataStringAll’ output from Quick Query is mapped to the inputs of Datatable. This is only possible because the org has been enabled for Reactive Screens pilot. Note that we separately provide the objectName.
In our QuickQuery example, the wiring also goes the other way. We wanted to enable an Export to CSV button as shown above and we wanted that button to be able to work on only the selected rows in the datatable. That means that every time the user changes their selections in the datatable, we need to let the Quick Query component know. We do that with the same wiring, but this time the wiring goes from outputs in Datatable component to inputs in Quick Query:
Datatable provides elegant inline editing, and we wanted to make it easy to apply all changes as easily as possible. To accomplish that, we enhanced the Upsert Records action to also support the recordDataString that Datatable outputs. Here’s what our sample flow looks like:
Note that this flow is installed with the Quick Query package. The inputs of Upsert looks like this:
Here you can see that we’re passing in only the edited rows. Note that we still needed, at design-time to ‘lock’ an object into Upsert Records. We selected Account but if we’re using recordDataStrings, that value is ignored.
The addition of recordDataString support to components and classes adds complexity to the configuration process. so it should only be done if there’s a real opportunity to let users switch between objects at runtime.