Skip to content

V1 Migration

weili edited this page Apr 18, 2025 · 1 revision

v1.0.0-alpha.1 → v1.0.0-alpha.3

Structural changes

  • fields has been renamed as sections to cater to beyond form fields
  • fieldType has been renamed as uiType to cater to beyond form fields
  • sections can only render section uiType, whereas section can render other uiType
  • the old section field type ceases to exist, please do not use it as a generic HTML wrapper anymore
// old
{
	"name": "My Form",
	"id": "my-form",
	"fields": {
		"myField1": {
			"fieldType": "radio",
			//...
		},
		"myWrapper": {
			"fieldType": "section",
			"children": {
				"myField2": {
					"fieldType": "radio",
					//...
				},
			}
		}
	}
}

// new
{
	"name": "My Form",
	"id": "my-form",
	"sections": { // sections instead of fields
		"mySection": {
			"uiType": "section", // this must be section
			"children": {
				"myField1": {
					"uiType": "radio", // uiType instead of fieldType
					//...
				},
				"myWrapper": {
					"uiType": "div", // div instead of section
					"children": {
						"myField2": {
							"uiType": "radio",
							//...
						},
					}
				}
			}
		}
	}
}

Update of uiType values

  • Some ui types have been renamed:
    • text → text-field
    • email → email-field
    • numeric → numeric-field
    • date → date-field
    • time → time-field
    • contact → contact-field
// old
{
	"myTextField": {
		"uiType": "text",
		//...
	},
	"myEmailField": {
		"uiType": "email",
		//...
	},
	"myNumericField": {
		"uiType": "numeric",
		//...
	},
	"myDateField": {
		"uiType": "date",
		//...
	},
	"myTimeField": {
		"uiType": "time",
		//...
	},
	"myContactField": {
		"uiType": "contact",
		//...
	}
}

// new
{
	"myTextField": {
		"uiType": "text-field",
		//...
	},
	"myEmailField": {
		"uiType": "email-field",
		//...
	},
	"myNumericField": {
		"uiType": "numeric-field",
		//...
	},
	"myDateField": {
		"uiType": "date-field",
		//...
	},
	"myTimeField": {
		"uiType": "time-field",
		//...
	},
	"myContactField": {
		"uiType": "contact-field",
		//...
	}
}

mol-frontend-engine → web-frontend-engine v1.0.0-alpha.1

Removal of schema key and update fields as an object

  • schema key has been removed
  • fields key is moved to the top level
  • fields is changed from array to object
  • The key of each field is the id of the field
// old
{
	"name": "My Form",
	"id": "my-form",
	"schema": {
		"fields": [
			{
				"id": "field-id",
				//...
			}
		]
	}
}

// new
{
	"name": "My Form",
	"id": "my-form",
	"fields": {
		"field-id": {
			//...
		}
	}
}

validationMode and revalidationMode

  • New top-level keys introduced as part of react-hook-form
  • Optional but have drastic impact to validation behaviours, refer to storybook for more info
// new
{
	"id": "my-form",
	"validationMode": "onSubmit",
	"revalidationMode": "onChange",
	//...
}

fieldType and label

  • type key of each field has been renamed as fieldType
  • The values are now in kebab-case, please refer to the respective fields in the storybook for more info
  • title key has been renamed as label
// old
{
	//...
	{
		"type": "TEXT",
		"title": "Name",
		"id": "my-input",
		//...
	}
}
// new
{
	//...
	"my-input": {
		"fieldType": "text",
		"label": "Name",
		//...
	}
}

Validation schema

  • All validation rules are now key-value objects
  • Error message is optional and defined via errorMessage key
// old
{
	//...
	"validation": [
		"required",
		{ "email": "invalid email" },
		{ "min": [0, "my error message" ] }
	]
}

// new
{
	//...
	"validation": [
		{ "required": true },
		{ "email": true, "errorMessage": "invalid email" }
		{ "min": 0, "errorMessage": "my error message" }
	]
}

Prepopulation of values

  • Values can be prepopulated via JSON schema through the new defaultValues key
{
	//...
	"fields": {
		"textfield": {
			label: "Textfield",
			fieldType: "text",
		}
	},
	"defaultValues": {
		"textfield": "Default value",
	},
	//...
}

Alert

  • Updated fieldType
    • ALERTalert
  • Removed label key
  • Renamed alertType as type
// old
{
	"id": "alert",
	"title": "",
	"type": "ALERT",
	"alertType": "warning",
	"children": "Hello world"
}

// new
{
	//...
	"alert": {
		"fieldType": "alert",
		"type": "warning",
		"children": "Hello world"
	},
	//...
}

CheckboxGroup

  • Updated fieldType
    • CHECKBOXcheckbox
// old
{
	"id": "checkboxes",
	"title": "Fruits",
	"type": "CHECKBOX",
	"options": [
		{ "label": "Apple", "value": "Apple" },
		{ "label": "Berry", "value": "Berry" },
		{ "label": "Cherry", "value": "Cherry" }
	],
	"validation": ["required"]
}

// new
{
	//...
	"checkboxes": {
		"fieldType": "checkbox",
		"label": "Fruits",
		"options": [
			{ "label": "Apple", "value": "Apple" },
			{ "label": "Berry", "value": "Berry" },
			{ "label": "Cherry", "value": "Cherry" }
		],
		"validation": [{ "required": true }]
	},
	//...
}

ContactNumber

  • Updated fieldType
    • CONTACTNUMBERcontact
  • Renamed and moved allowInternationalNumbers into validation config under contactNumber
  • Removed errorMessage key, error messages are to be defined in the validation config
// old
{
	"id": "mobileNo",
	"title": "Mobile number",
	"type": "CONTACTNUMBER",
	"allowInternationalNumbers": true,
	"enableSearch": true,
	"validation": ["required"],
	"errorMessage": "Invalid mobile number. Try again."
}

// new
{
	//...
	"mobileNo": {
		"fieldType": "contact",
		"label": "Mobile Number",
		"enableSearch": true,
		"validation": [
			{
				"contactNumber": {
					"internationalNumber": true,
				},
				"errorMessage": "Invalid mobile number. Try again."
			},
		]
	},
	//...
}

DateInput

  • Updated fieldType
    • DATEdate
  • Renamed noFutureDate validation rule as notFuture
  • Removed errorMessage key, error messages are to be defined in the validation config
// old
{
	"id": "date",
	"title": "Date",
	"type": "DATE",
	"validation": ["required", "noFutureDate"],
	"errorMessage": "Invalid date. Try again.",
	"useCurrentDate": true,
}

// new
{
	//...
	"date": {
		"fieldType": "date",
		"label": "Date",
		"useCurrentDate": true,
		"validation": [
			{ "required": true },
			{ "notFuture": true, "errorMessage": "Invalid date. Try again.", }
		],
	},
	//...
}

Select

  • Updated fieldType
    • SELECTselect
// old
{
	"id": "fruits",
	"type": "SELECT",
	"title": "Fruits",
	"placeholder": "Select one",
	"options": [
		{ "label": "Apple", "value": "Apple" },
		{ "label": "Berry", "value": "Berry" },
		{ "label": "Cherry", "value": "Cherry" },
	],
	"validation": ["required"]
}

// new
{
	//...
	"fruits": {
		"fieldType": "select",
		"label": "Fruits",
		"options": [
			{ "label": "Apple", "value": "Apple" },
			{ "label": "Berry", "value": "Berry" },
			{ "label": "Cherry", "value": "Cherry" },
		],
		"validation": [{ "required": true }]
	},
	//...
}

SubmitButton

  • Updated fieldType
    • SUBMITsubmit
// old
{
	"id": "submit",
	"type": "SUBMIT",
	"title": "Submit",
	"className": "submit",
}

// new
{
	//...
	"submit": {
		"fieldType": "submit",
		"label": "Submit",
		"className": "submit",
	},
	//...
}

TextArea

  • Updated fieldType
    • TEXTAREAtextarea
// old
{
	"id": "textarea",
	"title": "Textarea",
	"type": "TEXTAREA",
	"resizable": true,
	"maxLength": 100,
	"rows": 4,
	"placeholder": "Required field",
	"validation": ["required"],
	"chipTexts": ["Lamp post", "Bus stop", "Foot path", "Void deck"],
	"chipPosition": "top",
}

// new
{
	//...
	"textarea": {
		"label": "Textarea",
		"fieldType": "textarea",
		"resizable": true,
		"maxLength": 100,
		"rows": 4,
		"placeholder": "Required field",
		"validation": [{ "required": true }],
		"chipTexts": ["Pill 1", "Pill 2", "Pill 3"],
		"chipPosition": "bottom"
	},
	//...
}

Text

  • Updated fieldType
    • TEXTBODYtext-body
  • Removed label key
  • children is changed from accepting ReactNode to string or string[] or other text field types
// old
{
	"id": "text",
	"className": "col",
	"title": "",
	"type": "TEXTBODY",
	"children": "Hello world"
}

// new
{
	//...
	"text": {
		"fieldType": "text-body",
		"className": "col",
		"children": "Hello world"
	},
	//...
}

Textfield (Text, email, number)

  • Updated fieldType
    • TEXTtext
    • NUMBERnumeric
    • EMAILemail
// old
{
	"id": "textfield",
	"title": "Textfield",
	"type": "TEXT",
	"placeholder": "Required field",
	"validation": ["required"]
}

// new
{
	//...
	"textfield": {
		"label": "Textfield",
		"fieldType": "text",
		"placeholder": "Required field",
		"validation": [{ "required": true }]
	},
	//...
}

TimePicker

  • Updated fieldType
    • TIMEtime
// old
{
	"id": "time",
	"title": "Time",
	"type": "TIME",
	"useCurrentTime": true,
	"validation": ["required"]
}

// new
{
	//...
	"time": {
		label: "Time",
		fieldType: "time",
		useCurrentTime: true,
		"validation": [{ "required": true }]
	},
	//...
}

Wrapper

  • Updated fieldType
    • DIVdiv
    • SPANspan
    • SECTIONsection
    • HEADERheader
    • FOOTERfooter
    • H1h1
    • H2h2
    • H3h3
    • H4h4
    • H5h5
    • H6h6
  • Removed label key
  • children is changed from array to object similiar to fields key
    • The key of each field is the id of the field
// old
{
	"id": "wrapper",
	"className": "col",
	"title": "",
	"type": "DIV",
	"children": [
		{
			"id": "textfield",
			"title": "Textfield",
			"type": "TEXT",
			"validation": ["required"],
		},
	],
}

// new
{
	//...
	"wrapper": {
		"fieldType": "div",
		"className": "col",
		"children": {
			"textfield": {
				"label": "Textfield",
				"fieldType": "text",
				"validation": [{ "required": true }]
			}
		},
	},
	//...
}