Originally published 2019-08-14 on blog.tlarsendataguy.com, and shared here with permission.
Who else was excited when the technical preview for Flutter for web was announced? I know I was! Flutter is by far my favorite UI framework. But until the announcement it was limited to building cross-platform mobile apps (which, come one, is already pretty great). With it’s newfound ability to target web, a beautiful bridge was created between my interests. Alteryx, my favorite data analytics platform, provides SDKs for creating custom tools. The UIs for those tools are built with web technologies. Now that Flutter is a web technology, we can build the UIs in Flutter.
There is a bit of glue that is required for Flutter to interact with the configuration persistance layer of Alteryx’s HTML SDK. So rather than demo a complete tool here, I will focus on one way to build the glue. Before we start, let’s set a baseline of expectations:
- I use JetBrains’ IntelliJ IDEA when I code Flutter. It’s the best; you can’t go wrong with a JetBrains IDE.
- I want to code, build, and debug the UI exclusively using my IDE’s toolset. I don’t want to use Alteryx during any point of the development process because the context shift slows things down.
- The UI should behave exactly the same in a browser as it does in Alteryx. ‘Releasing to production’ should mean copying HTML and javascript files from the build directory to the custom tool folder, and nothing more.
- I want to spend as little time in javascript as possible.
- The glue code should be minimal and simple to use.
- I assume you have some knowledge of Alteryx’s HTML SDK.
Sound good? Then let’s get started…
Understanding Presistence in the Alteryx HTML SDK
There are three UI patterns Alteryx suggests for retrieving and persisting the tool’s XML configuration.
- Data items with widgets
- Provide SetConfiguration() and GetConfiguration() functions to the window.Alteryx.Gui object. These functions are completely responsible for parsing and saving the tool’s configuration.
- Provide a BeforeLoad() function to the window.Alteryx.Gui object which initializes DataItems. These DataItems handle the persistence and parsing for you.
Option 1 does not work for us because it uses some other framework (React, I think) for building the widgets. After trying the other options, I prefer option 3 for most cases, for the following reasons:
- It is a bit cleaner implementing 1 function rather than 2.
- It allows us to take advantage of the HTML SDK’s encryption facilities for persisting passwords and other sensitive strings.
Building the Javascript Glue
A fresh Flutter for web project has the following structure:

To start building the glue, we will make adjustments to web/index.html. The file we start with looks like this:
Let’s begin by adding a reference to Alteryx’s includes.html file and creating an empty script tag at the bottom for our Javascript glue code. Notice how we only add the Alteryx inclusions if window.Alteryx exists. When we debug this from the IDE it will not exist, so the if statement is required if we want to debug outside Alteryx.
For our script tag at the bottom, let’s start by defining the BeforeLoad function according to Alteryx’s documentation. As an example, I want to build a Flutter UI for my Hype tool, which publishes hyper files to Tableau server. I need to persist the following values in the tool’s configuration:
- Server: The address of my Tableau Server instance
- Username and Password: My credentials for Tableau Server
- Site: The site on Tableau Server where I want the hyper files published
- Project: The project where the hyper files will be published
- UploadFile: The field from the incoming data which contains the path to the hyper files I want to publish.
Here is a visual of what the tool, in its current form, looks like:

A BeforeLoad function that creates the needed DataItems looks like this:
This works perfectly in Alteryx, but we have a problem. Remember that when we debug outside Alteryx, window.Alteryx will not exist. This code requires window.Alteryx to exist and so we will only be able to debug in Alteryx. My solution to this problem is to mock window.Alteryx. To do that, we need to understand its structure, and I just so happen to have this high-level overview:

All of the objects in the diagram have additional properties and methods, but the ones I provided are all we need to mock the behaviors we will interact with. Let’s see what the mock looks like, and then I will explain it a bit:
We start by defining a small constructor method that implements the DataItem functions getValue() and setValue(value). The next section creates the Alteryx, Gui, and Manager objects. Manager contains a dictionary of MockDataItem, which we use to look up by name in the getDataItem(name) function. Each configuration item in the final tool needs to be mocked in the dictionary. The last part of the code defines a mock for the getIncomingFields() function. In it, I return a list of Field objects, one for each data type Alteryx supports. This allows me to make sure my Gui properly handles any incoming field type that Alteryx may provide.
When we put everything together, this is the totality of index.html. From this point forward, I will not have to touch javascript or HTML again:
Building the Dart Glue
Now that the Javascript glue is finished, we need to create a bit of glue in Dart. Dart has a package (dart:js) that handles interop between Dart and Javascript. In the lib folder, I create a file called configurer.dart that will contain all of the needed interop code. I want my interaction with this layer to be as simple as possible. For example, if I want to retrieve the Server configuration value, I want to call Server.Get() in my Dart code. If I want to set the Server value, then I want to call Server.Set(myServer). The code below creates the const variables which do exactly this:
The jsContextBridge class contains all of the Get and Set logic, so it becomes very easy to create my const variables which will interact with the configuration persistence layer of the HTML SDK. As you can see, the dart:js package makes it easy to interact with Javascript entities. Objects are simply dictionaries, and methods can be called via the callMethod() function. The trick is to make sure the object hierarchy defined in configurer.dart matches the actual window.Alteryx object. But it’s a one-time effort; I can reuse this code for all future tools.
The last piece of the Dart glue involves retrieving the incoming field list. The code looks like this:
We start by defining a simple data structure to hold Alteryx’s field information. The getIncomingFields() method returns a list of that structure populated from the Javascript getIncomingFields() method. I also created an optional parameter that the method uses to filter the incoming fields list. For example, if I only wanted text fields, I could pass [‘String’, ‘WString’, ‘V_String’, ‘V_WString’] to the filterTypes parameter and it would exclude any non-text field from the returned list.
We are almost done, but there is one additional, small piece of configurer.dart that I found was needed. DataItems defined as passwords were not loading correctly with this setup. It seemed to come down to timing; when I inspected the DataItems in Alteryx, they were loaded correctly. But they were not loaded when my Flutter code was asking for them. So I created a small asynchronous loop in configurer.dart that would run until window.Alteryx.Gui.Manager was not null. It doesn’t feel 100% like the correct solution, but so far it has not failed, either.
To use the loop, I simply call it from the initState() function of my main homepage State class. Something like this:
And with that, the Dart glue is finished. The completed configurer.dart file looks like this:
Now, anywhere I want my Flutter code to interact with the tool’s XML configuration, I simply import configurer.dart and call Get() or Set() on the pre-defined constant. This process integrates well both in the setState() method and in the BLoC pattern used with more complex designs. Best of all, from this point forward I can focus on creating and debugging my UI without thinking about the Javascript interop or worrying that it will not work when I run it with Alteryx. To wrap everything up, I leave you with a video of a Flutter UI I threw together for my Hype tool. You can see the UI working in exactly the same manner in both Alteryx and my development environment (Chrome):


Responses