1. Ad hoc dialogs and Progress bars

This page describes features introduced in ACF Plugin version 1.7.9.3. The native user interface is currently available in the macOS plugin.

  1. Ad hoc dialogs and Progress bars
    1. Introduction
    2. Ad hoc dialogs
    3. Start with the Dialog Configurator
    4. Opening a dialog from FileMaker
    5. Opening a dialog from an ACF function
    6. Dialog result
    7. Dialog JSON specification
      1. Root object
      2. Fields and initial values
      3. Supported field types
      4. Multiple columns
      5. Buttons
      6. Variations and a master selector
    8. Progress bars
    9. Progress bars in ACF functions
    10. Progress bars in FileMaker calculations
    11. Progress script steps
    12. Practical notes

1.1. Introduction

The ACF Plugin can create native input dialogs and progress windows without requiring a dedicated FileMaker layout. This is useful for parameter collection, settings, report options, imports, exports, and other tasks that would otherwise require global fields and utility layouts.

Both features can be used from:

Progress windows can additionally be updated and closed with native FileMaker script steps.

1.2. Ad hoc dialogs

An ad hoc dialog is described by a JSON object. The object defines the window title, size, fields, initial values, buttons, and optional alternative layouts. The dialog is modal: execution pauses until the user presses a button or closes the window, after which the entered values are returned as JSON.

No FileMaker layout, global field, or card window is needed.

1.3. Start with the Dialog Configurator

The recommended way to create a dialog is the visual Dialog Configurator:

dialog-configurator

https://horneks.no/manuals/ACF/tools/dialog-configurator-1.7.9.7.html

The configurator lets you:

The generated JSON can normally be used directly. You only need the technical specification later if you want to build or modify dialog definitions dynamically.

ConfigResult

1.4. Opening a dialog from FileMaker

Use the external plugin function:

ACF_OpenDialog ( dialogJSON )

dialogJSON is a text parameter containing a serialized JSON object. The function returns the result as serialized JSON text.

For example, use FileMaker's Insert Text script step to place the JSON copied from the configurator in a variable. Select $definition as the target, then paste the JSON into the text window provided by the script step:

Insert Text [ Select ; Target: $definition ; "{ ...dialog JSON from the configurator... }" ]
Set Variable [ $result ; Value: ACF_OpenDialog ( $definition ) ]

Using Insert Text avoids having to escape every double quote in the JSON as required by a FileMaker calculation string.

You can then read the selected button and field values with FileMaker's JSON functions:

JSONGetElement ( $result ; "button" )
JSONGetElement ( $result ; "values.Customer" )

Because ACF_OpenDialog is a calculation function, it can be used in script calculations without compiling an ACF package.

1.5. Opening a dialog from an ACF function

Inside ACF, open_dialog accepts one native JSON value and returns a native JSON result:

JSON result = open_dialog(definition);

The configurator can generate the complete ACF definition. A small example is:

function AskForCustomer()
    JSON definition = JSON(
        "title", "Customer search",
        "subtitle", "Enter the search parameters.",
        "size", JSONarray(520, 330),
        "labelPosition", "left",
        "fields", JSONarray(
            JSON("name", "Customer", "label", "Customer", "type", "text", "width", "full"),
            JSON("name", "FromDate", "label", "From date", "type", "date")
        ),
        "values", JSONarray("", "2026-06-15"),
        "buttons", JSONarray(
            JSON("id", "search", "label", "Search", "default", true),
            JSON("id", "cancel", "label", "Cancel", "cancel", true)
        )
    );

    JSON result = open_dialog(definition);
    return result;
end

The ACF function is blocked while the modal dialog is open. When the user closes the dialog, execution resumes with the returned JSON value.

Customer-search

1.6. Dialog result

A successful result contains the selected button and a flat object of field values:

{
  "button": "search",
  "buttonLabel": "Search",
  "values": {
    "Customer": "Horneks",
    "FromDate": "2026-06-15"
  }
}

The button value is the button's id. buttonLabel is the visible label. If the window is closed without a configured cancel button, button can be null.

Field names become keys below values. If the same field name occurs more than once in the active layout, the returned value for that name is an array:

{
  "values": {
    "Tag": ["First", "Second"]
  }
}

If the definition cannot be parsed or displayed, the result includes an error member:

{
  "button": null,
  "values": {},
  "error": "Dialog definition must be a JSON object"
}

1.7. Dialog JSON specification

1.7.1. Root object

Key Type Description Default
title string Window title. Dialog
subtitle string Optional explanatory text below the title bar. Empty
size array Dialog width and height in pixels, for example [620, 430]. Minimum dimensions are applied internally. [560, 440]
labelPosition string above places labels above controls. left aligns labels in a shared label area within each column. above
fields array Fields for a single-column dialog. Empty
values array Initial values corresponding by position to fields. Empty
columns array Alternative to root-level fields; each column contains its own fields and values. None
buttons array Button strings or button objects. OK and Cancel
selector object Optional master selector for switching between alternative field sets. None
variants object Field layouts keyed by selector values. None

Use either fields and values, or columns, for a given layout section.

1.7.2. Fields and initial values

The shortest field definition is a string:

{
  "fields": ["Customer", "Reference"],
  "values": ["Horneks", ""]
}

The string is used as both the field name and its label, and the control type is text.

For full control, use a field object:

{
  "name": "Notes",
  "label": "Notes for the report",
  "type": "textarea",
  "width": "full",
  "height": 120
}
Field key Type Description
name string Key used in the returned values object.
label string Label shown to the user. Defaults to name.
type string Control type. Defaults to text.
width number or string Fixed pixel width, or full/max to use the available column width.
height number Text area height in pixels. The minimum is 50.
options array Stored values for select and radio fields.
labels array Optional display labels corresponding to options.
value any JSON value Initial value used when no matching entry exists in the section's values array.

The section-level values array is positional: its first item belongs to the first field, its second item to the second field, and so on.

1.7.3. Supported field types

Type Description Returned value
text Single-line text field. string
textarea Multiline text area with vertical scrolling. It fills the available width. string
checkbox Checkbox. boolean
select Popup selection list. selected option value
radio Vertical group of radio buttons. radiobuttons is also accepted. selected option value
date Editable date field with a popup calendar. YYYY-MM-DD string
time Time field with a native time picker. HH:mm:ss string

For select and radio, options contains the returned values. An optional labels array can provide different user-facing text:

{
  "name": "Status",
  "label": "Order status",
  "type": "select",
  "options": ["open", "complete"],
  "labels": ["Open orders", "Completed orders"]
}

1.7.4. Multiple columns

Use columns when fields should be arranged side by side. Each column is a field section with its own fields and values arrays:

{
  "columns": [
    {
      "fields": [
        { "name": "LastName", "label": "Last name", "type": "text" },
        { "name": "BirthDate", "label": "Birth date", "type": "date" }
      ],
      "values": ["", ""]
    },
    {
      "fields": [
        { "name": "FirstName", "label": "First name", "type": "text" },
        { "name": "Active", "label": "Active", "type": "checkbox" }
      ],
      "values": ["", true]
    }
  ]
}

A field with "width": "full" fills its own column, not the complete dialog width.

1.7.5. Buttons

A button can be defined by a simple label:

"buttons": ["OK", "Cancel"]

For stable result identifiers and keyboard behavior, button objects are recommended:

"buttons": [
  { "id": "run", "label": "Run report", "default": true },
  { "id": "cancel", "label": "Cancel", "cancel": true }
]
Button key Type Description
id string Value returned in button.
label string Visible button title.
default boolean Makes the button respond to Return/Enter.
cancel boolean Makes the button respond to Escape and identifies the result used when the window is closed.

1.7.6. Variations and a master selector

A dialog can change its field layout when the user selects an option. This is useful when one settings dialog supports several related operations, such as Offers, Orders, and Invoices.

The root selector defines the master selection control. The root variants object contains one field section for each selector option:

Selector key Type Description
name string Key used for the selected value in the returned values object.
label string Label displayed beside the master selector.
options array Selector values. Each value must have a corresponding key in variants.
labels array Optional display labels corresponding to options.
value string Initially selected option. The first option is used when this is omitted.

Each member of variants is a normal layout section containing either fields and values, or columns.

{
  "title": "Report settings",
  "selector": {
    "name": "ReportSource",
    "label": "Report source",
    "options": ["offers", "orders", "invoices"],
    "labels": ["Offers", "Orders", "Invoices"],
    "value": "orders"
  },
  "variants": {
    "offers": {
      "fields": [
        { "name": "Customer", "label": "Customer", "type": "text" }
      ],
      "values": [""]
    },
    "orders": {
      "fields": [
        { "name": "OrderNumber", "label": "Order number", "type": "text" },
        { "name": "Completed", "label": "Include completed orders", "type": "checkbox" }
      ],
      "values": ["", false]
    },
    "invoices": {
      "fields": [
        { "name": "InvoiceNumber", "label": "Invoice number", "type": "text" },
        { "name": "PaymentStatus", "label": "Payment status", "type": "radio", "options": ["all", "paid", "unpaid"], "labels": ["All", "Paid", "Unpaid"] }
      ],
      "values": ["", "all"]
    }
  },
  "buttons": [
    { "id": "run", "label": "Run report", "default": true },
    { "id": "cancel", "label": "Cancel", "cancel": true }
  ]
}

The selected option is returned in values under the selector's name, together with the values from the active variant:

{
  "button": "run",
  "values": {
    "ReportSource": "orders",
    "OrderNumber": "10452",
    "Completed": false
  }
}

Each variant can use either a single fields/values section or its own columns array. Values entered in a variant are retained if the user switches to another option and then returns before closing the dialog.

1.8. Progress bars

Progress bars provide visible feedback while a FileMaker script or ACF function performs lengthy work. A progress window has a title, status message, progress indicator, and numeric handle.

The handle identifies the window in later update and close calls. Several progress windows can exist at the same time; they are independent and are stacked around the active FileMaker window.

Two display modes are available:

1.8. Progress bars in ACF functions

The ACF language provides three operations:

int handle = progress_open(title, message, maximum);
progress_update(handle, value, message);
progress_close(handle);

progress_open returns a numeric handle. progress_update and progress_close are statements and do not return values.

Example:

function ProcessRecords(int recordCount)
    int handle = progress_open(
        "Updating records",
        "Preparing...",
        recordCount
    );

    int i;
    for (i = 1, recordCount)
        // Perform work for record i here.
        progress_update(
            handle,
            i,
            format("Processing record %d of %d", i, recordCount)
        );
    end for

    progress_close(handle);
    return recordCount;
end

For work where the total cannot be calculated in advance:

int handle = progress_open("Import", "Connecting...", 100);
progress_update(handle, -1, "Receiving data...");

// Perform work with an unknown duration.

progress_update(handle, 80, "Finishing import...");
progress_close(handle);

The progress window remains responsive while the ACF function runs.

1.8. Progress bars in FileMaker calculations

Progress-bars

The corresponding external calculation functions are:

ACF_ProgressOpen ( title ; message ; maximum )
ACF_ProgressUpdate ( handle ; value ; message )
ACF_ProgressClose ( handle )

ACF_ProgressOpen returns the handle. The update and close functions return 1 when the handle was found and the operation succeeded.

A FileMaker script can control a progress window entirely through calculations:

Set Variable [ $progress ; Value: ACF_ProgressOpen ( "Export" ; "Preparing..." ; $recordCount ) ]

# Perform work and update $current in a loop.
Set Variable [ $updated ; Value: ACF_ProgressUpdate ( $progress ; $current ; "Exporting record " & $current ) ]

Set Variable [ $closed ; Value: ACF_ProgressClose ( $progress ) ]

The handle is not tied to the individual calculation call. It can be stored in a FileMaker variable, passed between scripts, or returned from an ACF function and used in later calls.

1.11. Progress script steps

FileMaker also registers these native plugin script steps:

A common pattern is to open the progress window with ACF_ProgressOpen in a Set Variable step, update it with ACF Progress Update inside a loop, and finish with ACF Progress Close.

The same handle can cross the boundary between ACF and FileMaker. For example, an ACF function can open a progress window and return its handle, after which a FileMaker script can update or close it. Likewise, a FileMaker calculation can open a window whose handle is passed into an ACF function.

1.12. Practical notes