visit
{
name: 'MyForm',
component: 'Form',
fields: [
{ name: 'name', component: 'TextField', label: 'Name' },
{ name: 'email', component: 'EmailField', label: 'Email' }
]
}
This query language also contains a construct for , which can be used to execute operations like
$add
, $multiply
, $filter
, $map
, etc... For example:{
$add: [ 1, 2 ]
}
Now that you have that background, let's take a look at an example where we extract the year from a user-provided date. Upon selecting a date with the date picker, you'll see that the
Year
field is populated:Let's step through this example. First, we construct a form with
date
and year
fields:{
component: "Form",
fields: [
{
name: "date",
component: "DateField",
label: "Date"
},
{
name: "year",
component: "IntegerField",
label: "Year"
}
]
}
Second, we listen for changes to the
date
value, extract the year and then set the value of the year
field:{
component: "Form",
fields: ...,
listeners: [
{
event: "fields.date.value",
actions: [
{
component: "Set",
name: "fields.year.value",
value: {
$year: {
$toDate: "{{fields.date.value}}"
}
}
}
]
}
]
}
The
$toDate
operator is used to convert the date value, which is in milliseconds, to a date object. The $year
operator is used to extract the year portion from the date. The Set
action is native to MSON and is used to set the value of the year
field.Pretty cool? Let's go a bit deeper...You can create custom actions, which can then be reused. Let's assume that we want to create an
app.GetYear
action that retrieves the year from a DateField value:compiler.registerComponent("app.GetYear", {
// Extend Set, a core MSON component, that sets a
// property on another component
component: "Set",
// Define the inputs to the custom action
schema: {
component: "Form",
fields: [
{
name: "date",
component: "DateField",
required: true
}
]
},
// Omitting the "name" here allows the value
// to be passed to the next action via
// "{{arguments}}"
//
// name: "",
// Use the template query to extract the year
// from the date
value: {
$year: {
$toDate: "{{date}}"
}
}
});
const form = compiler.newComponent({
component: "Form",
fields: ...,
listeners: [
{
event: "fields.date.value",
actions: [
// Extract the year and pass it to the next action
{
component: "app.GetYear",
date: "{{fields.date.value}}"
},
// Use the extracted year to set the year field
{
component: "Set",
name: "fields.year.value",
// {{arguments}} is the output of app.GetYear
value: "{{arguments}}"
}
]
}
]
});
Let's assume that we have a survey question and we want the user to be able to enter a free response when they select
Other
:We define the form and hide the
covidOther
text field by default:{
component: "Form",
fields: [
{
name: "covid",
component: "SelectField",
label: "My government's response to COVID-19 was...",
fullWidth: true,
options: [
{ label: "Good", value: "good" },
{ label: "Bad", value: "bad" },
{ label: "Other", value: "other" }
]
},
{
name: "covidOther",
component: "TextField",
label: "Please explain",
multiline: true,
hidden: true
}
]
}
If the user selects
Other
, we toggle the hidden
boolean property of the covidOther
field. The $ne
operator is shorthand for not equal.listeners: [
{
event: "fields.covid.value",
actions: [
{
component: "Set",
name: "fields.covidOther.hidden",
value: {
$ne: ["{{fields.covid.value}}", "other"]
}
}
]
}
]
eval()
- Components can be serialized using JSON.stringfy()
and stored practically anywhere. Moreover, components can be deserialized by dynamically compiling the result of JSON.parse()
. As a result, raw JS (in a string), including JS template literals, are not supported as deserializing such JS would require the use of eval()
or new Function()
, which would expose a and add significant performance issues.Also published at