How to add color to tags based on values in row

Hi! I am adding tags to my retool and I would like each value of my tags to be mapped to colors based on another column in the row:

Using "self" just seems to always default to the "CFF6F7" value, so I can tell it's not working as intended. I have tried several methods, including

  • {{ self.patient_import_task_status === "SUCCESS" ? "AEE3A4" : self.patient_import_task_status === "FAILED" ? "FAB5B5" : "CFF6F7" }}

  • {{ currentSourceRow.patient_import_task_status === "SUCCESS" ? "AEE3A4" : currentSourceRow.patient_import_task_status === "FAILED" ? "FAB5B5" : "CFF6F7" }}

None of these seem to work.

Is this something that is currently possible, and am I missing something here?

Hi @Anish_Srinivasan, Welcome to the Retool community :tada:

You can implement it as follows:

1 Like

Ah! Thanks for the quick reply here :slight_smile: I think the issue is that this doesn't work when I am working with tags:

In this case, I am actually editing the color for a specific option for tags. This gives me the following error:

ReferenceError: currentSourceRow is not defined

I have been doing exactly this recently!

Here are some tips that I have discovered along the way:

currentSourceRow is a property of the table, not a free reference to use in the options mapping.

This is how I have my Options setup for my column:

My datasource is a mapping of tags to colors in my database, so any app that needs the list can use it.

For me, there was a logical disconnect, which confused me. item in the above screenshot, does not reference the table values, or row, it is a reference to the mapping you are setting up. Defining these mappings will have the table automatically apply the right tag, based on the Value.

In my mapping, the Value is the text of the status, the item.label. Rendering the table, when a cell has that same value, Retool swaps for the mapped tag.

It is not that obvious, but they state it here:
image
that the {{ item }} we see there is the source column's cell value. But when you are in the options mapping, "Below, item will reference..." is the the value of the option you are trying to map.

One more side thing:
Instead of doing a long nested ternary, try utilizing some lodash

For example, you can store in a variable, a simple map like this:

{
  "SUCCESS": "green",
  "ERROR": "red",
  "MANY_MORE": "pink"
}

and then with the help of _.get (docs) you can:
{{ _.get(ColorMapVariable.value, something.with.prop) }}


Another method I use is _.thru (docs) which lets you reference a.big.nested.thing passed into a function to use.

Example:

{{
  currentSourceRow.patient_import_task_status === "SUCCESS" 
  ? "AEE34A" 
  : currentSourceRow.patient_import_task_status === "FAILED" 
    ? "FAB5B5" 
    : "CFF6F7"
}} 

could utilize _.thru() like this

{{
  _.thru(currentSourceRow.patient_import_task_status, (sts) => {
    return sts === "SUCCESS"
      ? "AEE34A"
      : sts === "FAILED"
        ? "FAB5B5"
        : "CFF6F7"
  })
}} 

One More Method

I have used this pattern elsewhere, but you can emulate pattern matching with lodash's _.cond() (docs) method.

{{
  _.cond([
    [_.matches("SUCCESS"), () => "AEE34A"],
    [_.matches("FAILED"), () => "FAB5B5"],
    [_.stubTrue, () => "CFF6F7"] // Default case (if no match)
  ])(currentSourceRow.patient_import_task_status)
}}
2 Likes

@khill-fbmc this is AMAZING! One more nuance here is that I am passing in an array into tags. I would want each "option" mapped according to color based on another column. So imagine, I have three "options", "P", "E", and "A". For each of these I want the following:

  • If option is "P" then
    {{
    _.thru(currentSourceRow.patient_import_task_status, (sts) => {
    return sts === "SUCCESS"
    ? "AEE34A"
    : sts === "FAILED"
    ? "FAB5B5"
    : "CFF6F7"
    })
    }}

  • If option is "E" then
    {{
    _.thru(currentSourceRow.encounter_import_task_status, (sts) => {
    return sts === "SUCCESS"
    ? "AEE34A"
    : sts === "FAILED"
    ? "FAB5B5"
    : "CFF6F7"
    })
    }}

  • If option is "A" then
    {{
    _.thru(currentSourceRow.patient_import_task_status, (sts) => {
    return sts === "SUCCESS"
    ? "AEE34A"
    : sts === "FAILED"
    ? "FAB5B5"
    : "CFF6F7"
    })
    }}

does this method above that you mentioned work in this case? Thank you so much for your help here :slight_smile:

Great news! I could not help myself but to try and solve this issue.

Now this might not be "the right way" but it definitely works :slight_smile:

Here is a JSON export of what I whipped together to get working.

Basically, the first thing I did, was add a new column to the table with no source.

I manually manipulated the source row, to serialize the states with their tags

Then, we can make a transformer that maps all the different combinations of tags and statuses. You have 3 tags and 3 statues with colors, so the options list needs 9 entries.

Then we use that transformer as the source of the options list

And finally, since the rows now produce arrays of tags with statues and the options can map those...

Et Voila!

2 Likes

This is awesome! Thanks Kevin :fire:

2 Likes