Datatype Agnostic Table Reusable Element - Reuse your clickable table with any datatype

Reusable Element Properties have been an absolute game-changer, and I would like to share a RE that I’ve found crazy useful.

The title of this topic is quite a handful, but essentially it means that with a single RE, you will be able to add a table on your app containing any dataType! Not only will you be able to display data, but also trigger page-level workflows that have the clicked-on dataThing available to them!
The RE will also be able to dynamically display as many rows and columns as you ask it to, change what data is being displayed based on custom states, and also change the datatype being displayed on the fly! You can drastically reduce the number of elements on the page by using a single table RE for many datatypes, as well as making the app generally more maintainable, as you only have one table to change/update.

Demo

Forgive the bad UI, I created a test app just to demo the functionality.

High-level summary of how it works

In order for the RE to be datatype agnostic, you obviously cannot reference field values in dynamic expressions inside the RE. Instead, we will be inputting the static text to be displayed into the RE properties. And in order to tie the dataThing back to the static data, we will also provide the unique IDs of the dataThings.

Setting up Reusable Element properties


These are the core properties which are needed to get the RE to work. On top of these, you can have as many design properties as you’d like in order to dynamically change the design/layout/arrangement of the Table. You really can get creative.

Headers - List of Texts
Simple comma separated list of table headers

Formatted Values - Single Text
This is the text that will contain all the static values that will be displayed in the Table. This is generally a result of a search or a list field +:format as text. Inside the format as text you will list out all the fields you want to show, as well as the unique ID of the dataThing, and any optional datasources such as image urls. Each row of the table will be delimited by the outer splitter string (in my case ‘||’) while cells in each row will be delimited by the inner splitter string (in my case ‘~~’) . Be sure to use a delimiter that won’t be present in the values you are feeding into the RE, do not use a comma!. To be safe, I generally add find and replace at the end of each value to find and remove the splitters.

Example ‘Formatted Values’:
Alice ~~ Smith ~~ Alpha ~~ 1234567890123x123456789012345678 || Bob ~~ Smith ~~ Bravo ~~ 1234567890123x123456789012345678 || Charlie …etc

Inner & Outer splitters - You can change the inner&outer splitters, but this is generally not needed.

Type - Text
The name of the datatype being fed to the RE. This is needed so the correct workflows are triggered on click.

RE Design

You will essentially need 3 Repeating Groups:

One for the Header Titles -
Datasource= Headers

One for the Table Rows -
Datasource = RE's Formatted Text:split by Outer Splitter

And a nested RG for the Table Cells
Datasource = Current Cell's Text: split by Inner Splitter: items until #Headers count (this is so the table won’t show the unique ids and optional datasources inputted into the RE, like images, options etc)
This is the RG that will contain a text element that will simply display ‘Current cell’s text’.

Click Event and dataEntry reconciliation

Once a table’s row is clicked, the RE somehow needs to send the underlying dataEntry back to the page-level. To do this we’ll use the uniqueID and the ‘Type’ RE property
You could set up searches for each datatype, however I use the following plugin:
String to thing / things Plugin | Bubble
The plugin lets you define the datatype of the thing and the unique ID, and it returns the Bubble thing.
I think its quicker than running a search, but i have not ran a methodical test. I mainly use it because it allows the table to be sortable because it can also publish a list rather than a single thing, I wont talk about that in this post, but the process is analogous to the single-entry case.

Here is the basic flow to retrieve the dataEntry:

  1. When the line item is clicked, set a text custom state to the unique ID of the row. Use regex to extract it from the row’s text (RegexPattern=\d{13}x\d{18})

  1. Set your StringtToThing’s dataTypes but leave the Strings blank, otherwise it will cause issues Using conditionals, set the strings and activate the event triggers for the correct datatypes. If you set Type 1 to be User, make sure that the ‘user’ conditional sets String 1 and Event 1 .

  1. Add as many custom states to the Reusable Element as Datatypes you want to use the table with. In my example, I am using Users and Tasks, so i added a ‘selectedUser’ custom state of type User, and a ‘selectedTask’ custom state of type Task.

  2. Add the ‘StringToThing value is active’ workflow, which basically triggers everytime its value is changed. Set the custom states created in Step 3 to the String to Thing’s value.

  3. And finally, on the page level add a ‘Do when condition is true’ workflow that runs every time. It will check whether the Table’s custom state is not empty. Generally each RE you place on the page will be dealing with a single dataType, so you know which custom state to check on the conditional; if its a user table, you will check whether selectedUser is not empty.

You can then reference the clicked entry by using RE's selectedData.

Adding a new supported dataType

To add a new datatype all you need to do is set the StringToThing’s parameters& activate the corresponding workflow. Then and add a new ‘selectedThing’ custom state on the RE.
Thats it ! :slight_smile:

Configuring pagination

Pagination is not handled by the RE, it will be handled on the page. Simply change the list of dataEntries being fed into ‘Formatted Values’ by using custom states.

Examples of where this might help

This RE will be useful if you are building an app that needs many simple tables displaying different datatypes. If you want to change the design/format of the table you can do so in a single place, and you wont have to build out every single table manually.
Example: You are creating content management/data visualisation dashboards for super-admins who want to have access to their app’s data so they can edit it/delete it. This might be dozens of tables, now handled by 1 RE.

This method is great to tackle multiple dataTypes at once, however if one particular dataType needs a more complex Table that will be displayed in multiple parts of your app, i would recommend checking out @georgecollier 's guide on making a dataType specific RE :

I really cannot overstate how much time these REs can save.

Happy Bubblin

3 Likes

IDK why but seeing this makes me want to use the Table element more haha. I have used this method in the past, but I am starting to use the Table element a lot more. Just recently I have learned how to setup very good conditionals to make really nice tables.

That was from my first-time using tables. Took me much less time it would take to build the RE method.

Reason being is the way you’re filtering your ID’s and key values. It’s just a bit much (not trying to call you out or anything).

For complex compatibility, I would just use my element scoper tool from my toolkit to add an easy conditional or trigger from within each cell if needed.

The difference is that you wont get a single table element to work with multiple datatypes.
I have not used the table element much because it’s not flexible enough. You have to statically define the ‘Type of Content’ , have to statically define the number of columns. You can’t even dynamically reference Current Column’s Index…

For static, one-off tables like the pricing/features table you linked, it works ok and you can make it look pretty, but as soon as you want to make a general purpose dynamic table that works for any dataType it falls way short. Maybe i’m wrong, and i’m very happy that you find the Table Element useful, its sad to see it get disregarded so much.
I admit that i do not like working with pre-built templates as soon as i hit limitations, and the table seems to have many.

I know my write up seems long (and to be fair the process can be simplified), but it honestly takes very little time to set up the RE once you know what you’re doing, and even less to copy/paste it from another app :grin: And most importantly it will then work on all Datatypes, no need to rebuild a new table.

z8LwHYfJT1

I’m able to reference the cells, and I don’t have to statically assign the columns:
81hLB1O802

Also with my Scoper tool I can reference anything or “any thing” from any cell

I’m able to make any field dynamic or triggerable as well with the scoper (to answer comment about dynamic things)

To add: Yes, bubble should add a bit more functionality in terms of referencing said cells, but it’s still in “beta” so I’ll give them that. none-the-less, it has definitely transformed from the get-go from where it was at the start.

I should REALLY make a guide on the scoper for others so they can see how much more dynamic they can make their applications :stuck_out_tongue:

Well its great that we’re both happy with our methods :grin:

I had seen your toolkit and was meaning to check it out but never got around to it. A guide/demo would definitely be helpful. Looking forward to it !

I’ve come across this post but the solution uses a repeating group instead of a table element type.

I’m aiming for the same functionality, but with a table element. I want to create one reusable element for all the tables in my app, and it should be able to accept and display any data type.

@GH5T, I’m having trouble understanding how you’re doing this. Is there a tutorial available?

So, is this doable, or are there limitations that make it impossible (and the only way right now is with repeating groups) @nico.dicagno?

You can presumably apply this technique with the table element. I haven’t tried it within a reusable element, but here are some illustrative screenshots from a table element that I use as a template to copy and customize throughout an app. Replace the hardcoded data source and delimiter characters with reusable element properties and you should be be able to confirm feasibility pretty quickly.

Table element tree

Data source

Row delimiter (new line)

Column delimiter (comma)

I would recommend sticking to the Repeating Group element. I cannot comment on whether this method will work with the Table element because I only use Repeating Groups.

Any reason why you’d prefer to use the Table element over RG’s?

Careful with using commas as delimiters. The text content of the table may very well contain commas, and this would completely break how the table parses the data. Newlines are a bit safer, but I have seen new line characters in tables before.
I personally use ‘|||’ for column delimiters and ‘- - -’ for row delimiters.

:100:
My base table element that I used to illustrate the point only uses comma-delimited values as a placeholder. I always copy and customize this base element to custom data types. When I truly need to split highly variable text, I rely on multi-character unique strings like you suggest or else regex.

Very interesting. I’ve done something similar in the past with text but the plugin really makes it seem easier to handle in the long run. Any thoughts on sorting and filtering? Say you want the user to click a column at the top to sort AZ or ZA for User names
@nico.dicagno

Hey @nico.dicagno and @davidb, thanks for your answers. I’ll check them out when I get a chance.

@nico.dicagno, I don’t have any specific reason to prefer the table element over the repeating groups. It just seems more suited for creating tables. But, I’ll play around and see which one is easier to handle and offers more flexibility.

Also, I’ll make sure to check out George Collier’s tutorial and keep you guys posted on what I achieve. Thanks again! :blush: