Forge now supports bi-directional parameter passing using a single, unambiguous
Parameter object. The same structure drives all of the following flows:
- Parent → child (pre-populate the child window / dialog)
- Request decoration (query / path parameters before a fetch)
- Child → parent (return values on
commit()) - Cross-data-source writes inside the same window
| field | required | description |
|---|---|---|
| direction | no – default in |
in (before open / fetch) – out (on commit) – both |
| from | yes | Origin store – syntax [dataSource]:store.Leave dataSource blank to use this window’s default DS. Stores: form, input, selection, filter, metrics, query, path, output (payload at commit). |
| to | yes | Destination store – same syntax as from. caller: prefix writes to the opener’s DS (only valid when direction: out). |
| name | yes | Selector on the destination side. |
| location | no | Selector on the origin side. If omitted it defaults to the value of name. |
Shorthands
• :form, :selection, … – omit the dataSource to mean this window’s default DS.
• :query, :path – aliases for :input.query / :input.path.
Automatic direction inference
• Omitted ⇒ in, unless from uses :output or to uses caller: – then default is out.
- from: :selection
to: :form
name: customerId # dest selector
location: customerId # source selector (identical ⇒ could omit)- from: :form
to: :query # expands → :input.query
name: statusQuery # dest key in ?statusQuery=
location: status # read form.statusIf you leave the data-source part blank (e.g. :form, :query), the
runtime substitutes the default dataSourceRef of the context that
executes the parameter. That means:
- When the parent opens a child window the inbound parameter
to: :formwrites to the child’s default DS. - Inside a dialog commit an outbound
to: caller:formtargets the opener, while simplyto: :formwould target the dialog’s own form.
Constant value – from: const, value in location.
- from: const
location: "/projects/reports"
to: :filter
name: uriSpread entire object – name: ... merges every property from the
source object into the target store.
Array wrapper – name: []ids always stores [value] so the caller
receives an array even when a single item was selected.
- from: :output # payload.email
to: caller:form
name: customerEmail # write caller.form.customerEmail
location: email # read payload.email
direction: out # could be omitted – inferred- direction: both
from: :form
to: audit:metrics
name: status
location: statusCaller metadata:
on:
- event: onClick
handler: window.openDialog
args:
- pickCustomer # id (pos 0)
- "Pick a customer" # title (pos 1)
- awaitResult: true # options object (pos 2)
parameters:
- from: :output
to: :form
name: customerId
location: id
direction: out # inferred because from=:outputDialog side (sends full form):
on:
- event: onClick
handler: dialog.commit # publishes form as payloadThe runtime writes payload.id to caller.form.customerId and resolves the
Promise returned by await window.openDialog() with the full payload.
While the examples above declare the parameter mapping in metadata, the exact same structure can be supplied when a component calls the imperative API directly:
// Inside a React event handler
const execArgs = [
'pickFile', // dialog id (pos 0)
'Pick a file', // title (pos 1)
{ // options (pos 2)
awaitResult: true,
parameters: [
{ from: ':output', to: 'caller:form', name: 'uri' },
],
},
];
const payload = await context.handlers.window.openDialog({
execution: { args: execArgs },
});
// `payload` is whatever the dialog passes to dialog.commit(payload)
// – in this case we expect an object like { uri: 'file.txt' }.The runtime merges the parameters array from the options object with
those that might have been supplied on execution.parameters, so both
styles inter-operate.
When you want each invocation to open a brand new window instance (instead of
focusing the existing one), pass newInstance: true in the options. To display
an incrementing title like chat <N+1>, also include autoIndexTitle: true.
on:
- event: onClick
handler: window.open
args:
- chat # window id / key
- chat # base title
- '' # optional data
- true # open in tab
- newInstance: true
autoIndexTitle: trueThis results in titles chat <1>, chat <2>, ... as users open multiple
instances from the navigation bar or actions.
A shim converts legacy Parameter rows to the new shape:
| legacy field | conversion |
|---|---|
in / kind |
populates from |
to / kind |
populates to |
location |
copied to location; also to name if missing |
output: true |
sets direction: out & from: :output |
scope |
appended to store part (dataSource:scope) |
kind: query/path |
converts to to: :input.query / :input.path |
Thus existing projects continue to run unmodified while new metadata can adopt the clearer five-field syntax immediately.