نماذج الإدخال مفيدة جداً في أي تطبيق ويب. على خلاف angular و angularjs، والتي تعطي النماذج أحقية خارج الصندوق. عليك أن تتعامل مع نماذج الإدخال بنفسك في React. وقد أدى ذلك إلى العديد من التعقيدات مثل كيفية الحصول على قيم النموذج، وكيف يمكنني إدارة حالة (state) النموذج، وكيف يمكنني التحقق من صحة النموذج على الفور وإظهار رسائل التحقق من الصحة. هناك طرق ومكتبات مختلفة للمساعدة في هذا ولكن إذا كنت مثلي تكره الاعتماد على الكثير من المكتبات، أهلا وسهلا بك على متن المركب، سوف نقوم بعمل النموذج من البداية.
هناك نوعان من حقول الإدخال في React. لدينا المدخلات غير المنضبطة (uncontrolled input) والمدخلات المتحكم فيها (controlled input). المدخلات غير المنضبطة مثل مدخلات النموذج التقليدية في HTML، حيث يتم حفظ ما كتبته. سوف نستخدم ref للحصول على قيم نموذج الإدخال.
قمنا بإضافة ref=”name” للمُدخل، بحيث يمكننا الوصول للقيمة عن طريق this.refs.name.value حين يتم اعتماد النموذج.والجانب السلبي لهذا هو أنه يجب عليك “سحب” القيمة من الحقل عندما تحتاج إليها وقد يحدث هذا عندما يتم اعتماد النموذج.
تكون المُدخلات التي يتم التحكم بها (controlled inputs)عندما يتحكم مركب React الذي يعرض نموذج الإدخال في ما يحدث في هذا النموذج عند إدخال المستخدم اللاحق. بمعنى، عندما تتغير القيم في النموذج، يحفظ المركب الذي يعرض النموذج القيمة في الحالة (state) الخاصة به.
بالتأكيد يمكن لمركب آخر التعامل مع حالة (state) النموذج. والهدف من ذلك هو أنه في كل مرة يتغير فيها المُدخل (input)، يتم استدعاء الدالة changeHandler ويتم تخزين حالة المُدخل. ومن هنا يكون للمركب دائمًا القيمة الحالية للمدخلات دون الحاجة إلى استدعائها. هذا يعني أن مركب النموذج يمكنه الاستجابة للتغير الذي يحدث على المُدخل على الفور ؛ فمثلاً
- في حالة رد الفعل، مثل أكواد التحقق من الصحة (validation).
- تعطيل الزر إلا في حالة أن تكون جميع الحقول المُدخلة صحيحة.
- فرض صيغة إدخال محددة.
التعامل مع عدة مُدخلات (inputs) في نموذج الإدخال
في معظم الحالات، يكون علينا التعامل مع عدة مُدخلات في نموذج الإدخال. نحتاج إلى طريقة لالتقاط المُدخلات بدالة، بدلاً من تعريف دوال متعددة لفعل ذلك. وبالتالي، سنقوم بتعديل changeHandler كالآتي:
بسبب طريقة تغيير changeHandler بالأعلى، فإن المُدخل في النموذج الاشارة إليه، لتعديل الحالات (status) دينامكياً.
قيمة سمة الاسم (name) في كل مُدخل يجب أن تكون متشابهة مع حالة الاسم المعرفة في formControls في البناء (constructor).
إنشاء مركب إدخال نصي (TextInput)
هناك العديد من عناصر الإدخال مثل: النص، البريد الالكتروني، كلمة المرور، خيار select، صندوق الاختيار (checkbox)، التاريخ، زر الاختيار (radio button)، إلخ. وأنا أحب أن أُنشئ مركبات خاصة منفصلة لعناصر الإدخال، دعنا نبدأ بالمُدخل النصي (text input type).
لاحظ الـ {…props}، نستخدم هذا لتوزيع الخصائص (props) في عنصر الإدخال، كما يمكننا استخدام عنصر إدخال مخصص، كما في المثال التالي:
التحقق من صحة المُدخل النصي (TextInput) المخصص
بما أننا نستخدم المُدخل الذي يتم التحكم به (controlled input)، نستطيع إضافة مفاتيح أخرى للحالة (state) فيformControls، ليساعد في التحقق من المُدخل. نحتاج للخاصية valid (متاح)، لنعرف ما إذا كان المُدخل متاح أم لا. تحتوي validationRules على قائمة من القواعد التي يتم التحقق منها قبل أن يكون المُدخل متاحاً (valid).
هدفنا في كل مرة يتم يتغير فيها الإدخال (input)، نتأكد من أن الـvalidationRules للمُدخل تم التحقق من كونها صحيحة (true) أو خاطئة (false)، بعد ذلك يتم تحديث مفتاح valid بنتيجة التحقق. كما أضفنا خاصية اللمس، لنعرف ما إذا كان المستخدم قد لمس المُدخل في النموذج (from) أم لا. هذا الأمر سيساعد في عرض ملاحظات التحقق، عندما يتم لمس المُدخل في النموذج. هذا التحقق سيتم عن طريق الدالة changeHandler كالتالي:
الـvalid مساوية لدالة validate(value, prevState.formControls[name]).validationRules)، والتي سوف تستخدم للتحقق من حالة تحكم معين ما إذا كان صحيحاً (true) أو خاطئاً (false).
قمت بنقل دالة التحقق من الصحة في class منفصل، ثم قمت باستدعائه. دالة التحقق من الصحة (validate) لها معاملان، وهما القيمة والقواعد. سوف نقوم بالمرور خلال جميع القواعد عن طريق الـloop، ونتحقق من كل قاعدة، فإذا كانت مسموحة (valid) سوف نُرجع true، وإذا كانت غير مسموحة (invalid) سوف نُرجع false.
دعنا نفترض أننا نريد إضافة شرط تحقق آخر للاسم (name)، على سبيل المثال نريد أن يكون الاسم حقل مطلوب (required)، كل ما نحتاج فعله هو أن نقوم بتحديث الـformControl، للـvalidationRules في الاسم، وكتابة الكود المنطقي له في الـ validator class كما الآتي:
ثم نحتاج لتحديث الـvalidator class ليتوافق مع الـvalidator المطلوب.
قمنا بإنشاء مُدخل نصي (textInput) مخصص، وقمنا بإنشاء formControl له خاصية بإسم اسم (name) و لها قواعد تحقق وهي isRequired و minLength لـ3، بالأسفل المركب الذي يعالج هذا:
حين نضغط على زر الاعتماد، ونكون قد ملأنا المُدخل النصي (TextInput)، سوف تطبع الـformSubmitHandler في الـconsole قيمة كالآتالـ valid يساوي إما صحيح (true) أو خطأ (false).
الشيء الرائع، أننا لا نحتاج للانتظار لحين أن يضغط المستخدم على زر الاعتماد لمعرفة ما إذا كان المُدخل صحيحاً أم لا. وذلك لأنه يتم تخزين حالة (state) المركب، ولذلك يمكننا استخدام هذا في عرض رسالة الخطأ أو ملاحظة، عند كتابة المستخدم في المُدخل. ويمكننا أيضاً تعطيل زر الاعتماد (submit) لحين أن يكون المُدخل متاحاً.
عرض ملاحظة الخطأ
بالنسبة لنا لعرض ملاحظ الخطأ لمُدخل معين، نحتاج لتمرير خاصية الـtouched و الـvalid كـ prop لمركب المُدخل. سوف نضيف تنسيق للخطأ (error) وذلك بالاعتماد على حالة الـvalid، ونريد فعل ذلك فقط عندما يتم لمس المُدخل.
ونريد أيضاً أن نعدل مركب المُدخل النصي (TextInput) الخاص بنا، لعرض التنسيق بناءً على قيمة الـprops.valid و الـprops.touched.
أرجو ملاحظة أنه عليك إضافة تنسيق form-control و control-error لملف App.css.
يجب أن ترى لقطة الشاشة كالتالي، وذلك إذا كان المُدخل غير مسموح (invalid)، وتم لمسه.
تعطيل زر الاعتماد إذا كان النموذج (form) غير مسموح (invalid)
Html 5 لديه الخاصية disabled في زر المُدخل، يمكن أن نساوي خاصية الـformControls الخاصة بنا مع خاصية الـdisabled. حين يكون الـformControls غير مسموح (not valid).
الـdisabled={!this.state.formControls.name.valid} يمكن أن تعمل بشكل جيد، إذا كان لدينا تحكم نموذجي (form control) واحد. لكن إذا كنا نريد التعامل مع أكثر من تحكم نموذجي (form control) واحد، نستطيع أن نقوم بإضافة خاصية جديدة للحالة (state)، والتي سوف تتبع حالة الـ validity في كل كائن (object) الـformControl. إذاً يجب علينا أن نقوم بتحديث الحالة (state) ليتناسب مع هذا
نحتاج لتحديث دالة الـchangeHandler، بحيث يمكننا المرور خلال كل الحالات المتاحة (valid status) للتحكم النموذجي (form control)، وعندما يكون متاحاً (valid)، يتم تحديث حالة الـformIsValid لصحيح (true).
مع هذه الإعدادات سيكون من السهل علينا إعداد خاصية عدم الاتاحة (disabled) لحالة الـformIsValid، وهذا سوف يعالج كائن نموذج (form object) واحد أو أكثر.
أنواع أخرى من الإدخال
TEXTAREA: الـ TEXTAREA و البريد الإلكتروني (email) و كلمة المرور (password)، سوف يعملون بشكل مشابه للمُدخل النصي (text input). يمكننا إنشاء مركب الـTextArea.
EMAIL: يمكننا إنشاء مركب البريد الالكتروني (email)، تماماً مثل الـTextInput
PASSWORD: ويمكننا أيضاً إنشاء مركب كلمة المرور (password) تماماً مثل الـTextInput
البريد الإلكتروني (email) والـ TEXTAREA و كلمة المرور (password)، سوف يبدون مشابهين للمُدخل النصي (text input).
مشابه لـemail، password ، وtextarea الـtext input
SELECT OPTION: المتحكم النموذجي (form control) خيار الـselect، مختلف بعض الشيء عن باقي المتحكمات (from controls)، لأننا بحاجة للتوافق مع خيارات الـselect. سوف يبدو كالآتي
ثم سيكون مركب خيار الـselect ـ (Select Option) مثل الآتي
RADIO: مُدخل الـradio مشابه لـselect option، حيث أنه يمكن اختيار خيار واحد فقط من الخيارات المتاحة. المتحكم النموذجي (form control) سوف يكون مشابه للمتحكم النموذج (form control) ـselect option. بالأسفل مركب زر الـradio وكيف يبدو.
بوضع كل العناصر مع بعضها البعض، بافتراض أننا نريد أن يكون لدينا مُدخل بريد الكتروني (email)، اسم (TextInput)، الجنس (Select Input)، ومُدخل radio كله في متحكم نموذجي ( form control). بالأسفل مثال لكيف سوف يبدو المركب الخاص بك
شكراً للقراءة.