Form
Form input component with input validation rules and validation states and feedback texts for each HLFormItem
Basic Form
html
<template>
<HLForm :model="basicForm" style="width: 400px" size="lg">
<HLFormItem label="Name" path="name">
<HLInput id="name" v-model:model-value="basicForm.name" placeholder="Input Name" />
</HLFormItem>
<HLFormItem label="Age" path="age">
<HLInputNumber id="age" v-model:value="basicForm.age" placeholder="Input Age" />
</HLFormItem>
<HLFormItem label="Address" path="address">
<HLInput id="address" v-model:model-value="basicForm.address" placeholder="Input Address" type="textarea" />
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLInput, HLInputNumber } from '@platform-ui/highrise'
import { ref } from 'vue'
const basicForm = ref({
name: '',
age: null,
address: '',
})
</script>
Input Text
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-text-item" label="Name" path="text" feedback="This is a hint text to help user.">
<HLInput id="all-inputs-text" v-model:model-value="formValue.text" placeholder="Input Text" />
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLInput } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
text: '',
})
</script>
Input Tag
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-tags-item" label="Input Tags" path="tags" feedback="This is a feedback">
<HLInputTag id="all-inputs-tags" v-model:value="formValue.tags" placeholder="Input Age" />
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLInputTag } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
tags: [],
})
</script>
Input Phone
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-phone-item" label="Input Phone" path="phone" feedback="This is a feedback">
<HLInputPhone id="all-inputs-phone" v-model:value="formValue.phone" placeholder="Input phone" />
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLInputPhone } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
phone: '9876543210',
})
</script>
Input Number
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-number-item" label="Input Number" path="number">
<HLInputNumber id="all-inputs-number" v-model:value="formValue.number" placeholder="Input number" />
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLInputNumber } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
number: null,
})
</script>
Input Text Area
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-textarea-item" label="textArea" path="textArea" feedback="This is a feedback">
<HLInput id="all-inputs-textarea" v-model:model-value="formValue.textArea" placeholder="Input Text" type="textarea" />
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLInput } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
text: '',
})
</script>
Select
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-select-item" label="Select" path="selectValue" feedback="This is a feedback">
<HLSelect id="all-inputs-select" v-model:value="formValue.selectValue" placeholder="Input select" :options="simpleSelectOptions" />
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLSelect } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
selectValue: null,
})
const simpleSelectOptions = ref([
{ label: 'Option 1', value: 'option-1' },
{ label: 'Option 2', value: 'option-2' },
{ label: 'Option 3', value: 'option-3' },
])
</script>
OTP
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-otp-item" label="OTP" path="otp" feedback="This is a feedback">
<HLInputOtp id="all-inputs-otp" v-model:value="formValue.otp" placeholder="0" @on-complete="completeOTPHandler" />
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLInputOtp } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
otp: '',
})
const completeOTPHandler = (value: { otp: string; state: 'completed' }) => {
console.log('OTP completed:', value.otp)
}
</script>
Slider
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-slider-item" label="Slider" path="sliderValue" feedback="This is a feedback">
<HLInputSlider id="all-inputs-slider" type="single" v-model:value="formValue.sliderValue" placeholder="0" size="xs" />
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLInputSlider } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
sliderValue: 0,
})
</script>
Date Picker
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="date-picker" label="Date Picker" path="datePicker" feedback="This is a feedback">
<HLDatePicker id="all-inputs-date-picker" v-model:value="formValue.datePicker" placeholder="Select Date" />
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLDatePicker } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
datePicker: null,
})
</script>
Time Picker
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="time-picker-item" label="Time Picker" path="time" feedback="This is a feedback">
<HLTimePicker id="all-inputs-time-picker" v-model:value="formValue.time" placeholder="Select Time" />
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLTimePicker } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
time: null,
})
</script>
Toggle Group
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-toggle-group-item" label="Toggle Group" path="toggleGroup">
<HLToggleGroup id="all-inputs-toggle-group" placeholder="toggle" group-label="">
<HLSpace id="all-inputs-toggle-group-space">
<HLToggle
id="all-inputs-toggle-1"
v-model:value="formValue.toggleGroup[0]"
:checked-value="true"
:unchecked-value="false"
label="Random 1"
/>
<HLToggle
id="all-inputs-toggle-2"
v-model:value="formValue.toggleGroup[1]"
:checked-value="true"
:unchecked-value="false"
label="Random 2"
/>
</HLSpace>
</HLToggleGroup>
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLToggleGroup, HLToggle } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
toggleGroup: [true, true],
})
</script>
Radio Group
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-radio-group-item" label="Radio Group" path="radioGroup">
<HLRadioGroup id="all-inputs-radio-group" v-model:value="formValue.radioGroup" placeholder="radio">
<HLSpace id="all-inputs-radio-group-space">
<HLRadio id="all-inputs-radio-1" value="radio-1"> Steve Smith </HLRadio>
<HLRadio id="all-inputs-radio-2" value="radio-2"> Virat Kohli </HLRadio>
</HLSpace>
</HLRadioGroup>
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLRadioGroup, HLRadio } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
radioGroup: null,
})
</script>
Radio Card Group
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-radio-card-group-item" label="Radio Card Group" path="radioCardGroup">
<HLRadioGroup id="all-inputs-radio-card-group" v-model:value="formValue.radioCardGroup" placeholder="radio">
<HLSpace id="all-inputs-radio-card-space">
<HLRadioCard id="all-inputs-radio-card-1" value="radiocard-1" title="Hugo Behean" description="Perfect support dreamer" />
<HLRadioCard id="all-inputs-radio-card-2" value="radiocard-2" title="Koss Vyane" description="School teacher" />
</HLSpace>
</HLRadioGroup>
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLRadioGroup, HLRadioCard } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
radioCardGroup: null,
})
</script>
Color Picker
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-color-picker-item" label="Color Picker" path="color" feedback="This is a feedback">
<HLColorPicker id="all-inputs-color-picker" v-model:value="formValue.color" type="picker" placeholder="Select Color" size="xs" />
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLColorPicker } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
color: 'red',
})
</script>
Checkbox Group
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-checkbox-group-item" label="Checkbox Group" path="checkboxGroup">
<HLCheckboxGroup id="all-inputs-checkbox-group" v-model:value="formValue.checkboxGroup">
<HLSpace id="all-inputs-checkbox-group-space">
<HLCheckbox id="all-inputs-checkbox-1" value="facebook">Facebook</HLCheckbox>
<HLCheckbox id="all-inputs-checkbox-2" value="twitter">Twitter</HLCheckbox>
<HLCheckbox id="all-inputs-checkbox-3" value="instagram">Instagram</HLCheckbox>
</HLSpace>
</HLCheckboxGroup>
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLCheckboxGroup, HLCheckbox } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
checkboxGroup: ['facebook'],
})
</script>
Checkbox Card Group
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-checkbox-card-group-item" label="Checkbox Card Group" path="checkboxCardGroup">
<HLCheckboxGroup id="all-inputs-checkbox-card-group" v-model:value="formValue.checkboxCardGroup">
<HLSpace id="all-inputs-checkbox-card-space">
<HLCheckboxCard
id="all-inputs-checkbox-card-1"
value="checkboxcard-1"
title="Hugo Behean"
description="Perfect support dreamer"
/>
<HLCheckboxCard id="all-inputs-checkbox-card-2" value="checkboxcard-2" title="Koss Vyane" description="School teacher" />
</HLSpace>
</HLCheckboxGroup>
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLCheckboxGroup, HLCheckboxCard } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
checkboxCardGroup: null,
})
</script>
Upload
html
<template>
<HLForm id="all-inputs-form" ref="formRef" :model="formValue" style="width: 400px">
<HLFormItem id="all-inputs-upload-item" label="Upload" path="upload" feedback="This is a feedback">
<HLUpload id="all-inputs-upload" v-model:file-list="formValue.upload" placeholder="Upload" />
</HLFormItem>
</HLForm>
</template>
<script setup lang="ts">
import { HLForm, HLFormItem, HLUpload } from '@platform-ui/highrise'
import { ref } from 'vue'
const formRef = ref()
const formValue = ref({
upload: [],
})
</script>
Form validation
The HLForm component provides flexible validation capabilities through its rules
prop. While you can implement validation using various approaches, we strongly recommend using Joi as the validation library.
Here's how to implement form validation using our recommended approach with Joi:
html
<HLForm ref="formRefValidation" :model="formValueValidation" :rules="rulesValidation" style="width: 400px">
<HLFormItem label="Name" path="name" required :validation-status="validationStatus.name" :feedback="validationFeedback.name">
<HLInput id="name" v-model:model-value="formValueValidation.name" placeholder="Input Name" />
</HLFormItem>
<HLFormItem label="Age" path="age" required :validation-status="validationStatus.age" :feedback="validationFeedback.age">
<HLInputNumber id="age" v-model:value="formValueValidation.age" placeholder="Input Age" />
</HLFormItem>
<HLFormItem label="Address" path="address" required :validation-status="validationStatus.address" :feedback="validationFeedback.address">
<HLInput id="address" v-model:model-value="formValueValidation.address" placeholder="Input Address" type="textarea" />
</HLFormItem>
<HLFormItem>
<HLSpace>
<HLButton id="validate" @click="handleValidateClick">Validate</HLButton>
<HLButton id="restore" @click="handleRestore" type="default">Reset</HLButton>
</HLSpace>
</HLFormItem>
</HLForm>
ts
import { FormValidationError } from 'naive-ui'
import { ref } from 'vue'
import Joi from 'joi'
// Form state
const formRefValidation = ref()
const formValueValidation = ref({
name: '',
age: null,
address: '',
})
// Validation state
const validationStatus = ref({
name: undefined as 'error' | 'warning' | undefined,
age: undefined as 'error' | 'warning' | undefined,
address: undefined as 'error' | 'warning' | undefined,
})
const validationFeedback = ref({
name: '',
age: '',
address: '',
})
// Joi validation schema
const validationSchema = Joi.object({
name: Joi.string().required().min(2).max(50).messages({
'string.empty': 'Name is required',
'string.min': 'Name should be at least 2 characters',
'string.max': 'Name should be at most 50 characters',
'any.required': 'Name is required',
}),
age: Joi.number().required().min(18).max(100).messages({
'number.base': 'Age is required',
'number.min': 'Age should be at least 18',
'number.max': 'Age should be at most 100',
'any.required': 'Age is required',
}),
address: Joi.string().required().min(10).max(200).messages({
'string.empty': 'Address is required',
'string.min': 'Address should be at least 10 characters',
'string.max': 'Address should be at most 200 characters',
'any.required': 'Address is required',
}),
})
// Validator function
const createValidator = (field: keyof typeof formValueValidation.value) => {
return async (rule: any, value: any) => {
const resultSchema = validationSchema.extract(field)
const result = resultSchema.validate(value)
if (result.error) {
const error = result.error.details[0]
// Check if the error is for empty/required field
if (error.type === 'string.empty' || error.type === 'any.required' || error.type === 'number.base') {
validationStatus.value[field] = 'error'
validationFeedback.value[field] = error.message
throw new Error(error.message)
} else {
// For other validation cases (min/max length, age range), return warning
validationStatus.value[field] = 'warning'
validationFeedback.value[field] = error.message
return {
status: 'warning',
message: error.message,
}
}
}
// Clear validation status and feedback if valid
validationStatus.value[field] = undefined
validationFeedback.value[field] = ''
}
}
// Form validation rules
const rulesValidation = {
name: [{ validator: createValidator('name'), trigger: ['input', 'blur'] }],
age: [{ validator: createValidator('age'), trigger: ['input', 'blur'] }],
address: [{ validator: createValidator('address'), trigger: ['input', 'blur'] }],
}
// Validation handler
async function handleValidateClick(e: MouseEvent) {
e.preventDefault()
try {
await formRefValidation.value?.validate((errors: any) => {
if (!errors) {
console.log('Valid form:', formValueValidation.value)
// Clear all validation statuses and feedback on success
Object.keys(validationStatus.value).forEach(key => {
const field = key as keyof typeof validationStatus.value
validationStatus.value[field] = undefined
validationFeedback.value[field] = ''
})
} else {
console.log('Validation results:', errors)
}
})
} catch (error) {
console.log('Validation failed:', error)
}
}
const handleRestore = () => {
formRefValidation.value?.restoreValidation()
// Reset form values
Object.keys(formValueValidation.value).forEach(key => {
formValueValidation.value[key as keyof typeof formValueValidation.value] = key === 'age' ? null : ''
})
// Clear validation states and feedback
Object.keys(validationStatus.value).forEach(key => {
const field = key as keyof typeof validationStatus.value
validationStatus.value[field] = undefined
validationFeedback.value[field] = ''
})
}
Imports
ts
import { HLForm, HLFormItem, HLInput } from '@platform-ui/highrise'
import { ref } from 'vue'
ts
import { HLForm, HLFormItem, HLInput } from '@platform-ui/highrise'
import { ref } from 'vue'
import Joi from 'joi'
Props
HLForm Props
Name | Type | Default | Description |
---|---|---|---|
id * | string | undefined | undefined | The id of the element |
disabled | boolean | false | Whether to disable the form |
label-width | number | string | undefined | undefined | Width of all form item labels in the form |
label-align | 'left' | 'right' | 'right' | Alignment of all form item labels in the form |
label-placement | 'left' | 'top' | 'left' | Position of all form item labels in the form |
model | Object | undefined | undefined | Form data object |
rules | type FormRules = Record<string, FormItemRule | Array<FormItemRule>> | undefined | undefined | Validation rules for form items |
show-feedback | boolean | true | Whether to show feedback in form items |
show-label | boolean | true | Whether to show labels in form items |
show-require-mark | boolean | true | Whether to show required mark on form items |
size | 'sm' | 'md' | 'lg' | 'medium' | Size of form items |
FormItemRule Interface
ts
interface FormItemRule {
required?: boolean
validator?: (rule: FormItemRule, value: any) => boolean | Error | Promise<void>
trigger?: Array<'input' | 'blur' | 'change'> | 'input' | 'blur' | 'change'
message?: string
type?: 'string' | 'number' | 'array' | 'object' | 'email'
min?: number // For string length, array length or number value
max?: number // For string length, array length or number value
pattern?: RegExp
}
FormItemTooltipProps Interface
ts
interface FormItemTooltipProps {
placement?:
| 'top'
| 'top-start'
| 'top-end'
| 'right'
| 'right-start'
| 'right-end'
| 'bottom'
| 'bottom-start'
| 'bottom-end'
| 'left'
| 'left-start'
| 'left-end'
trigger?: 'hover' | 'click' | 'focus' | 'manual'
width?: string | number
maxWidth?: string | number
showArrow?: boolean
delay?: number
duration?: number
disabled?: boolean
zIndex?: number
}
FormItemRule Interface
ts
interface FormItemRule {
required?: boolean
validator?: (rule: FormItemRule, value: any) => boolean | Error | Promise<void>
trigger?: Array<'input' | 'blur' | 'change'> | 'input' | 'blur' | 'change'
message?: string
type?: 'string' | 'number' | 'array' | 'object' | 'email'
min?: number // For string length, array length or number value
max?: number // For string length, array length or number value
pattern?: RegExp
}
FormItemTooltipProps Interface
ts
interface FormItemTooltipProps {
tooltipContent: string
placement?:
| 'top'
| 'top-start'
| 'top-end'
| 'right'
| 'right-start'
| 'right-end'
| 'bottom'
| 'bottom-start'
| 'bottom-end'
| 'left'
| 'left-start'
| 'left-end'
trigger?: 'hover' | 'click' | 'focus' | 'manual'
width?: string | number
maxWidth?: string | number
showArrow?: boolean
delay?: number
duration?: number
disabled?: boolean
zIndex?: number
}
HLFormItem Props
Name | Type | Default | Description |
---|---|---|---|
feedback | string | undefined | Feedback/hint text content |
label | string | undefined | Label of the form item |
path | string | undefined | Validation path of the form item |
required | boolean | false | Whether the form item is required |
rule | FormItemRule | Array<FormItemRule> | undefined | Validation rules for the form item |
show-feedback | boolean | undefined | Whether to show feedback, overrides form's show-feedback |
show-label | boolean | undefined | Whether to show label, overrides form's show-label |
show-require-mark | boolean | undefined | Whether to show required mark, overrides form's show-require-mark |
validation-status | 'success' | 'warning' | 'error' | undefined | Validation status |
tooltip | Object | null | tooltip Object |
showFeedbackTooltip | boolean | undefined | Whether to show feedback tooltip |
feedbackLineClamp | number | 1 | Lines to show without elipsis |
feedbackTooltipProps | Object | null | Properties of the feedback tooltip |
requireMarkPlacement | 'left' | 'right' | 'right' | Placement of the required mark |
showRequireMark | boolean | true | Whether to show required mark, overrides form's show-require-mark |
Slots
HLForm Slots
Name | Parameters | Description |
---|---|---|
default | () | The default content slot |
HLFormItem Slots
Name | Parameters | Description |
---|---|---|
default | () | The default content slot |
label | () | label content for the form item |
feedback | () | feedback/hint text content below the form item |
Methods
Name | Parameters | Returns | Description |
---|---|---|---|
getForm | () | FormInst | null | Returns the form instance |
validate | (callback?: (errors?: Array<FormValidationError>) => void) => Promise<void> | Promise<void> | Validates all form items. Returns a promise that resolves when validation is complete |
restoreValidation | () | void | Restores form validation to initial state |