Skip to content

Accessibility: Work in progress

Translations: Not Needed

Form

Form input component with input validation rules and validation states and feedback texts for each HLFormItem

Basic Form


Input Name
Input Age
Input Address
Vue
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

Input Text
Vue
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

+0

Input Age

Vue
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

Vue
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

Input number
Vue
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

Input Text
Vue
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

Input select
Vue
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

Vue
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

0
100
Vue
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

Select Date
Vue
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

HH:mm:ss
Vue
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

Random 1

Random 2

Vue
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

Vue
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

Hugo Behean

Perfect support dreamer

Koss Vyane

School teacher

Vue
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

Vue
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

Vue
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

Hugo Behean

Perfect support dreamer

Koss Vyane

School teacher

Vue
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

Click to upload

or drag and drop

Vue
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:


Input Name
Input Age
Input Address
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

NameTypeDefaultDescription
id *string | undefinedundefinedThe id of the element
disabledbooleanfalseWhether to disable the form
label-widthnumber | string | undefinedundefinedWidth 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
modelObject | undefinedundefinedForm data object
rulestype FormRules = Record<string, FormItemRule | Array<FormItemRule>> | undefined undefinedValidation rules for form items
show-feedbackbooleantrueWhether to show feedback in form items
show-labelbooleantrueWhether to show labels in form items
show-require-markbooleantrueWhether 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

NameTypeDefaultDescription
feedbackstringundefinedFeedback/hint text content
labelstringundefinedLabel of the form item
pathstringundefinedValidation path of the form item
requiredbooleanfalseWhether the form item is required
ruleFormItemRule | Array<FormItemRule>undefinedValidation rules for the form item
show-feedbackbooleanundefinedWhether to show feedback, overrides form's show-feedback
show-labelbooleanundefinedWhether to show label, overrides form's show-label
show-require-markbooleanundefinedWhether to show required mark, overrides form's show-require-mark
validation-status'success' | 'warning' | 'error'undefinedValidation status
tooltipObjectnulltooltip Object
showFeedbackTooltipbooleanundefinedWhether to show feedback tooltip
feedbackLineClampnumber1Lines to show without elipsis
feedbackTooltipPropsObjectnullProperties of the feedback tooltip
requireMarkPlacement'left' | 'right''right'Placement of the required mark
showRequireMarkbooleantrueWhether to show required mark, overrides form's show-require-mark

Slots

HLForm Slots

NameParametersDescription
default()The default content slot

HLFormItem Slots

NameParametersDescription
default()The default content slot
label()label content for the form item
feedback()feedback/hint text content below the form item

Methods

NameParametersReturnsDescription
getForm()FormInst | nullReturns 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()voidRestores form validation to initial state