Formulario
LhForm y LhFormItem proporcionan enlace de modelo, validación de obligatorios y visualización de errores de campo.
Uso básico
Uso básico
vue
<script setup lang="ts">
import { reactive, ref } from 'vue'
import { LhForm, LhFormItem, LhInput, LhButton, LhMessage } from '@lh-ui/vue3'
const formRef = ref()
const formModel = reactive({
name: '',
email: '',
})
const formRules = {
name: [{ required: true, message: 'Introduce el nombre' }],
email: [{ required: true, message: 'Introduce el correo electrónico' }],
}
async function submitForm() {
const valid = await formRef.value.validate()
if (valid) {
LhMessage.success('Envío correcto')
console.log('Envío correcto', formModel)
}
}
function resetForm() {
formRef.value?.resetFields()
}
</script>
<template>
<LhForm ref="formRef" :model="formModel" :rules="formRules" label-width="80px">
<LhFormItem prop="name" label="Nombre" required>
<LhInput v-model="formModel.name" placeholder="Introduce el nombre" />
</LhFormItem>
<LhFormItem prop="email" label="Correo electrónico" required>
<LhInput v-model="formModel.email" placeholder="Introduce el correo electrónico" />
</LhFormItem>
<LhFormItem>
<LhButton type="primary" @click="submitForm">Enviar</LhButton>
<LhButton plain @click="resetForm" style="margin-left: 8px">Restablecer</LhButton>
</LhFormItem>
</LhForm>
</template>vue
<script>
import { LhForm, LhFormItem, LhInput, LhButton, LhMessage } from '@lh-ui/vue3'
export default {
components: { LhForm, LhFormItem, LhInput, LhButton },
data() {
return {
formModel: { name: '', email: '' },
formRules: {
name: [{ required: true, message: 'Introduce el nombre' }],
email: [{ required: true, message: 'Introduce el correo electrónico' }],
},
}
},
methods: {
async submitForm() {
const valid = await this.$refs.formRef.validate()
if (valid) {
LhMessage.success('Envío correcto')
console.log('Envío correcto', this.formModel)
}
},
resetForm() { this.$refs.formRef?.resetFields() },
},
}
</script>
<template>
<LhForm ref="formRef" :model="formModel" :rules="formRules" label-width="80px">
<LhFormItem prop="name" label="Nombre" required>
<LhInput v-model="formModel.name" placeholder="Introduce el nombre" />
</LhFormItem>
<LhFormItem prop="email" label="Correo electrónico" required>
<LhInput v-model="formModel.email" placeholder="Introduce el correo electrónico" />
</LhFormItem>
<LhFormItem>
<LhButton type="primary" @click="submitForm">Enviar</LhButton>
<LhButton plain @click="resetForm">Restablecer</LhButton>
</LhFormItem>
</LhForm>
</template>Tema personalizado
El formulario puede aplicar una paleta temática personalizada.
Formulario con tema porcelana azul y blanco
vue
<script setup lang="ts">
import { reactive } from 'vue'
import { LhConfigProvider, LhForm, LhFormItem, LhInput, LhButton } from '@lh-ui/vue3'
const themeForm = reactive({ name: '' })
const cerblueTheme = {
'primary-color': '#2B4C7C',
'primary-color-hover': '#3D649E',
'primary-color-bg': '#E8EDF3',
}
</script>
<template>
<!-- Tema porcelana azul y blanco -->
<LhConfigProvider :theme-vars="cerblueTheme">
<LhForm :model="themeForm" label-width="80px">
<LhFormItem label="Nombre">
<LhInput v-model="themeForm.name" />
</LhFormItem>
<LhFormItem>
<LhButton type="primary">Enviar</LhButton>
</LhFormItem>
</LhForm>
</LhConfigProvider>
</template>vue
<script>
import { LhConfigProvider, LhForm, LhFormItem, LhInput, LhButton } from '@lh-ui/vue3'
export default {
data() {
return {
themeForm: { name: '' },
cerblueTheme: {
'primary-color': '#2B4C7C',
'primary-color-hover': '#3D649E',
'primary-color-bg': '#E8EDF3',
},
}
},
}
</script>
<template>
<!-- Tema porcelana azul y blanco -->
<LhConfigProvider :theme-vars="cerblueTheme">
<LhForm :model="themeForm" label-width="80px">
<LhFormItem label="Nombre">
<LhInput v-model="themeForm.name" />
</LhFormItem>
<LhFormItem>
<LhButton type="primary">Enviar</LhButton>
</LhFormItem>
</LhForm>
</LhConfigProvider>
</template>Internacionalización
Formulario internacionalizado
vue
<script setup lang="ts">
import { reactive, ref } from 'vue'
import { LhConfigProvider, LhForm, LhFormItem, LhInput, LhButton } from '@lh-ui/vue3'
import { zhCN } from '@lh-ui/vue3'
import { enUS } from '@lh-ui/vue3'
const locale = ref('zh-CN')
const formModel = reactive({ name: '' })
</script>
<template>
<!-- Configuración de internacionalización -->
<LhConfigProvider :locale="locale === 'zh-CN' ? zhCN : enUS">
<LhForm :model="formModel" label-width="80px">
<LhFormItem :label="locale === 'zh-CN' ? '姓名' : 'Name'">
<LhInput v-model="formModel.name" :placeholder="locale === 'zh-CN' ? '请输入姓名' : 'Enter name'" />
</LhFormItem>
<LhFormItem>
<LhButton type="primary">{{ locale === 'zh-CN' ? '提交' : 'Submit' }}</LhButton>
</LhFormItem>
</LhForm>
</LhConfigProvider>
</template>vue
<script>
import { LhConfigProvider, LhForm, LhFormItem, LhInput, LhButton } from '@lh-ui/vue3'
import { zhCN } from '@lh-ui/vue3'
import { enUS } from '@lh-ui/vue3'
export default {
data() {
return {
locale: 'zh-CN',
formModel: { name: '' },
zhCN: zhCN,
enUS: enUS,
}
},
}
</script>
<template>
<!-- Configuración de internacionalización -->
<LhConfigProvider :locale="locale === 'zh-CN' ? zhCN : enUS">
<LhForm :model="formModel" label-width="80px">
<LhFormItem :label="locale === 'zh-CN' ? '姓名' : 'Name'">
<LhInput v-model="formModel.name" :placeholder="locale === 'zh-CN' ? '请输入姓名' : 'Enter name'" />
</LhFormItem>
<LhFormItem>
<LhButton type="primary">{{ locale === 'zh-CN' ? '提交' : 'Submit' }}</LhButton>
</LhFormItem>
</LhForm>
</LhConfigProvider>
</template>Posición de las etiquetas y disposición en línea
label-position alterna la alineación de las etiquetas (left / right / top); inline dispone los elementos del formulario en horizontal.
label-position / inline
vue
<script setup lang="ts">
import { reactive } from 'vue'
const fpModel = reactive({ name: '', city: '' })
</script>
<template>
<LhForm :model="fpModel" label-position="top" inline>
<LhFormItem prop="name" label="Nombre" required>
<LhInput v-model="fpModel.name" />
</LhFormItem>
<LhFormItem prop="city" label="Ciudad">
<LhInput v-model="fpModel.city" />
</LhFormItem>
</LhForm>
</template>vue
<script>
export default {
data() {
return {
fpModel: { name: '', city: '' },
}
},
}
</script>
<template>
<LhForm :model="fpModel" label-position="top" inline>
<LhFormItem prop="name" label="Nombre" required>
<LhInput v-model="fpModel.name" />
</LhFormItem>
<LhFormItem prop="city" label="Ciudad">
<LhInput v-model="fpModel.city" />
</LhFormItem>
</LhForm>
</template>LhForm Props
| Prop | Descripción | Tipo | Predeterminado |
|---|---|---|---|
| model | Objeto de datos del formulario | { [x: string]: unknown; } | — |
| rules | Reglas de validación de campos | { [x: string]: LhFormRule[]; } | — |
| labelPosition | Posición de la etiqueta | "left" | "right" | "top" | 'right' |
| labelWidth | Anchura de la etiqueta | string | number | — |
| inline | Si se usa disposición en línea | boolean | false |
| sx | Props de disposición rápida | LhSxProps | — |
LhFormItem Props
| Prop | Descripción | Tipo | Predeterminado |
|---|---|---|---|
| prop | Ruta del campo en model; admite user.name | string | — |
| label | Texto de la etiqueta | string | — |
| required | Si el campo es obligatorio | boolean | false |
| rules | Reglas de validación del campo actual; su prioridad es mayor que la de Form rules | LhFormRule[] | — |
Reglas de validación
ts
type LhFormRule = {
required?: boolean
message?: string
validator?: (value: unknown, model: Record<string, unknown>) => string | undefined
}LhForm expone los métodos validate() y resetFields().
Accesibilidad
- El texto de error de
LhFormItemllevarole="alert": cuando la validación falla, los lectores de pantalla lo anuncian de inmediato - La zona de contenido se asocia al texto de error mediante
aria-describedby, de modo que las tecnologías de asistencia pueden leer la correspondencia «campo → error»; cuando no hay error, la asociación se elimina automáticamente - Los controles de formulario (Input / Select / Checkbox / Radio / Switch / Slider / InputNumber / DatePicker / TimePicker / Cascader) leen el estado de validación del
LhFormItemal que pertenecen: si la validación falla, el control se marca conaria-invalid, y la marca se elimina automáticamente cuando el error desaparece; un control colocado fuera de unLhFormItemno se ve afectado - El texto de respaldo de los obligados proviene de
form.requireddel paquete de idioma (en español, «Este campo es obligatorio») y cambia de idioma con el ConfigProvider; elmessagede lasrulestiene prioridad más alta
Definiciones de tipos
Las estructuras de tipos TypeScript exportadas por este componente (extraídas automáticamente de packages/components/form/src/types.ts y de las fuentes @lh-ui/share/core/*; abre cada entrada para ver la definición completa; la descripción de los atributos está en la tabla de Props de arriba):
LhFormLabelPosition
ts
export type LhFormLabelPosition = 'left' | 'right' | 'top'LhFormProps
ts
export interface LhFormProps {
model: Record<string, unknown>
rules?: Record<string, LhFormRule[]>
labelPosition?: LhFormLabelPosition
labelWidth?: string | number
inline?: boolean
/** Props de disposición rápida */
sx?: LhSxProps
}LhFormItemProps
ts
export interface LhFormItemProps {
prop?: string
label?: string
required?: boolean
rules?: LhFormRule[]
}LhFormRule (de @lh-ui/share/core/form)
ts
export interface LhFormRule {
required?: boolean
message?: string
validator?: (value: unknown, model: Record<string, unknown>) => string | undefined
}