Using custom columns

Custom columns in table components are a quick and easy way to add a column to your table component. With that said, custom columns are generally only available on your app's "frontend". Their data isn't easily accessible in the table's data property so doing something like summing up two custom columns can be tricky. You can't just do {{ currentRow.number_column1 + currentRow.number_column2 }} if those columns are custom columns.

You can use the table2.columnMappers property (see screenshots below), which holds custom column information, but if the logic you'd like to write is too big for a one-liner inside the mapper, then keep reading!

A screenshot of the .columnMappers property:

An example of using the .columnMappers property to sum two custom columns inside of another custom column:

If you want to do more than sum two columns together and your JS is starting to get a little complicated, I'd personally recommend writing a JS transformer that handles all the logic and adds any columns you need into your data. Then, you can show the results of that JS transformer in your table and avoid custom columns all together.

How to add a new column to your data

Here's a quick, helpful answer written by a Community member!

Here's an example specifically built for a user who attended Retool office hours last week! They wanted to use custom columns to add tax and some conditional fees to a base amount, and show the total amount.

I'm looping through the data returned from a SQL query and adding in some new columns (just new Keys in a row Object).

Here's some simple, boilerplate code:


for (let i=0;i<data_array.length;i++) { //loops through our data array
  let row_obj = data_array[i] //creates a variable for each row in our data array
  row_obj['new_column'] = 5 * i //replace 5*i with the value to insert into your new column
}
return data_array;

Here's my code from the above example to add custom columns and conditionally set their values:


for (let i=0;i<data_array.length;i++) { //loops through our data array
  let row_obj = data_array[i] //creates a variable for each row in our data array
  let amount_with_tax = row_obj.amount * 1.09 //amount + tax
  let fee_based_on_date = 0 //creates a variable for our fee
  let start = moment(row_obj.created_at) //start date using moment
  let end = moment(row_obj.updated_at) //end date using moment
  let date_diff = end.diff(start, 'days') //difference between the end and start dates, returns a string, e.g. '843'
  let date_diff_as_int = parseInt(date_diff) //converts difference into an integer, e.g. 843 

  if (date_diff_as_int <= 850) { //conditional logic to set the fee based on the date difference
    fee_based_on_date = 8.50
  } else if (date_diff_as_int <= 900) {
    fee_based_on_date = 9
  } else if (date_diff_as_int <= 950) {
    fee_based_on_date = 9.50
  } else {
    fee_based_on_date = 10
  }
  row_obj['with_tax'] = amount_with_tax //adding new columns to the row object, e.g. a new 'with_tax' column
  row_obj['fee'] = fee_based_on_date
  row_obj['with_tax_and_fee'] = amount_with_tax + fee_based_on_date
}
return data_array;

See attached app JSON if you want to poke around with my setup! You can import this JSON file by clicking Create new (home page) > From JSON. Quick docs on exporting/importing apps here and as always, comment below with any thoughts or questions! :slight_smile:

add tax column without using custom column (2).json (24.5 KB)

1 Like

Here's how you might add up selected column values!

Without custom columns, we can easily access the column values to add them up:


{{_.sum(table1.selectedRow.data.map(row => row.with_tax_and_fee))}}

With custom columns, it requires a bit more JS:


{{table2.selectedRow.index.reduce((partialSum, i) => partialSum + table2.columnMappers['Custom Column 1'][i] + table2.columnMappers['Custom Column 2'][i], 0)}}

Hi @victoria!

I'm trying to employ my custom columns in a js transformer but it doesn't like columnMappers

var newData = [];
let timeStart = {{table1.columnMappers['Custom Column 2']}}
let timeEnd = {{table1.columnMappers['Custom Column 3']}}
let items = {{getSingleDay.dataArray}}
items.forEach(event => {
    newData.push({
    start: event.start,
      startTime: event.timeStart,
      endTime: event.timeEnd,
      title: event.summary
  })
});
return newData

here's what it currently looks like, but I keep getting "undefined" from both startTime and endTime. Thanks!

Hey @fish_hatchery! Happy to help with this.

Would you mind sharing a screenshot of your left panel’s State tab with your table1.columnMappers property expanded out as much as possible?

Perfect, thank you!

So looking through your code,

You’re looping through your getSingleDay.dataArray array. You’re referring to each element in that array as ‘event’. Then you’re adding new values into your object with the value of event.timeStart, for example.

Does each element in your getSingleDay.dataArray array have a timeStart key?

Or are you trying to pop the value from your custom column 2 in that startTime value?