FM BetterForms Docs
BF Editorfmbetterforms.com
master
master
  • Introduction
  • 🏆Features
  • Getting Started
    • Welcome to FM BetterForms!
    • System Overview
    • Quick Tour of the BetterForms IDE
    • 1. Setting Up Your Foundation
      • 1.1 Configure FileMaker Server
      • 1.2 Install BetterForms Helper File
      • 1.3 Add Your Server to BetterForms (IDE)
    • 2. Building Your First Application
      • 2.1 Create an App (Site) in the IDE
      • 2.2 Create Your First Page (Intro to Page Builder)
      • 2.3 Understanding & Managing Environments (IDE)
      • 2.4 Adding Elements to Your Page
      • 2.5 Understanding Validation
      • 2.6 Adding Actions to Your Page
      • 2.7 Creating Your First List View
      • 2.8 Understanding Page Data Flow
      • 2.9 Creating Your First Hook
      • 2.10 Working with Data Tables (Coming Soon)
    • 3. Understanding Core BetterForms Concepts
      • 3.1 Introduction to Hooks (and where to find them in the IDE)
      • 3.2 Running Your First Hook (Practical Example)
      • 3.3 Introduction to Actions & Action Scripts (IDE Context)
      • 3.4 Understanding the Data Model (and Page Data Model UI)
    • 4. Common Customizations & Expanding Your App
      • 4.1 Adding & Configuring Buttons (Page Builder)
      • 4.2 Implementing Page Navigation (Actions & Site Navigation UI)
      • 4.3 Displaying Data in Tables (Page Builder & Element Config)
      • 4.4 Basic App Styling (Site Styling UI)
    • 5. Mastering the BetterForms Environment & Advancing Your Skills
      • 5.1 Understanding & Managing Environments (In-Depth)
      • 5.2 Deep Dive: Page Configuration & Settings
        • Navigating the Page Builder Interface
        • Working with Page-Level Action Scripts
        • Configuring the Page Data Model
        • Page Integration Settings Explained
        • Managing Page Info & Other Settings
      • 5.3 Working with Global Scripts
      • 5.4 Managing App (Site) Settings & Navigation
      • 5.5 Exploring Further: What to Learn Next
    • Support & Resources
      • Getting Help
      • Learning JSON
  • Reference
    • Site Settings
      • Navigation
      • App Model
      • DOM Header Insertions
      • Global Named Actions
      • Site Structure
      • Slots / Code Injection
    • Developer Mode
    • Page Settings
      • Data Model
      • Card / Window Modals
      • Validation
        • Custom Validators
      • Misc Page Settings
    • Page Elements
      • Copy of Site Structure
      • BetterForms Elements
        • Checkbox
        • Checklist
        • Cleave.js Input Masking
        • DateTime Picker
        • Google Address Autocomplete
        • Image Display Element
        • Input
        • Masked Input
        • Range Slider (noUiSlider)
        • Radios
        • Select
        • Advanced Select (selectEx)
        • TextArea
      • Common
        • Input
        • Button
        • Data Table
        • HTML
      • Grouping Elements
        • Tabs
        • Panel
        • accordion
        • accordion2
        • listrows
      • Uploading Files
        • dropzone
        • dropzone to S3
        • uploadCare
        • 🏗️Uppy File Upload Widget Integration with AWS S3
      • Misc Elements
        • Plain Text / Code Editor
        • signature
        • fullCalendar
        • rangeSlider
      • Payment Gateways
        • Authorize.net
        • PayPal
        • Stripe
      • Adding Custom Page Elements
    • Actions Processor
      • Named Actions (Action Scripts)
      • Actions
        • runUtilityHook
        • path
        • debounce
        • throttle
        • showAlert
        • showModal / hideModal
        • function
        • clipboard
        • cookie
        • setFocus
        • scrollTo
        • wait
        • emit
        • validate
        • channelJoinAnon
        • channelLeaveAnon
        • messageSend
        • messageSendAnonChannel
        • consoleError
        • showStripeCheckout
      • Authentication Actions
    • Script Hooks
      • Globals Variables
        • $$BF_Model
        • $$BF_App
        • $$BF_State
      • Keeping Keys Private
      • Reducing Payload Size
      • API Callback Endpoint
      • Common Hooks
      • Scoped Hooks
    • Users & Authentication
      • Managing User Accounts
      • Custom Login Pages
      • OAuth
    • Advanced Configuration
      • Custom Domains
    • BF Utility Functions
      • Example Usage
        • BF.i18n()
    • BF Error Codes
    • Messaging
      • Adding users to channels
      • Removing users from channels
      • Sending messages
      • Get connected users
      • Get active channels
    • Practices for File Downloads
    • BF Streaming Proxy
    • Updating the Helper File
    • Connection Trouble Shooting Guide
    • Software Testing Overview
    • JavaScript Libraries
    • FM BetterForms - Quality Assurance
    • Rollbacks and Version Control
    • BF Server Proxy
    • Setting up Auth0
    • Create an S3 Bucket on AWS
    • ApexCharts - Getting started
    • BF Enterprise Documentation
    • BetterForms Error Pages API
    • BF Streaming API
    • LLM Query API
    • Creating a PWA
  • Usage Tips
    • Troubleshooting
      • Debugging
      • Frozen Actions Queue
      • Vue Variables
    • JavaScript Tips
      • Calling Named Actions from HTML Vue Events
      • Calculations
    • Hacking a Webpage
    • System Overview
    • Forms Processor
      • Form Types
      • HTML & VueJS
      • Styling and Design
    • Customizing and Styling
      • Custom CSS
      • Custom Components
        • Components Editor
        • Component Best Practices
      • Page Pre-loaders
      • Favicon
    • Design Patterns and Best Practices
      • Working with environments
      • Handling Data
      • Saving Data
      • Data Optimization
      • Business Logic
      • UI / UX
      • Debugging
      • Script Engine Optimization
    • Getting Started
    • Installation
  • Security
    • Authentication
    • Security White Paper
    • Firewalls
    • Technology Stack
  • Compatibility
Powered by GitBook
On this page
  • Additional keys:
  • Slots Example
  • Slots
  • Accessing Data in slots
  • row
  • data model
  • Child Rows
  • Interacting with the Table (Row Click Actions)
  • Custom Sorting Functionality

Was this helpful?

  1. Reference
  2. Page Elements
  3. Common

Data Table

PreviousButtonNextHTML

Last updated 2 months ago

Was this helpful?

This component is based on Refer to source code for additional documentation.

Additional keys:

Additional Keys
Type
Description

model

string

The key of an array in your data model containing the data to display in the table

options

object

Various options as defined in the source code (see link above)

actions_onRowClick

array

(optional) Array of actions to execute when row is clicked

slots

array

(optional) Array of objects, allows insertion of HTML content (see below)

Slots Example

Add the slots key to this element to define HTML regions to be displayed with the table. The slot key within each object defines the name of the slot, which can be referenced in the columns key.

If you name a slot child_row, that HTML content will be displayed when the row of the table is expanded. (see CSS trick for how to customize the look of the child row icon)

"columns": ["name", "title", "slot_name", "button_slot"],
"slots": [{
    "html": "<h1>{{model.title}}</h1>",
    "slot": "title"
}, {
    "html": "<h6>{{model.description}}</h6>",
    "slot": "slot_name"
}, {
    "html": "<button class=\"btn btn-info\" v-on:click=\"namedAction('myNamedAction'; {row: props.row})\"><i class=\"fa fa-check\"></i> OK</button>",
    "slot": "button_slot"
}, {
    "html": "{{props.row.productList}}",
    "slot": "child_row"
}]

When referencing row data within slots, use props.row instead of the usual model keyword.

Slots

Slots allow you to insert you own custom HTML in predefined positions within the component Slots with respect the BF Forms render engine and render VueJS code also:

  • beforeTable: Before the table wrapper. After the controls row

  • afterTable: Before the table wrapper.

  • beforeFilter: Before the global filter (filterByColumn: false)

  • afterFilter: After the global filter

  • beforeLimit: Before the per page control

  • afterLimit: After the per page control

  • beforeFilters: Before the filters row (filterByColumn: true)

  • afterFilters: After the filters row

  • beforeBody: Before the <tbody> tag

  • afterBody: After the <tbody> tag

  • prependBody: Prepend to the <tbody> tag

  • appendBody: Append to the <tbody> tag

If a slot has the same name as a column, it will replace the columns contents. You can class the rows object (data object for that row) via model.row.myField

Accessing Data in slots

row

Each rows data can be found in the props.row variable when using custom html slots.

eg: {{props.row.nameFirst}} would render the first name field

data model

Sometimes you may want to reference the parent data model (The model that was used for the form, or the container element). You can reference to parents data model with the variable model

eg: {{model.isLocked}} would render the isLocked field in the parent data model

Child Rows

Add the following CSS to your site to change how the icon to open or close the child row

.VueTables__child-row-toggler {

    width: 16px;

    height: 16px;

    line-height: 16px;

    display: block;
    margin: auto;

    text-align: center;
}



.VueTables__child-row-toggler--closed::before {
    content: "►";
}

.VueTables__child-row-toggler--open::before {

    content: "▼";
}

Interacting with the Table (Row Click Actions)

actions_onRowClick

The Data Table element supports actions_onRowClick actions. This allows you to programmatically control what happens when a user clicks a row.

Within each action in this actions array, a "row" key will be injected into the options.params so that you can reference the data of the row that was clicked.

  • To access the row from a function action use action.options.params.row

  • To access the row from within an options key (see example below), use this.params.row.id

The following is an example that will pas the key id from the table row into the path action

// actions_onRowClick is added to the root level of the element 

// Best practice:
"actions_onRowClick": [{
   "action": "namedAction",
   "name": "myRowClickHandler"
  }]  
  
 // in myRowClickHandler, you can get the row from params:
 let row = action.options.params.row
 ...
 
 
 
 // Older practice:
 actions_onRowClick": [{
   "action": "path",
   "options": {
      "path_calc": "'/invoicedetail?id=' + this.params.row.id"
    }
  ]
  
// In Filemaker in the invoicedetail onFormRequest hook script
// Get the id via $$BF_Query:
Set Variable $id = JSONGetElement ( $$BF_Query ; "id" )

Custom Sorting Functionality

A common issue arises when attempting to use the table’s custom sorting functionality for columns where numeric values are stored as strings. For instance, when sorting a column with prices stored as strings, the default behavior sorts them alphabetically rather than numerically.

To address this, you can define custom sorting functions in the table options. Below is an example demonstrating how to handle custom sorting for different types of columns:

  • price_function: Sorts the price column numerically, converting the price strings to floats for accurate comparison.

  • name_function: Sorts the name column by last name, splitting the full name string and comparing the last names.

  • date_function: Sorts the date column chronologically, converting the date strings to date objects for accurate comparison.

"options": {
    "customSorting": {
        "price_function": "var ascending = arguments[0]; return function(a,b){if (ascending) return parseFloat(a.price) >= parseFloat(b.price) ? 1 : -1; return parseFloat(a.price) <= parseFloat(b.price) ? 1 : -1;}",
        "name_function": "var ascending = arguments[0]; return function(a,b){if (ascending) return a.name.split(' ')[1] >= b.name.split(' ')[1] ? 1 : -1; return a.name.split(' ')[1] <= b.name.split(' ')[1] ? 1 : -1;}",
        "date_function": "var ascending = arguments[0];return function(a, b) {if (ascending) return moment(a.date, 'M/D/YYYY').isAfter(moment(b.date, 'M/D/YYYY')) ? 1 : -1;return moment(b.date, 'M/D/YYYY').isAfter(moment(a.date, 'M/D/YYYY')) ? 1 : -1;}"
    }
}

Vue-Tables-2
below