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[]}.DatabaseObjectrefers 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
