Data binding
Bind form field data to content.
Use data binding to create dynamic content in your forms. These functions help you bind form field data to Markdown elements and create conditional content blocks.
Inline data binding
Bind form field data directly within Markdown elements using the {$ field $}
syntax.
Example
import { Composer } from "formsmd";
const composer = new Composer({
id: "my-form"
});
composer.emailInput("email", {
question: "What's your email address?",
required: true
});
composer.slide({});
composer.h1("Welcome, {$ email $}!");
composer.p("Order confirmation will be sent to {$ email $}.");
Generates the following Markdown-like syntax:
#! id = my-form
email* = EmailInput(
| question = What's your email address?
)
---
# Welcome, {$ email $}!
Order confirmation will be sent to {$ email $}.


Block-level data binding
Create dynamic content blocks that respond to multiple form field values. Use the div()
function with the bind
parameter to specify which form fields to watch.
Function overview
The following is the overview of the function:
div(content: string, params?: object)
Parameters
bind
Array<string>
The names of the form fields to bind to the division (e.g., ["name", "email"]
). Any changes to these fields will trigger updates to the division content.
id
string
The id
attribute of the division element.
classNames
string[]
The CSS class names of the division element. See the available CSS utility classes.
attrs
Array<{ name: string, value: string }>
Other HTML attributes of the division element. Each attribute has a name
and value
property.
Example
Please note, the content inside the <div>
elements uses Nunjucks, so its entire list of features such as if-else statements, loops, filters, etc. are fully supported. Of course, Markdown is also supported within the content.
composer.numberInput("price", {
question: "Price",
required: true,
unitEnd: "$",
subfield: true,
min: 1
});
composer.numberInput("quantity", {
question: "Quantity",
required: true,
subfield: true,
min: 1
});
composer.div(`
{% if price and quantity -%}
Total: \${{ price }} × {{ quantity }} = \${{ price * quantity }}
{% else -%}
Total: Set price and quantity
{% endif %}
`, {
classNames: ["fs-lead", "col-8"],
bind: ["price", "quantity"]
});
Generates the following Markdown-like syntax:
price* = NumberInput(
| question = Price
| subfield
| min = 1
| unitend = $
)
quantity* = NumberInput(
| question = Quantity
| subfield
| min = 1
)
::: [.fs-lead .col-8 {$ price quantity $}]
{% if price and quantity -%}
Total: ${{ price }} × {{ quantity }} = ${{ price * quantity }}
{% else -%}
Total: Set price and quantity
{% endif %}
:::

Group together inputs and content using <div>
<div>
Use divStart()
and divEnd()
functions to create content groups with shared data bindings or styling.
Function overview
divStart(params?: object)
divEnd()
The parameters for divStart()
are the same as the div()
function.
Example
// Start a new <div>
composer.divStart({
classNames: ["col-6"]
});
composer.p("Contact information:");
composer.textInput("name", {
question: "Full name",
required: true
});
composer.emailInput("email", {
question: "Email address",
required: true
});
// End the <div>
composer.divEnd();
Generates the following Markdown-like syntax:
::: [.col-6]
Contact information:
name* = TextInput(
| question = Full name
)
email* = EmailInput(
| question = Email address
)
:::
Last updated
Was this helpful?