Actions
Custom actions can be applied to 4 areas of an object-table: rows, cells, columns and the object-table itself.
Empty action
In the event that a table contains no rows, an <empty-action>
node can be used to add additional UI functionality.
<object-table ...>
<empty-action icon="fa-angle-right" on-press="$:noResultsAction()" validate="false" />
...
</object-table>
function noResultsAction(object){
// Do something with the object
console.log(JSON.stringify(object));
}
Note: This works in addition to the empty-message
attribute that is available on an object-table
.
Row actions
Similar to bind, a row can trigger an action by nesting a standard action
tag in an object-table
. For example:
<object-table ...>
<action icon="fa-angle-right" on-press="$:rowAction($selection)" validate="false" />
...
</object-table>
function rowAction(object){
// Do something with the object
console.log(JSON.stringify(object));
}
When using a function to specify the icon
attribute on <action/>
, it has access to $object
(note: not $selection
), for example:
<object-table ...>
<action icon="$:getIcon($object)" .../>
...
</object-table>
Cell actions
When an action
is specified within a column
, the action will fire when the particular column is selected. The icon
, in this case, is placed on the right - and should not be confused with a standard cell icon, which is independent of the action
icon
.
<object-table ...>
<column display="{name}" heading="Name">
<action icon="fa-angle-right" on-press="$:cellAction($selection)"/>
</column>
<column display="{surname}" heading="Surname">
<action icon="fa-angle-right" on-press="$:cellAction($selection)" />
</column>
...
</object-table>
function cellAction(object){
// Do something with the object
console.log(JSON.stringify(object));
}
Much like a row action, this function also has access to $selection
.
Combining row and cell actions
In the case where both a row and cell action are present, the cell action will take precedence and prevent the row action from firing.
<object-table ...>
<action icon="fa-angle-right" on-press="$:rowAction($selection)" />
<!-- Clicking here will fire the row action -->
<column heading="Name">{name}</column>
<!-- Clicking here will fire the cell action only -->
<column heading="Surname" display="{surname}">
<action icon="fa-angle-right" on-press="$:cellAction($selection)" />
</column>
</object-table>
Column actions
A column action is displayed next to the column heading, in the same place the filter icon would normally be. If the action is specified, the header-action
icon is used regardless if filters are enabled or not.
<object-table ...>
<column heading="Name">
<header-action icon="fa-angle-right" on-press="$:headerAction()" />
</column>
</object-table>
Note: Unlike row and cell actions, this function does not have access to $selection
, as they are only rendered once per column.
Common patterns
Header actions can be used in interesting patterns, as follows:
Combo menu
In this example the header action displays a dropdown menu with a set of options, where and when pressed.
function headerAction(){
var option = actionSheet(["Setting 1", "Setting 2", "toggle-filter"]);
// do something with the option
}
Combo menu with original filter capability
function headerAction(){
var option = actionSheet([
"Setting 1",
"Setting 2",
"Toggle Filter" // <--- we want this menu item to have the original toggle-filter capability
]);
if(option === 2){
// so we specifically return 'show-filter' here
// this is referred to as a 'return directive'
return "show-filter"
}
}
Pin frozen column
In this example, when the action is pressed, a view variable is set which indicates that the particular column should 'freeze' to the left.
<var name="frozen_column" type="string" />
<object-table ...>
<column freeze="$:view.frozen_column === 'name'?'left':'none'" heading="Name">
<header-action icon="fa-pin" on-press="$:headerAction()" />
</column>
...
</object-table>
function headerAction(){
view.frozen_column = "name";
}
object-table
actions
object-table
actionsobject-table
actions enable additional buttons to be appended to the controls area of an object-table
. Additionally, these buttons can call functions passing the current data in the object-table
.
For example:
<object-table label="Employees" limit="17" empty-message="Your items will appear here" query="employees" mode="paginate">
<column heading="Name">{name}</column>
<button-group>
<button icon="fa-envelope" label="Email" on-press="exportCSV($filteredData, filteredDisplayData, controls)"/>
<button icon="fa-download" label="Export CSV" on-press="exportCSV($filteredData, filteredDisplayData, controls)"/>
</button-group>
</object-table>

Each of the buttons call a function in their on-press
attribute with the following three parameters:
$filteredData
: An object of the form{columns: string[], rows: DatabaseObject[]}
.DatabaseObject
refers to the familiar JourneyApps object that can be used to update values in the database.filteredDisplayData
: An object of the form{columns: string[], rows: string[][]}
. The rows correspond to the text currently displayed in the table. This object can be directly passed to CSV'sstringify()
function to create a CSV export of the table's data.controls
: An object of the form{page: number, totalPages: number, limit: number, filters: {string: string[]}}
. This represents the current state of the search criteria and filters applied to theobject-table
.
In both parameters where data is passed to the function the sort order and current table filters are applied to the data.
Example: Select all items on a page
<object-table label="Select one to view details" query="tickets" empty-message="Your items will appear here" limit="5">
<column heading="Date">{date}</column>
<column filter="true" heading="Customer">{customer}</column>
<column filter="true" heading="Pad">{pad_name}</column>
<column style-align="right" heading="Total">{$object.ticket_total}</column>
<button-group>
<button label="Select all" icon="fa-check" on-press="$:selectAll($filteredData, controls)" validate="false" style="outline" />
</button-group>
</object-table>
function selectAll(filteredData, controls) {
var startIndex = (controls.page - 1) * controls.limit;
var endIndex = controls.limit * controls.page;
// slice the current visible page's objects out of the array of all objects currently rendered (sorting and filtering included)
var selectedObjects = filteredData.rows.slice(startIndex, endIndex);
}
Example: One-click CSV export
<model name="employee" label="Employee">
<field name="name" label="Name" type="text:name" />
<display>{name}</display>
</model>
<view title="CSV Export">
<var name="employees" type="query:employee" />
<object-table label="Employees" query="employees">
<column heading="Name">{name}</column>
<button-group>
<button icon="fa-download" label="Export CSV" on-press="exportCSV($filteredData, filteredDisplayData, controls)"/>
</button-group>
</object-table>
</view>
function exportCSV(filteredData, filteredDisplayData, controls) {
var data = CSV.stringify(filteredDisplayData);
journey.files.saveFile(data, 'data.csv');
}
Last updated