Table Control: Configuration Quirks and Avoiding Common Problems


The Brazos UI Table control is highly flexible, having been designed to accommodate any other control (including other tables!), to convert to read-only with a single configuration option, and to have a suite of built-in functions (selection, data sorting, CSV exporting, and more) all while being performant and easy for end users to interact with. However, being one of the most powerful and flexible controls in the Brazos UI Toolkit means that developers have a lot more to be aware of when working with the Table control. The following guidelines should help you get the most out of your tables while also helping you avoid or diagnose problems you might encounter.

Note: The Table and the deprecated Data Table control are, behind the scenes, identical. The Table control simply defaults to being editable while the deprecated Data Table defaults to being read-only.

Help Text

Help text in Brazos UI controls is normally configured via the stock Help field from a coach view control (Properties > General > Common > Help):

Normally, the help text will display as a mouseover tooltip for the associated control:

The behavior of tooltip help of tables and controls placed in tables is altered as outlined below.

Table-level help

The table control itself does not support the use of help text but instead incorporates the help text of individual controls used within it (see below for control-level and column-level help). For table-level help, we advise designing the layout of the coach and table to make it clear as to its purpose. If additional information needs to be conveyed, that can be achieved via text blocks on the page (using a Custom HTML block, for example) or through targeted column-specific help. The Custom HTML block method is used in the Brazos UI Examples Application:

Control-level help

Controls placed within the table will display their help text as a tooltip. By default, this help text will display upon mouse over of any individual cell within that column. This can be useful if there is something that a user needs to be reminded of with every cell, but can result in a somewhat "busy" user experience.


Column-level help

Instead of displaying help text in every cell of a column, the help text can be displayed in the header cell of the column by utilizing the "Tooltip Icon" configuration option of a control. Just as the Label of the control is used to set the column name, the "Tooltip Icon" will tie the help text to the selected icon (which displays in the header cell). This can be a tidier option than every cell displaying mouse-over text and also gives a visual indicator of available help via the icon.


Editable vs. Read-Only

As noted in the "Lighter, Faster: Using Table Controls in Non-Editable Mode" Technote, the Table control has a configuration option to switch the mode of the table from editable to read-only.

When presenting non-editable data to users or when you need to squeeze every drop of performance out of your coach, using the Table in Read-Only mode is a great choice. Utilizing Read-Only mode is as easy as changing the 'Table Mode' configuration option. There is no need to change the controls in the table even if you are using those that normally accept inputs. This can be a boon when you need both editable and read-only versions of the same table arrangement. However, due to alterations that happen behind the scenes to table structure and behavior, there are several tweaks and accommodations that may be required.

Check for:

  1. Button labels. The per-row naming of buttons is possible with editable tables but is not supported in Read-Only mode. As part of the changes to embedded controls when the table is non-editable, the button control will only show a single label for the entire column.
  2. Date Time Picker date formatting. With no formatting set in the control itself, the default date displays are different in each table mode. When read-only, the date is formatted identically to how the Output Text control does it (with no formatting specified).

    If a format is specified in the control, it will be honored regardless of the table mode. Therefore, if you use the same table configuration in multiple places it is best to specify the date format for consistency.
  3. Modal data population. How row data are populated into a modal changes depending on if the table is editable or read-only. See the section below on using modals in tables for specifics of how to configure a Modal for each table mode.
  4. Table bindings with AJAX data loading. The requirements for data binding differ between editable and read-only table modes when using AJAX-population of data. The subsequent behavior of the data binding is also different when loading data via and AJAX service. See the section below on using AJAX with tables.

Using Modals with Tables

As shown in the Brazos UI Examples application, modals can be used to great effect with the Table control. While a row-independent form could be used with a table, it is often more useful to populate a modal with data that is directly derived from the row. At the most basic, the Modal control can be used to show more of a row's data (or the entire record). To do so requires that the controls within the modal get mapped to the correct data. There are three methods for accomplishing this:

  1. Editable Table with Modal in row. The most straightforward use is to place the Modal control directly into the table as a column. In terms of the underlying page layout, each row will have its own Modal control. Then, as with any other control in the table, you can utilize the `currentItem` value to set each field of the Modal.
    • Table is bound to tableData[] (TableData)
    • Each field in the row is associated with a given property of the BO, e.g. tableData.currentItem.date1
    • Fields in the modal are associated with a row property in the same way, e.g. tableData.currentItem.deliverableStatus

  2. Read-Only Table with Modal in row. When the table is in Read-Only mode, the Modal control populates its data in a slightly different manner. Behind the scenes, each row does not actually have its own modal popup present in the DOM. Rather, each modal launch button opens the same modal content popup and row-specific data is populated into it. This is one of the changes that allows the Table to be lighter and faster when set to Read-Only mode but this does change how the Modal needs to be configured to load data correctly. Specifically, the Modal itself requires a binding to a singular variable that is the same datatype as the table's binding. The fields within the modal are then bound to this singular variable's properties and not directly to any of the row's currentItem. When the modal launch button is clicked, the correct row data is "automagically" mapped to the modal and its fields. Example:
    • Table is bound to tableData[] (TableData)
    • Each field in the row is associated with a given property of the BO, e.g. tableData.currentItem.date1
    • The Modal is bound to a different single variable of the same type, e.g. modalVariable (TableData)

    • Fields in the modal are associated with the properties of the modal's binding, e.g. modalVariable.ID

  3. Single modal with editable tables. Placing a modal in an editable Table control results in one modal per row. It is possible to streamline this by mimicking how the read-only table utilizes a single modal with data loading. As this is more complicated of an implementation, you should test performance of your coaches to determine if this arrangement would be beneficial.
    Example using local data binding:
    • Table is bound to tableData[] (TableData). Selection should be set to "None" or "Single Selection" only.
    • Each field in the row is associated with a given property of the BO, e.g. tableData.currentItem.date1
    • Button is placed in the table with 'Select Row' for the Table Behavior configuration option. This button will be used to select the correct table row and open the Modal programmatically.
    • Modal, placed outside of table, is configured as follows:
      • Hide Launch Button checked
      • Open Modal Display Programmatically set to a boolean variable (e.g. openModal (Boolean))
      • Fields in the Modal are bound to listSelected properties of the associated table's binding, e.g. tableData.listSelected.string1

    • Wire the select Button's boundary event to a script that sets the boolean to `true` (e.g. tw.local.openModal = true;)

    For an AJAX-populated Table you will need to make the following modifications to the above configuration:
    • Utilize the Selection List configuration option
    • Bind the Modal's fields to the configured Selection List (e.g. tw.local.selectionList.currentItem.string1)
    Note that while the display of data works with the above configurations, you will need to utilize the boundary events available from the Modal in order to persist changes made to selected data.

Configuration errors:

If a read-only table's modal isn't configured correctly, you will notice that the modal will either not load the data (fields are blank) or that every modal shows the same data regardless of which row it is launched from. The latter case happens because in read-only mode there is a hidden placeholder row that always references the same `currentItem` regardless of which modal launch button is used.

AJAX Loading of Tables

When loading table data via AJAX there are several technical behavior changes with regard to variable bindings and data manipulation to take into consideration.

Data mapping. A data binding is required for an editable Table, but is actually optional in read-only mode. The read-only Table is capable of assigning data based on control-bindings only, which does mean you still need a variable of the correct BO type in order to assign these bindings correctly. It is safe to assign a binding regardless of mode, however, so the simplest rule of thumb it to always have a binding. The binding should always be a list object.

It is important to note that using the bound variable of an AJAX-populated table for either data evaluation and manipulation should not be relied upon. This is called out in the documentation for the Table control. Since data in the table is derived from the AJAX service and not the binding:

  • The binding will not reference the entire data set as it would with local binding. Typically the binding will only be populated with a single page's worth of data rather than the entire data set which greatly limits data access.
  • Attempts to change data using the binding will not give expected results. A Row Actions Service should be implemented for making and persisting changes to the table's data.

Boundary Events

Firing a boundary event from a button placed within the table may give unexpected or inaccurate results. Button controls placed in the table can be configured to select or delete rows. If you are attempting to fire a boundary event related to the addition or deletion of a row on button click, you must fire the event off of the table itself. Configure the Button itself as desired ("Table Behavior") and in the Table check the "Fire Boundary Event When Row Added or Deleted" configuration option. If you need both boundary event types, assign a String variable to the "Action Executed" configuration option.

From the Table's boundary event you can then evaluate the String variable in a Script or a Decision Gateway (shown here):

Have more questions? Submit a request


  • Avatar
    Aleksander Kovač

    Please add an explanation on how to handle row click events.

  • Avatar
    Tom Bushart

    Hi Aleksander! Row-click events are not something that the Table handles out of the box, but that is something we've done as custom work before. As something potentially similar there is this article on carrying out a full select on Output Text or Table cells. Let me open up a support ticket for you so we can work through what your goal is with row click events and what the best way to achieve that might be.

    Edited by Tom Bushart
Powered by Zendesk