كيفية التعامل مع النماذج مع الرد فقط

حسنا ، عنوان هذا المقال هو الطعم. سأخبرك فعلاً بكيفية التعامل مع النماذج ... Javascript. والرد سيكون مجرد مساعدتنا على البقاء إعلان. هذا ما هو عليه ، بعد كل شيء.

إذا شعرت في أي وقت أن العمل باستخدام النماذج في React كان أكثر من اللازم أو يستخدم الزاوي لتوفير تجربة أفضل أو كنت ترغب فقط في معرفة ما قد يكون أفضل طريقة * لتنظيم النماذج في رد فعل ، فاقرأ على ذلك.

أول شيء أود أن أذكره هو مدى قوة واجهة برمجة التطبيقات (API) الفعالة والتقليل من قيمتها. لها سمعة سيئة إلى حد ما ، لأنه أمر حتمي تمامًا. هذا هو السبب في وجود مكتبات مثل رد الفعل ، أو الصوت ، أو الزاوي ، إلخ. أعتقد أن هذا يخلق انطباعًا خاطئًا مع المبتدئين الذين يقفزون إلى الاستنتاج بأنه يجب عليك الابتعاد عنه. يجب عليك في الواقع تجنب التعليمات البرمجية الضرورية ، ولكن يجب أيضًا احتضان كل القوة التي يمنحكها المتصفح و DOM.

حسناً ، يكفي مع المقدمة ، دعنا ننتقل

كيفية إنشاء نماذج مع رد الفعل وإرسال البيانات إلى الخادم؟

دعنا نبدأ بسيطة.

النهج الأكثر أضيق الحدود

عرض توضيحي:

وإليك الرمز:

حسنًا ، أين هي سمات القيمة أو عمليات الاسترجاعات onChange؟ حسنًا ، لست مطالبًا باستخدامها. يتم استدعاء رد الاتصال onSubmit عند إرسال نموذج html إما بالنقر فوق الزر إرسال أو فقط بالضغط على "إدخال" أثناء التركيز في أحد حقول الإدخال. عند إضافة سمات الاسم إلى المدخلات الخاصة بك ، يمكنك إضافة هيكل إلى النموذج الخاص بك. يمكن إجراء تسلسل لهذه البنية من خلال واجهة FormData الأصلية (الدعم الأساسي في جميع المتصفحات و IE10 +). كل ما عليك فعله هو تمرير عنصر نموذج (يمكننا الوصول إليه عبر event.target) إلى مُنشئ FormData وستحصل على تفسير تسلسلي للمدخلات التي يمكن إرسالها إلى الخادم.

لاحظ أيضًا أننا لا نضيف مستمع onClick إلى الزر. إذا فعلنا ذلك ، فلن نتمكن من الاستجابة لإرسال الأحداث التي يتم تشغيلها من لوحة المفاتيح (عن طريق الضغط على مفتاح الإدخال). هذا سيء UX. باستخدام رد الاتصال onSubmit نغطي كلتا الحالتين.

باستخدام هذه الطريقة ، بصرف النظر عن حجم نمو النموذج ، فلن تحتاج إلى كتابة أي تعليمات برمجية إضافية. ما عليك سوى اتباع ممارسة جيدة تتمثل في إضافة سمة اسم دائمًا إلى علامات الإدخال الخاصة بك (بالطبع يجب أن تتوافق هذه الأسماء مع ما يتوقعه الخادم).

لاحظ أيضًا كيف احتفظنا بمكون النموذج بالتعريف الكامل حتى بدون استخدام ميزات التفاعل مثل "المكونات الخاضعة للرقابة". ليست هناك حاجة إلى الحكام أو التلاعب DOM الخام. إليك الرابط إلى الكمان مع النموذج.

تتطلب بياناتي تحويلها من إدخال المستخدم ، لذلك أحتاج إلى مكونات معقدة ومراقبة من قبل الدولة!

حسنا ، لا ، ليس بالضرورة.

أحد الأشياء الأولى التي تتعلمها عند البدء في رد الفعل هو أن البيانات يجب أن يكون لها مصدر واحد للحقيقة وأنه يجب أن تتدفق بطريقة واحدة ، من أعلى إلى أسفل. هذا صحيح. لكن أين هو "مصدر" بيانات النموذج؟ ذلك يعتمد على نوع التطبيق لديك.

من المحتمل جدًا أن تأتي بيانات النموذج من مدخلات المستخدم ومن أي مكان آخر ، ولا تتم مشاركتها في أي مكان آخر.

أحد الدروس القيمة التي تتعلمها من مستندات الرد هي أنه عندما يتعين عليك مشاركة الحالة ، يجب رفع الحالة لأعلى. لكن كن حذرًا: لا ترفع الحالة عندما لا تحتاج إليها.

نعم ، هناك حالات يكون فيها المدخلات التي يتم التحكم فيها اختيارًا صالحًا. أخطط لتغطية تلك الحالات في منصبي التالي.

لكن في الوقت الحالي ، أود أن أستكشف إلى أي مدى يمكنك الذهاب مع الطريقة البسيطة الموضحة أعلاه دون الوصول إلى المدخلات التي يتم التحكم فيها.

تحويلات إدخال البيانات

تخيل أن البيانات التي يحتاجها الخادم في شكل مختلف عن البيانات التي يدخلها المستخدم. دعنا نقول أن لدينا هذه المتطلبات:

  • يقوم المستخدم بإدخال التاريخ بتنسيق MM / DD / YYYY ، لكن الخادم يتوقعه بتنسيق YYYY-MM-DD
  • يجب إرسال اسم المستخدم بأحرف كبيرة
handleSubmit (حدث) {
    event.preventDefault ()؛
    بيانات const = FormData جديدة (event.target) ؛
    // ملاحظة: يمكنك الوصول إلى حقول FormData باستخدام `data.get (fieldName)`
    const [الشهر ، اليوم ، السنة] = data.get ('تاريخ الميلاد'). split ('/') ؛
    const serverDate = `$ {year} - $ {month} - $ {day}`؛
    data.set ('birthdate'، serverDate)؛
    data.set ('اسم المستخدم' ، data.get ('اسم المستخدم'). toUpperCase ())؛
    إحضار ('/ api / form-submit-url' ، {
      طريقة: "وظيفة" ،
      الجسم: البيانات ،
    })؛
}

كان ذلك سهلاً للغاية. أفضل ما في الأمر هو أنه لم يكن عليك البحث عن طريقة خاصة بالإطار أو المكون الإضافي للقيام بذلك. تذكر موزعي $ وخطوط تنسيق $؟ لم تكن ميزة سيئة ، لقد كانت ميزة رائعة. لقد استمتعت استخدامه. لكنني أعتقد أنك ستوافق على أنها مبالغة في هذه الحالة بالذات.

هناك جانب سلبي واحد. هل لاحظت كيف ربطنا أنفسنا بأجزاء معينة من المدخلات؟ داخل المقبض ، أرسل معالج الآن علينا أن نعرف أي المدخلات تحتاج إلى تحويل وأيها لا. لقد فقدنا بعض التصريحات. دعنا نحل هذه المشكلة.

من الآن فصاعدًا عندما تحتاج القيمة التي أدخلها المستخدم إلى تحويل ، سأدعو هذا "التحليل".

بناءً على التطبيق الخاص بك ، قد تحتاج إلى وظائف محلل مختلفة لأنواع مختلفة من المدخلات. ولكن من خلال التطبيق الخاص بك ، من المحتمل أن تعيد استخدام الكثير منها. إعادة استخدام الرمز هو شيء نفعله طوال الوقت. لماذا لا تنشئ مجموعة من وظائف الأداة المساعدة المسؤولة عن تحليل مدخلات النموذج الخاصة بك؟ إليك مثال على ذلك:

const inputParsers = {
  التاريخ (الإدخال) {
    const [الشهر ، اليوم ، السنة] = input.split ('/') ؛
    إرجاع `$ {year} - $ {month} - $ {day}`؛
  }،
  الأحرف الكبيرة (الإدخال) {
    إرجاع الإدخال. toUpperCase () ؛
  }،
  رقم (الإدخال) {
    عودة parseFloat (المدخلات) ؛
  }،
}؛

مجرد كائن جافا سكريبت مع الأساليب. ولكن كيف نستخدمها؟ حسنا…

الوقت لمعرفة المزيد عن DOM api

يحتوي أي عنصر

على خاصية عناصر. قراءة المزيد عنها هنا. إنه كائن مجموعة html. أفضل ما في الأمر هو أنه يوفر الوصول إلى جميع عقد إدخال النموذج حسب المفتاح ، حيث يكون المفتاح هو سمة اسم الإدخال. نعم ، بصرف النظر عن مدى عمق العنصر الذي لديك <إدخال name = 'birthdate' /> داخل النموذج ، يمكنك الوصول إليه باستخدام form.elements.birthdate. أليس هذا رائعًا؟

حسنًا ، يمكننا الوصول إلى عقد إدخال جميع النماذج باسمهم. ولكن كيف نعرف أي منها يتم تحليله؟ كيف يمكننا وضع علامة على تلك المدخلات التي تحتاج إلى بعض التحليل الإضافي؟

سمات البيانات بالطبع! هذا ما هم هنا من أجله. للإشارة إلى أن قيمة المدخلات تحتاج إلى تحويلها إلى أحرف كبيرة قبل إرسالها إلى الخادم ، أقترح إضافة سمة تحليل البيانات إليها:

<مساهمة
  اسم = "اسم المستخدم"
  نوع = "نص
  بيانات تحليل = "الأحرف الكبيرة"
/>

وصفي جدا. وإليك المثال الكامل الذي يوضح كيف يمكننا تحويل جميع البيانات اللازمة. انتبه إلى معالج "handleSubmit":

هذا قوي جدا ، في رأيي. مرة أخرى ، يمكن أن تنمو أشكالنا كبيرة بقدر حاجتها دون جعل وظيفة معالجنا أكبر.

وأفضل ما في الأمر هو أننا لم نربط أنفسنا بأي مكتبة لمعالجة أشكال التفاعل فحسب ، بل ربطنا أنفسنا بالكاد لرد الفعل. إذا قررت يومًا ما التخلي عن رد الفعل لأي سبب ، فلن تضطر إلى تغيير طريقة تعاملك مع النماذج بشكل ملحوظ. DOM لا يذهب إلى أي مكان.

التحقق من صحة المدخلات

إذا كنت ملاحظًا ، فقد تكون لاحظت مشكلة أخرى في النموذج أعلاه. لا نتحقق من المدخلات للتأكد من صحتها قبل تحليلها ، مما قد يؤدي إلى أخطاء. إذا كنت تعتقد أن DOM api لا يمكن أن يساعدنا هنا أو أنها غير مدعومة جيدًا ، يسعدني أن أقول إنك مخطئ. التحقق من صحة نموذج HTML هو شيء قوي آخر أحب استخدامه كثيرًا.

المثال الأكثر بساطة:


  <اسم الإدخال = "اسم المستخدم" type = "text" مطلوب />

هذا هو. لقد أضفنا سمة مطلوبة فقط إلى أحد المدخلات. سيعتبر المتصفح أن حقل الإدخال هذا غير صالح إذا كان فارغًا وصالحًا إذا كان به حرف واحد على الأقل. عندما يكون حقل الإدخال على الأقل غير صالح ، فلن يسمح المتصفح للمستخدم بإرسال النموذج ، بل سيعرض تلميحًا بالقرب من أول إدخال غير صالح.

ولكن الشيء ، لا يمكننا الاعتماد على هذا السلوك: لن يمنع المتصفح من إرسال النموذج في Safari و Safari للجوال. لكننا لسنا بحاجة إلى! ليست تلميحات أداة المتصفح هي أفضل طريقة للذهاب إلى أي حال: فهي ليست مرنة بما فيه الكفاية وليست سهلة الاستخدام.

ما نفعله هو هذا:

<نموذج noValidate>
  <اسم الإدخال = "اسم المستخدم" type = "text" مطلوب />

نضيف سمة novalidate (يتحول noValidate في jsx إلى novalidate في html). اسم السمة مضلل إلى حد ما. عندما نضيفها ، فإننا لا نوقف التحقق من صحة النموذج. نحن فقط نمنع المتصفح من التدخل عند إرسال نموذج غير صالح حتى نتمكن من "التدخل" في أنفسنا.

لذا ، كيف يعمل التحقق من صحة النموذج الآن؟ مثل هذا: يحتوي عنصر على checkValidity () طريقة تُرجع خطأ عندما يعتبر النموذج غير صحيح وصحيح عندما يكون صالحًا. يعتبر النموذج غير صالح عندما يكون أحد عناصر الإدخال على الأقل غير صالح. إليك نسخة تجريبية صغيرة:

وإليك كيف يمكننا استخدام هذا في مقابلتنا

handleSubmit (حدث) {
  if (! event.target.checkValidity ()) {
    // النموذج غير صالح! لذلك نحن لا نفعل شيئا
    إرجاع؛
  }
  // النموذج صالح! يمكننا تحليل وتقديم البيانات
}

عظيم! الآن لدينا طريقة لمنع تحليل المدخلات غير الصالحة عندما يكون النموذج غير صالح.

هل يمكننا اكتشاف المدخلات الفردية غير الصحيحة؟ بالتأكيد! ماذا؟ بالضبط نفس الشيء: تحتوي المدخلات أيضًا على طريقة .checkValidity (). انظر بنفسك:

لا تعد إضافة سمة مطلوبة هي الطريقة الوحيدة لإخبار المستعرض بأنه يلزم التحقق من الإدخال. ماذا يمكن ان نفعل ايضا؟

  • استخدم سمة النقش. السمة أقوى التحقق من الصحة. يجب أن تكون قيمتها عبارة عن regex والتي ستتم مقارنتها بقيمة الإدخال بالكامل.
    دعنا نقول أننا نريد السماح بالأرقام فقط في بعض حقول الإدخال. إليك كيفية القيام بذلك: <إدخال نوع = "text" pattern = "\ d +" />. هذا هو. يمكننا الآن استدعاء .checkValidity () طريقة الإدخال والتحقق مما إذا كانت صالحة أم لا.
لاحظ أنه عندما يكون الإدخال فارغًا ، فإنه يعتبر
  • إعطاء مدخلات نوع البريد الإلكتروني. تمامًا كما يوحي الاسم ، سيتم التحقق من الإدخال لنمط بريد إلكتروني صالح ، لذلك لا يتعين علينا التوصل إلى حل regex غريب.

حسنًا ، لنستخدم هذه المعرفة. إليك ما قد يبدو عليه رمز النموذج الآن:


  
  <مساهمة
    معرف = "اسم المستخدم"
    اسم = "اسم المستخدم"
    نوع = "نص"
    بيانات تحليل = "الأحرف الكبيرة"
  />
  
  
  
  <مساهمة
    معرف = "تاريخ الميلاد"
    اسم = "تاريخ الميلاد"
    نوع = "نص"
    بيانات تحليل = "التاريخ"
    نائب = "MM / DD // YYYY"
    النمط = "\ د {2} \ / \ د {2} / \ د {4}"
    مطلوب
  />
  <زر> إرسال البيانات! 

إليك حيلة كاملة مع التحقق من الصحة وإليكم لمحة عن كيفية عملها:

تصور مدخلات غير صالحة

أنا أعرف ما قد تفكر فيه. إذا كان بالإمكان التحقق من صلاحية الإدخال باستخدام طريقة .checkValidity () ، فيمكننا تبديل فئات الصلاحية باستخدام javascript!

خطأ! حسنًا ، هذا ليس "خطأ" حقًا ، لكن لدي حل أفضل كثيرًا لأقدمه. دعنا نتعرف على شيء واحد أكثر قوة حول واجهة برمجة التطبيقات للنموذج.

: غير صالح المغلق محدد

يمكن أن تستهدف هذه المدخلات غير صالحة مع المغلق النقي! تماما مثل هذا:

المدخلات: غير صالحة {
  لون الحدود: أحمر.
}

مرة أخرى ، أنا أعرف ما قد تفكر فيه. "مثل هذا المغلق السحري ربما لديه دعم فظيع للمتصفح". أنا سعيد جدًا بتصحيحك: إنه يحتوي على دعم رائع للمتصفح!

هناك بعض العيوب. على الرغم من أن أداة اختيار css الزائفة قوية ، إلا أنها غبية جدًا. دعنا نقول أننا نريد تصميم مدخلات غير صالحة فقط بعد أن يحاول المستخدم إرسال النموذج. لا يشتمل النموذج على فكرة "القذرة" أو وجود حالة "حاول الإرسال". لذلك سيتم تمييز المدخلات غير الصحيحة بحد أحمر حتى قبل أن يحاول المستخدم كتابة أي شيء على الإطلاق.

كيف يمكننا التعامل مع هذا؟ سهل جدا! يمكننا فقط إضافة فئة "displayErrors" إلى النموذج نفسه بعد أن يحاول المستخدم إرسالها ونمط المدخلات على أنها غير صالحة فقط عندما تكون داخل نموذج مع فئة .displayErrors:

handleSubmit (حدث) {
  if (! event.target.checkValidity ()) {
    this.setState ({displayErrors: true}) ؛
    إرجاع؛
  }
  this.setState ({displayErrors: false}) ؛
}
يجعل() {
  const {displayErrors} = this.state؛
  إرجاع (
    <شكل
      onSubmit = {this.handleSubmit}
      noValidate
      className = {displayErrors؟ 'displayErrors': ''}
    >
      {/ * ... * /}
    
  )؛
}

... وفي المغلق لدينا:

.displayErrors المدخلات: غير صالحة {
  لون الحدود: أحمر.
}

يعمل كالسحر:

إليك الكمان الذي يمكنك اللعب به.

آمل أن أكون قد أقنعتك بأن DOM DOM الأصلي هو شيء قوي لا يحظى باهتمام كاف ويجب استخدامه. إنه مرن بدرجة كافية لمنحك أي سلوك تريده.

ماذا عن المدخلات "الخاضعة للرقابة" ، رغم ذلك؟ هناك الكثير من الحالات عندما تحتاج إليها. في هذا المنشور أردت أن أطلعكم على واجهة برمجة تطبيقات النماذج واستكشف قوتها. عدم استخدام المدخلات الخاضعة للرقابة يخدم هذا الغرض بشكل جيد للغاية.

قد تعتقد أنه عندما يكون لديك "تحكم" المدخلات لا تحتاج إلى هذا DOM API. لكنني أؤكد لك أن هذه الأشياء متكاملة. في مشاركتي التالية ، أرغب في استكشاف كيف يمكن أن يؤدي استخدام النماذج الأصلية إلى جانب المدخلات الخاضعة للرقابة إلى جعلك أكثر قوة. لكنني أريد أيضًا التأكيد على أنه لا ينبغي عليك البحث عن أداة أكثر قوة عندما يمكنك الاستغناء عنها بسهولة.