Skip to content
API 风格:

Form 폼 ​

LhForm과 LhFormItem은 모델 바인딩, 필수 입력 검증, 필드 오류 표시를 제공합니다.

기본 사용법 ​

기본 사용법
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: '이름을 입력하세요' }],
  email: [{ required: true, message: '이메일을 입력하세요' }],
}

async function submitForm() {
  const valid = await formRef.value.validate()
  if (valid) {
    LhMessage.success('제출 성공')
    console.log('제출 성공', formModel)
  }
}

function resetForm() {
  formRef.value?.resetFields()
}
</script>

<template>
  <LhForm ref="formRef" :model="formModel" :rules="formRules" label-width="80px">
    <LhFormItem prop="name" label="이름" required>
      <LhInput v-model="formModel.name" placeholder="이름을 입력하세요" />
    </LhFormItem>
    <LhFormItem prop="email" label="이메일" required>
      <LhInput v-model="formModel.email" placeholder="이메일을 입력하세요" />
    </LhFormItem>
    <LhFormItem>
      <LhButton type="primary" @click="submitForm">제출</LhButton>
      <LhButton plain @click="resetForm" style="margin-left: 8px">초기화</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: '이름을 입력하세요' }],
        email: [{ required: true, message: '이메일을 입력하세요' }],
      },
    }
  },
  methods: {
    async submitForm() {
      const valid = await this.$refs.formRef.validate()
      if (valid) {
        LhMessage.success('제출 성공')
        console.log('제출 성공', this.formModel)
      }
    },
    resetForm() { this.$refs.formRef?.resetFields() },
  },
}
</script>

<template>
  <LhForm ref="formRef" :model="formModel" :rules="formRules" label-width="80px">
    <LhFormItem prop="name" label="이름" required>
      <LhInput v-model="formModel.name" placeholder="이름을 입력하세요" />
    </LhFormItem>
    <LhFormItem prop="email" label="이메일" required>
      <LhInput v-model="formModel.email" placeholder="이메일을 입력하세요" />
    </LhFormItem>
    <LhFormItem>
      <LhButton type="primary" @click="submitForm">제출</LhButton>
      <LhButton plain @click="resetForm">초기화</LhButton>
    </LhFormItem>
  </LhForm>
</template>

커스텀 테마 ​

폼에 커스텀 테마 색상을 적용할 수 있습니다.

青花瓷(청화백자) 테마 폼
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>
  <!-- 청화백자 테마 -->
  <LhConfigProvider :theme-vars="cerblueTheme">
    <LhForm :model="themeForm" label-width="80px">
      <LhFormItem label="이름">
        <LhInput v-model="themeForm.name" />
      </LhFormItem>
      <LhFormItem>
        <LhButton type="primary">제출</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>
  <!-- 청화백자 테마 -->
  <LhConfigProvider :theme-vars="cerblueTheme">
    <LhForm :model="themeForm" label-width="80px">
      <LhFormItem label="이름">
        <LhInput v-model="themeForm.name" />
      </LhFormItem>
      <LhFormItem>
        <LhButton type="primary">제출</LhButton>
      </LhFormItem>
    </LhForm>
  </LhConfigProvider>
</template>

국제화 ​

국제화 폼
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>
  <!-- 국제화 설정 -->
  <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>
  <!-- 국제화 설정 -->
  <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>

라벨 위치와 인라인 레이아웃 ​

label-position으로 라벨 정렬(left / right / top)을 전환하고, inline으로 폼 항목을 가로로 배치합니다.

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="이름" required>
      <LhInput v-model="fpModel.name" />
    </LhFormItem>
    <LhFormItem prop="city" label="도시">
      <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="이름" required>
      <LhInput v-model="fpModel.name" />
    </LhFormItem>
    <LhFormItem prop="city" label="도시">
      <LhInput v-model="fpModel.city" />
    </LhFormItem>
  </LhForm>
</template>

LhForm Props ​

속성설명타입기본값
model폼 데이터 객체{ [x: string]: unknown; }—
rules필드 검증 규칙{ [x: string]: LhFormRule[]; }—
labelPosition라벨 위치"left" | "right" | "top"'right'
labelWidth라벨 너비string | number—
inline인라인 레이아웃 사용 여부booleanfalse
sxsx 빠른 레이아웃 속성LhSxProps—

LhFormItem Props ​

속성설명타입기본값
propmodel의 필드 경로, user.name 지원string—
label라벨 텍스트string—
required필수 입력 여부booleanfalse
rules현재 필드 검증 규칙, Form rules보다 우선 순위가 높음LhFormRule[]—

검증 규칙 ​

ts
type LhFormRule = {
  required?: boolean
  message?: string
  validator?: (value: unknown, model: Record<string, unknown>) => string | undefined
}

LhForm은 validate()와 resetFields() 메서드를 노출합니다.

접근성 ​

  • LhFormItem의 오류 글자는 role="alert"을 가지며, 검증 실패 시 스크린 리더가 즉시 알려줍니다
  • 내용 영역은 aria-describedby로 오류 글자를 연결하여 보조 기술이 '필드 → 오류' 대응 관계를 읽을 수 있습니다. 오류가 없으면 연결이 자동으로 제거됩니다
  • 폼 컨트롤(Input / Select / Checkbox / Radio / Switch / Slider / InputNumber / DatePicker / TimePicker / Cascader)은 자신이 속한 LhFormItem의 검증 상태를 읽어, 검증 실패 시 컨트롤에 aria-invalid를 표시하고 오류가 해소되면 자동으로 제거합니다. 컨트롤이 LhFormItem 밖에 있으면 영향을 받지 않습니다
  • 필수 입력 기본 글자는 언어 팩 form.required(중국어 「此项为必填」)에서 가져오며, ConfigProvider 언어 전환을 따릅니다. rules의 message가 더 높은 우선 순위를 가집니다

타입 정의 ​

이 컴포넌트가 외부로 내보내는 TypeScript 타입 구조는 다음과 같습니다(packages/components/form/src/types.ts와 @lh-ui/share/core/* 소스에서 자동 추출, 각 항목을 펼쳐 전체 정의를 확인하세요. 속성 설명은 위쪽 Props 표를 참고하세요).

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
  /** sx 빠른 레이아웃 속성 */
  sx?: LhSxProps
}
LhFormItemProps
ts
export interface LhFormItemProps {
  prop?: string
  label?: string
  required?: boolean
  rules?: LhFormRule[]
}
LhFormRule (@lh-ui/share/core/form에서 가져옴)
ts
export interface LhFormRule {
  required?: boolean
  message?: string
  validator?: (value: unknown, model: Record<string, unknown>) => string | undefined
}

국풍의 아름다움으로 코드의 토대를 세웁니다