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="primzhCNy">{{ 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="primzhCNy">{{ 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 ​

الخاصيةالوصفالنوعالافتراضي
modelكائن بيانات النموذج{ [x: string]: unknown; }—
rulesقواعد التحقق من الحقول{ [x: string]: LhFormRule[]; }—
labelPositionموضع التسمية"left" | "right" | "top"'right'
labelWidthعرض التسميةstring | number—
inlineما إذا كان التخطيط صَفِّيًاbooleanfalse
sxخصائص التخطيط السريع sxLhSxProps—

خصائص LhFormItem ​

الخاصيةالوصفالنوعالافتراضي
propمسار الحقل في model، يدعم user.namestring—
labelنص التسميةstring—
requiredما إذا كان إلزاميًاbooleanfalse
rulesقواعد التحقق لهذا الحقل، أولويتها أعلى من rules الخاصة بـ FormLhFormRule[]—

قواعد التحقق ​

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؛ وmessage داخل rules له أولوية أعلى

تعريفات الأنواع ​

بنى TypeScript التي يصدّرها هذا المكوّن خارجيًا (مستخرَجة تلقائيًا من packages/components/form/src/types.ts و@lh-ui/share/core/*؛ انقر كل عنصر لعرض التعريف كاملًا؛ وصف الخصائص في جدول الخصائص أعلاه):

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
}

جمال التقاليد، أساس الكود