A single-line text field. Use for free-text answers where the user types a value directly.
Read Form Rules before using this component — keys, labels, required fields, expressions, visibility, and validation all follow shared conventions.
type: "email")type: "password")Instead of input, use… |
For… |
|---|---|
customphonenumber |
Phone numbers — never input with type: "tel" |
customcurrencyformatinput |
Currency / monetary amounts — never input with type: "number" |
customidinput |
National IDs and document numbers |
number |
Plain numeric inputs |
textarea |
Multi-line text |
| Prop | Type | Required? | Description |
|---|---|---|---|
label |
string |
required | Visible label. Title Case for nouns ("First Name"), Sentence case for questions ("What is your occupation?"). Must be unique across the form. |
required |
boolean |
required | Always false. The expression controls the runtime value — never set this to true directly. |
defaultRequired |
boolean |
required | true for required fields, false for optional ones. This is the value the expression reads. |
type |
string |
optional | Input mode. One of: text (default), email, password, number, tel. |
placeholder |
string |
optional | Ghost text shown inside the field before the user types. |
tooltip |
string |
optional | Short help text shown as an icon tooltip next to the label. |
hint |
string |
optional | Subtle help text rendered below the field, always visible. |
readonly |
boolean |
optional | Prevents editing. Use expressions["props.readonly"] to toggle dynamically. Do not use disabled. |
hideField |
boolean |
optional | Hides the field and excludes its value from submission. Use expressions["props.hideField"] to toggle. Do not use hide directly. |
maxLength |
number |
optional | Maximum character count. Requires a validation.messages.maxLength entry. |
minLength |
number |
optional | Minimum character count. Requires a validation.messages.minLength entry. |
pattern |
string |
optional | Regex the value must match. Requires a validation.messages.pattern entry. Write the raw regex string — no / delimiters. |
Every input field must include this exact expression, regardless of whether the field is required or optional. Never omit it, never change it.
"expressions": {
"props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
}
The expression reads defaultRequired and automatically becomes false when the field is hidden — preventing hidden fields from blocking form submission.
defaultRequired: true.defaultRequired: false.{
"key": "FIRST_NAME",
"type": "input",
"props": {
"label": "First Name",
"required": false,
"defaultRequired": true
},
"expressions": {
"props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
},
"validation": {
"messages": {
"required": "First Name is required."
}
}
}
defaultRequired: false makes the field optional. The pattern prop adds format validation — a matching validation.messages.pattern entry is required whenever pattern is set.
{
"key": "WEBSITE",
"type": "input",
"props": {
"label": "Website",
"required": false,
"defaultRequired": false,
"placeholder": "https://example.com",
"pattern": "^https?://.+"
},
"expressions": {
"props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
},
"validation": {
"messages": {
"required": "Website is required.",
"pattern": "Please enter a valid URL starting with http:// or https://"
}
}
}
{
"key": "EMAIL_ADDRESS",
"type": "input",
"props": {
"label": "Email Address",
"required": false,
"defaultRequired": true,
"type": "email"
},
"expressions": {
"props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
},
"validation": {
"messages": {
"required": "Email Address is required."
}
}
}
key is UPPER_SNAKE_CASE and unique across the entire formprops.label is present, unique, and correctly casedsections > formly-group > block > inputrequired: false is set (never true)defaultRequired is set (true or false)expressions["props.required"] is present with the exact required expressionvalidation.messages.required is presentvalidation.messages has an entry for every constrained prop (pattern, maxLength, minLength)type is one of the allowed values — not inventedinput for phone numbers, currency, IDs, or multi-line text (see "When NOT to use")