نموذج Form
مكوّن مركّب من LhForm + LhFormItem، يوفّر التحقق من البيانات وعرض الأخطاء ومحاذاة العلامات وغيرها من القدرات.
الاستخدام الأساسي
import { useRef, useState } from 'react'
import { LhButton, LhForm, LhFormItem, LhInput, LhSelect } from '@lh-ui/react'
import type { LhFormInstance, LhFormRule } from '@lh-ui/react'
interface FormData {
name: string
style: string
}
const rules: Record<string, LhFormRule[]> = {
name: [{ required: true, message: 'يرجى إدخال اسم العمل', trigger: 'blur' }],
style: [{ required: true, message: 'يرجى اختيار أسلوب الرسم', trigger: 'change' }],
}
export default function Demo() {
const [formData, setFormData] = useState<FormData>({ name: '', style: '' })
const formRef = useRef<LhFormInstance>(null)
const handleSubmit = async () => {
const valid = await formRef.current?.validate()
if (valid) alert(`تم الإرسال بنجاح: ${formData.name} / ${formData.style}`)
}
const handleReset = () => {
formRef.current?.resetFields()
setFormData({ name: '', style: '' })
}
return (
<LhForm ref={formRef} model={formData} rules={rules} labelWidth="80px">
<LhFormItem label="اسم العمل" prop="name">
<LhInput
value={formData.name}
onChange={(val) => setFormData((prev) => ({ ...prev, name: val }))}
/>
</LhFormItem>
<LhFormItem label="أس لوب الرسم" prop="style">
<LhSelect
value={formData.style}
onChange={(val) => setFormData((prev) => ({ ...prev, style: val as string }))}
options={[{ label: 'رسم الحبر', value: 'ink' }]}
/>
</LhFormItem>
<LhFormItem>
<LhButton type="primary" onClick={handleSubmit}>إرسال</LhButton>
<LhButton onClick={handleReset}>إعادة تعيين</LhButton>
</LhFormItem>
</LhForm>
)
}
خصائص Form
| خاصية | الوصف | النوع | الافتراضي |
|---|---|---|---|
| model | كائن بيانات النموذج (مطلوب) | Record<string, unknown> | — |
| rules | قواعد التحقق، ومفاتيحها هي أسماء الحقول | Record<string, LhFormRule[]> | — |
| labelWidth | عرض العلامة | string | number | — |
| labelPosition | موضع العلامة | 'left' | 'right' | 'top' | 'right' |
| inline | تخطيط سطري | boolean | false |
| disabled | تعطيل جميع العناصر الفرعية | boolean | false |
| size | حجم العناصر الفرعية | 'large' | 'middle' | 'small' | يتبع ConfigProvider |
| onSubmit | حدث الإرسال الأصلي (مع تطبيق preventDefault) | (event: FormEvent) => void | — |
خصائص FormItem
| خاصية | الوصف | النوع | الافتراضي |
|---|---|---|---|
| label | نص العلامة | string | — |
| prop | اسم الحقل (يدعم مسار النقاط، ويقابل مفتاحًا في model) | string | — |
| rules | قواعد على مستوى العنصر (تتجاوز قواعد مستوى form عند تطابق الاسم) | LhFormRule[] | — |
| required | نجمة الحقل المطلوب (تعرض العلامة فقط، بينما تأتي دلالة التحقق من rules) | boolean | false |
| labelWidth | تتجاوز عرض العلامة على مستوى form | string | number | — |
| errorMessage | رسالة خطأ مخصصة | string | — |
| showMessage | إظهار رسالة الخطأ | boolean | true |
LhFormRule
| خاصية | الوصف | النوع |
|---|---|---|
| required | هل الحقل مطلوب | boolean |
| message | رسالة فشل التحقق | string |
| trigger | طريقة التشغيل | 'blur' | 'change' |
| validator | دالة تحقق مخصصة (يمكن أن تُرجع Promise، وينتظر التحقق غير المتزامن بشكل صحيح) | (value, model) => string | undefined | Promise<string | undefined> |
| min / max | الحد الأدنى / الأقصى (قيمة رقمية أو طول) | number |
| pattern | تحقق بالتعبير النمطي | RegExp |
دوال ref الخاصة بـ Form
LhFormInstance (تُكشف عبر forwardRef + useImperativeHandle):
| دالة | الوصف | القيمة المعادة |
|---|---|---|
| validate | التحقق من جميع الح قول | Promise<boolean> |
| validateField | التحقق من حقل واحد | Promise<boolean> |
| resetFields | إعادة تعيين جميع الحقول إلى قيمها الأولية | void |
| resetField | إعادة تعيين حقل واحد | void |
const formRef = useRef<LhFormInstance>(null)
const ok = await formRef.current?.validate()
صحّحت هذه المكتبة عيوب التحقق غير المتزامن في plus: فدالة validateField في plus تستخدم Promise.resolve(!message) ولا تنتظر Promise الخاص بالمدقق غير المتزامن، فيُرجع التحقق غير المتزامن true دائمًا. أما نسخة React فتنتظر صراحة اكتمال الـ thenable قبل الحكم. راجع دليل الترحيل.
يُسجّل LhFormItem المُدقّق في form داخل useEffect، ويُلغى تسجيله تلقائيًا عند إلغاء التركيب. ولا حاجة للتصريح المسبق بالحقول في rules — فالحقول الموجودة في model دون rules تُلتقط قيمها الأولية عند التسجيل.
لا تفسر validateFormField في share قيمة trigger، بل يتولى هذا المستوى تحديد وقت التشغيل: فقيمة trigger: 'blur' (الافتراضية)
تُجري التحقق عند فقدان التركيز على FormItem، وقيمة trigger: 'change' عند تغيّر منطقة المحتوى. أما القواعد التي لا تحمل trigger
فتُشغَّل فقط عند فقد التركيز وعند استدعاء validate()، ولا تظهر الأخطاء بشكل متكرر أثناء الإدخال.
ويأخذ التحقق عند change القيمة الجديدة لهدف الحدث وليس لقطة model — فتحديثات الحالة وإرسال الأحداث في React لا تحدث في الدورة نفسها،
والرجوع إلى model سيتأخر دورة واحدة. وتُلتقط أحداث change الخاصة بعناصر التحكم الأصلية (input / textarea / select الأصلي)
عند صعودها إلى منطقة المحتوى؛ أما عناصر التحكم المخصصة فلا تمتلك حدث change أصليًا (نقر خيار LhSelect يُنتج click فقط)،
لذلك يُطلَق validateChange(value) عبر سياق FormItem حاملًا القيمة الجديدة صراحة.
بالإضافة إلى إعادة model إلى لقطة قيمه الأولية، تُزيد resetFields() العدّاد الداخلي resetVersion، فيُلاحظ كل FormItem
تغيّر الإصدار ويمسح حالة الخطأ الخاصة به. ولا تزال الحالة المُتحكم بها الخارجية بحاجة إلى المزامنة يدويًا (مثل
setFormData(initial) في العرض التوضيحي) — فـ React لا يستطيع كتابة model نيابة عنك كما يفعل سلسلة reactive في Vue.
الأنماط
import '@lh-ui/react/style/form'