MLoadRecords Class
Overview
The MLoadRecords class handles loading form schemas and records from companion Fulcrum apps. It creates a dictionary to convert form_value keys to data_name keys for easier access to record data.
Common Use Cases
- Load records from a linked app based on a record link field
- Refresh a record link field when records in the linked app reference this record
- Prevent duplicate record selection across records in this app
Quick Start
const appID = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
function processRecordsCallback() {
const loadedRecords = loader.appRecords
const titleList = loadedRecords.map(x => x.scientific_name + ' - ' + x.common_name)
SETVALUE('result', titleList.join('\n'))
}
const loader = M.mkMLoadRecords(appID, processRecordsCallback)
loader.dnRecLink = 'species_link'
ON('load-record', loader.buildAppFvDict)
ON('change', 'species_link', loader.updateLoadedRecords)
Method Flow Diagrams
The following diagrams show how methods chain together in the MLoadRecords class.
Diagram 1: buildAppFvDict / getAppFvs Flow
Used in ON('load-record') to initialize the loader.
buildAppFvDict(event) getAppFvs(event)
│ │
│ ├── recordsOnLoad = true
│ │
└────────────────┬───────────────────────┘
│
▼
loadForm(formID, processForm)
│
▼
processForm(form)
│
├── appFvs = {form_value_key: data_name, ...}
│
▼
┌───────────────────┐
│ recordsOnLoad? │
└───────────────────┘
│
┌────────────┴────────────┐
│ │
FALSE TRUE
│ │
▼ ▼
(STOP) ┌────────────────┐
│ dnRefreshRL? │
Records loaded └────────────────┘
later via │
ON('change') ┌────────┴────────┐
│ │
NOT SET SET
│ │
▼ ▼
updateLoadedRecords() refreshRecordLink()
│ │
│ │
(see Diagram 2) (see Diagram 3)
Key Points:
buildAppFvDictdoes NOT setrecordsOnLoad, so it stops after building the dictionarygetAppFvssetsrecordsOnLoad = true, so it continues to load records- Use
buildAppFvDictwhen you want to load records later viaON('change') - Use
getAppFvswhen you want to load all records immediately on form load
Diagram 2: updateLoadedRecords Flow
Used in ON('change') for record link field, or called automatically from processForm when recordsOnLoad is true.
updateLoadedRecords(event)
│
├── ids = VALUE(dnRecLink).map(x => x.record_id)
│
▼
┌───────────────┐
│ ids exist? │
└───────────────┘
│
┌─────┴─────┐
│ │
NO YES
│ │
▼ ▼
clearAutoFields() loadRecords(ids, processRecords)
│ │
▼ ▼
(STOP) processRecords(records)
│
▼
_processRecordResults(records)
│
├── appRecords = converted records
│
▼
┌─────────────────────┐
│ recordsOnLoad AND │
│ enterLoadedData? │
└─────────────────────┘
│
┌─────┴─────┐
│ │
FALSE TRUE
│ │
▼ ▼
(STOP) enterLoadedData(records)
│
▼
(STOP)
User callback processes
records (e.g., populate
fields, build lists)
Key Points:
- Extracts record IDs from the configured
dnRecLinkfield - If no IDs found, clears auto-populated fields and stops
enterLoadedDatacallback only runs ifrecordsOnLoadis true
Diagram 3: refreshRecordLink Flow
Finds records in linked app that reference THIS record (reverse lookup).
refreshRecordLink()
│
├── opts = filterTemplate(dnRefreshRL, "contains", RECORDID())
│
▼
loadRecords(opts, processRefreshRL)
│
▼
processRefreshRL(records)
│
▼
_processRecordResults(records)
│
├── appRecords = converted records
│
▼
┌──────────────┐
│ has records? │
└──────────────┘
│
┌─────┴─────┐
│ │
NO YES
│ │
▼ ▼
(STOP) ids = appRecords.map(x => x.id)
│
▼
SETVALUE(dnRecLink, ids)
│
▼
addOnRefreshRL()
│
▼
(STOP)
User callback for
additional processing
Key Points:
- Queries for records where
dnRefreshRLfield contains currentRECORDID() - Updates
dnRecLinkwith the IDs of matching records - Useful for parent-child relationships where child records link to parent
Diagram 4: selfDupCheck Flow
Prevents duplicate record selection across records in this app.
selfDupCheck(event)
│
├── id = event.value[0].record_id
│
▼
┌────────────┐
│ id exist? │
└────────────┘
│
┌─────┴─────┐
│ │
NO YES
│ │
▼ ▼
clearAutoFields() SETVALUE(dnRecLinkIds, id)
│ │
▼ ▼
(STOP) loadRecords(filterTemplate(...), processSelfDupCheck)
│
▼
processSelfDupCheck(records)
│
▼
_processRecordResults(records)
│
▼
┌───────────────────────┐
│ Is current record in │
│ results? (not a dup) │
└───────────────────────┘
│
┌─────┴─────┐
│ │
YES NO (duplicate!)
│ │
▼ ▼
(STOP) clearAutoFields()
│
▼
SETVALUE(dnRecLink, null)
│
▼
duplicateAlert()
│
▼
(STOP)
Key Points:
- Requires
dnRecLink,dnRecLinkIds, and optionallydnsRecLinkAutoto be configured - Stores the selected record ID in a text field (
dnRecLinkIds) for querying - If another record already links to the same target, clears selection and shows alert
Configuration Properties
| Property | Type | Description |
|---|---|---|
formID |
string |
Fulcrum form ID of the linked app |
enterLoadedData |
Function|null |
Callback to process records after loading |
recIDs |
Array<string>|null |
Array of record IDs to load |
appFvs |
Object |
Dictionary mapping form_value keys to data_names |
appRecords |
Array<Object>|null |
Loaded records with data_name keys |
recordsOnLoad |
boolean |
If true, loads records immediately after form schema |
sortOrder |
Array<Array>|null |
Sort order for queries, e.g., [['report_id', 'dsc']] |
dnRecLink |
string |
THIS app data name of record link field |
dnRecLinkIds |
string |
CHILD app data name of text field storing record IDs |
dnsRecLinkAuto |
Array<string> |
Data names to clear if duplicate found |
dnRefreshRL |
string |
CHILD app data name that links back to this record (this.dnRecLink) |
addOnRefreshRL |
Function |
Additional callback after refreshing record link |
duplicateAlert |
Function |
Function to call when duplicate detected |
helpers |
FulcrumHelpers |
FulcrumHelpers instance for utility methods |
Examples
Example 1: Load Records on Change
Load species data when a record link field changes.
const speciesAppID = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
function displaySpeciesInfo() {
const records = loader.appRecords
if (!records) return
const info = records.map(r => `${r.scientific_name} (${r.common_name})`).join('\n')
SETVALUE('species_summary', info)
}
const loader = M.mkMLoadRecords(speciesAppID, displaySpeciesInfo)
loader.dnRecLink = 'species_link'
ON('load-record', loader.buildAppFvDict)
ON('change', 'species_link', loader.updateLoadedRecords)
Example 2: Prevent Duplicate Selection
Ensure each project can only be linked once across all records.
const projectAppID = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
const loader = M.mkMLoadRecords(projectAppID, null)
loader.dnRecLink = 'project_link'
loader.dnRecLinkIds = 'project_id_text' // Hidden text field to store ID for querying
loader.dnsRecLinkAuto = ['project_name', 'project_manager', 'project_date']
// Custom duplicate alert
loader.duplicateAlert = () => {
ALERT('This project is already assigned to another record. Please choose a different project.')
}
ON('load-record', loader.buildAppFvDict)
ON('change', 'project_link', loader.selfDupCheck)
Example 3: Refresh Child Records
Automatically populate a record link with all child records that reference this parent.
const childAppID = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
function afterRefresh() {
const count = loader.appRecords ? loader.appRecords.length : 0
SETVALUE('child_count', count)
}
const loader = M.mkMLoadRecords(childAppID, null)
loader.dnRecLink = 'child_records' // Record link field in THIS app
loader.dnRefreshRL = 'parent_record_link' // Field in CHILD app that links to this record
loader.sortOrder = [['created_at', 'dsc']]
loader.addOnRefreshRL = afterRefresh
ON('load-record', loader.getAppFvs) // Use getAppFvs to load immediately
See Also
FulcrumHelpers- Parent class with utility methodsFulcrumHelpers#fv2DnRows- Converts form_value records to data_name recordsFulcrumHelpers#loadRecords- Base record loading method