الفرق بين المراجعتين لصفحة: «Next.js/building forms»

من موسوعة حسوب
ط مراجعة
ط نقل جميل-بيلوني صفحة Next.js/guides إلى Next.js/building forms دون ترك تحويلة
(لا فرق)

مراجعة 17:10، 3 يناير 2023

يرتبط نموذج الويب web form بطرفي العميل والخادم، ويُستخدم لإرسال البيانات التي تعامل معها خادم ويب للمعالجة والتخزين. يُعدّ النموذج نفسه عميلًا، بينما تُعدّ آلية التخزين التي تستخدم لحفظ واستعادة وإرسال البيانات عند الحاجة هي الخادم.

سيساعدك هذا الدليل في تعلّم كيفية إنشاء نموذج ويب باستخدام Next.js.

القسم الأول: نموذج HTML

يُبنى نموذج HTML باستخدام العنصر <form> الذي يأخذ مجموعة من السمات والحقول لهيكلة النموذج من خلال الحقول النصية وصناديق التحقق والقوائم المنسدلة والأزرار وغيرها.

إليك مثالًا عن صياغة نموذج HTML:

<!-- Basic HTML Form -->
<form action="/send-data-here" method="post">
  <label for="first">First name:</label>
  <input type="text" id="first" name="first" />
  <label for="last">Last name:</label>
  <input type="text" id="last" name="last" />
  <button type="submit">Submit</button>
</form>

ستبدو الواجهة الأمامية كالتالي:

نموذج بحقلي الاسم الأول و الثاني

يسلك العنصر <form> سلوك الحاوية التي تضم مختلف عناصر الدخل <input> مثل الحقول النصية text وأزرار الإرسال button، وسندرس كل عنصر على حدى من هذه العناصر مع سماتها.

  • action: وهي سمة تحدد وجهة بيانات النموذج عندما يُرسل، وقيمتها عادة عنوان URL (مطلق أو نسبي).
  • method: يحدد نوع طلب HTTP (GET أو POST) المستخدم في إرسال بيانات النموذج.
  • <label>: عنصر يحدد عنوان عناصر أخرى، ويدعم شمولية أو سهولة الوصول accessibility وخاصةً الوصول من خلال قارئات الشاشة.
  • <input>: وهو العنصر الأكثر استخدامًا في هيكلة النماذج لتشكيل حقول البيانات. يعتمد هذه العنصر بشدة على قيمة السمة type التي يمكن أن تكون نص text أو صندوق تحقق checkbox أو بريد إلكتروني email أو أزرار خيارات radio وغيرها.
  • <button>: وتمثل الأزرار القابلة للنقر التي تستخدم في إرسال البيانات.

التحقق من النموذج Form Validation

وهي العملية التي نتحقق فيها من صحة المعلومات التي أدخلها المستخدم وصحة تنسيقها كوجود المحرف @ مثلًا في عنوان البريد الإلكتروني الذي يدخله. ويكون التحقق وفق نمطين:

  • التحقق من جانب العميل: ويجري التحقق من صحة المعلومات في المتصفح.
  • التحقق من جانب الخادم: ويجري التحقق من صحة المعلومات في الخادم.

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

يُصنّف التحقق من جانب العميل ضمن فئات عدة أيضًا مثل:

  • مُدمج Built-in: يستخدم سمات HTML مثل required و type و minLength و maxLength و pattern وغيرها.
  • مبني على JavaScript: يجري التحقق باستخدام شيفرة JavaScript.

التحقق المدمج من النماذج باستخدام سمات HTML

  • required: ويحدد الحقول التي ينبغي ملؤها قبل إرسال النموذج.
  • type: ويحدد نوع البيانات (عدد، بريد إلكتروني، نص،..).
  • minLength: ويحدد العدد الأدنى المسموح من المحارف لحقل نصي.
  • maxLength: ويحدد العدد الأعلى المسموح من المحارف لحقل نصي.

لذلك قد يبدو النموذج الذي يستخدم هذه السمات كالتالي:

!--مع تحقق مدمج HTML نموذج  -->
<form action="/send-data-here" method="post">
  <label for="roll">Roll Number</label>
  <input
    type="text"
    id="roll"
    name="roll"
    required
    minlength="10"
    maxlength="20"
  />
  <label for="name">Name:</label>
  <input type="text" id="name" name="name" required />
  <button type="submit">Submit</button>
</form>

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

التحقق من مدخلات المستخدم

التحقق باستخدام شيفرة JavaScript

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

<form onsubmit="validateFormWithJS()">
  <label for="rollNumber">Roll Number:</label>
  <input type="text" name="rollNumber" id="rollNumber" />

  <label for="name">Name:</label>
  <input type="text" name="name" id="name" />

  <button type="submit">Submit</button>
</form>

<script>
  function validateFormWithJS() {
    const name = document.querySelector('#name').value
    const rollNumber = document.querySelector('#rollNumber').value

    if (!name) {
      alert('Please enter your name.')
      return false
    }

    if (rollNumber.length < 3) {
      alert('Roll Number should be at least 3 digits long.')
      return false
    }
  }
</script>

يُستخدم العنصر <script> لإدراج شيفرة JavaScript من جانب العميل. وقد يضم العنصر شيفرة سطرية كما في المثال السابق، أو قد يشير إلى ملف سيفرة خارجي من خلال السمة src. يتحقق المثال الذي عرضناه سابقًا من الاسم ورقم الدور لمستخدم، إذ لا تسمح الدالة ()validateFormWithJS بإرسال النموذج إن كان حقل الاسم فارغًا أو كان الدور أقل من ثلاث خانات. يجري التحقق من النموذج عند النقر على زر الإرسال Submit، ولن تنتقل إلى الصفحة التي ما لم تكن القيم التي يقدمها المستخدمة صالحة.

التحقق باستخدام جافاسكربت

التحقق من النماذج باستخدام التعابير النمطية

تُستخدم التعابير النمطية Regular Expressions في JavaScript للتحقق من صحة بيانات النماذج، ولا بد حينها من استخدام السمة pattern. والتعبير النمطي الذي يُعرف اختصارًا بالشكل RegEx هو كائن يصف نمطًا محددًا من المحارف. تُطبق السمة pattern على العنصر <input> فقط، وبالتالي تستطيع التحقق من قيمة هذا العنصر بتعريف تعبير نمطي يُشكِّل قاعدة تحقق خاصة بك. فإن لم تتطابق القيمة التي يدخلها المستخدم مع التعبير النمطي سيعطي عنصر الدخل رسالة خطأ.

يظهر المثال التالي استخدام السمة pattern مع عنصر دخل:

<form action="/action_page.php">
  <label for="pswrd">Password:</label>
  <input
    type="password"
    id="pswrd"
    name="pswrd"
    pattern="[a-z0-9]{1,15}"
    title="Password should be digits (0 to 9) or alphabets (a to z)."
  />

  <button type="submit">Submit</button>
</form>

ينبغي أن تضم كلمة السر أرقامًا من 0 إلى 9 وأحرفًا صغيرة من a إلى z ولا تزيد عدد المحارف عن 15 محرفًا. لا يُسمح أيضًا بمحارف أخرى مثل (# أو $ أو & أو غيرها). وهكذا سيكون التعبير النمطي الذي يحقق القواعد السابقة هو: {1,15}[a-z0-9].

التحقق باستخدام التعابير النمطية

للمزيد من التفاصيل حول التعابير النمطية، ارجع إلى مقال التعابير النمطية Regular Expressions في جافاسكريبت.

القسم الثاني: إعداد المشروع

سننشئ في هذا القسم نماذج React باستخدام Next.js.

أنشئ تطبيق جديد باستخدام create-next-app مثلًا وذلك بتنفيذ الأمر التالي في الطرفية:

npx create-next-app

أجب عن الأسئلة التي يطرحها معالج إنشاء التطبيق وامنح المشروع اسمًا. انتقل إلى جذر مجلد مشروعك الجديد ثم نفّذ أحد الأمرين npm run dev أو yarn dev لتبدأ خادم التطوير.

افتح عنوان URL الذي يظهر على الطرفية للتأكد من صحة عمل تطبيقك.

القسم الثالث: إعداد مسار API الخاص بنموذج Next.js

سنبني الواجهتين الأمامية والخلفية باستخدام Next.js. أنشئ لهذه الغاية وصلة API على الخادم لإرسال البيانات إليها. تُزوّدك Next.js بنظام توجيه يعتمد على الملفات مبني على مبدأ الصفحات. إذ يُربط كل ملف ضمن المجلد pages/api بالمسار */api/ ويُعامل كوصلة API (نقطة اتصال مع الواجهة البرمجية) بدلًا من كونه صفحة page.

انتقل إلى المجلّد pages/api ثم أنشئ ملفًا باسم form.js وانسخ إليه هذه الشيفرة المكتوبة بلغة Node.js:

export default function handler(req, res) {
  // أرسل البيانات في جسم الطلب
  const body = req.body

  // تعليمات اختيارية لإظهار وضع الاستجابة
  // في سطر الأوامر عند تشغيل التطبيق
  console.log('body: ', body)

  // التحقق من أول وآخر اسم
  // والعودة مباشرة إن لم يُعثر على شيء
  if (!body.first || !body.last) {
    // أرسل رمز حالة الخطأ
    return res.status(400).json({ data: 'First or last name not found' })
  }

  // الاسم موجود
  // أرسل رمز حالة النجاح
  res.status(200).json({ data: `${body.first} ${body.last}` })
}

تتلقى الدالة handler الطلب req من العميل (بيانات النموذج المُرسلة) وترسل الاستجابة res بتنسيق JSON تضم الاسم الأول والأخير. بإمكانك الوصول إلى وصلة API هذه من خلال العنوان http://localhost:3000/api/form، واستبدل عنوان الخادم المحلي بعنوان Vercel الفعلي مثلًا إن شئت ذلك في مرحلة النشر.

ملاحظة: بإمكانك أيضًا ربط قاعدة بيانات MongoDB أو جداول Google بوصلة API هذه لكي تخزّن البيانات التي يرسلها النموذج بأمان لاستخدامات أخرى. لا نستخدم قاعدة بيانات في هذا الدليل بل نعيد نفس البيانات المُرسلة لشرح ما يجري فقط.

إرسال بيانات النموذج دون استخدام JavaScript

بإمكانك الآن أن تستخدم الوصلة النسبية api/form/ ضمن السمة action للنموذج. تُرسل البيانات إلى الخادم من خلال طلب HTTP من نوع POST:

<form action="/api/form" method="post">
  <label for="first">First name:</label>
  <input type="text" id="first" name="first" />
  <label for="last">Last name:</label>
  <input type="text" id="last" name="last" />
  <button type="submit">Submit</button>
</form>

عندما ترسل هذا النموذج، ستُرسل البيانات إلى وصلة API الخاصة بالنماذج api/form/، ثم يستجيب الخادم الذي يعالج عادة تلك البيانات، ويحمّل عنوان URL المحدد بواسطة السمة action، مسببًا تحميل صفحة جديدة. ستنتقل في مثالنا إلى الوجهة http://localhost:3000/api/form وستكون استجابة الخادم كالتالي:

استجابة الخادم

القسم الرابع: تهيئة النماذج في Next.js

أنشأنا في القسم السابق مسار API لإرسال النماذج، وقد حان الوقت الآن لتهيئة العميل (النموذج نفسه) ضمن Next.js باستخدام React. ستكون خطوتنا الأولى توسيع معرفتك بنماذج HTML وتحويلها إلى React (باستخدام JSX).

إليك نفس النموذج لكن على شكل مكوّن React كُتب باستخدام JSX:

export default function Form() {
  return (
    <form action="/api/form" method="post">
      <label htmlFor="first">First Name</label>
      <input type="text" id="first" name="first" required />

      <label htmlFor="last">Last Name</label>
      <input type="text" id="last" name="last" required />

      <button type="submit">Submit</button>
    </form>
  )
}

إليك ما تغيّر:

  • تحوّلت السمة for إلى htmlFor (كونها كلمة مرتبطة بحلقة "for" في JavaScript).
  • للسمة action الآن عنوان URL نسبي وهو وصلة API الخاصة بالنموذج.

وهكذا تكون الهيكيلية الأساسية لنموذج Next.js قد اكتملت.

يمكنك الاطلاع على كامل المشروع والشيفرة المصدرية في المستودع المخصص على GitHub

نموذج نيكست

القسم الخامس: إرسال بيانات النموذج دون JavaScript

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

  • لحل مشكلة حزمة الاستهلاك المحدودة.
  • زيادة عمر بطارية الجهاز (هاتف أو حاسوب محمول).
  • لأسباب تتعلق بالخصوصية، فقد لا يرغب المستخدم أن يُلاحق من قبل سكربتات التحليل.

وبغض النظر عن الأسباب، سينعكس تعطيل شيفرة JavaScript سلبًا على عمل الموقع إن لم يعطله كليًا.

سنفتح الآن المجلد next-forms ضمن المجلد pages/ وسننشئ الملف no-js-form.js.

تلميح سريع: الصفحة في Next.js هي مكوّن React مُصدَّر عن ملفات موجودة في المجلد pages وتمتلك إحدى الامتدادات التالية: js. أو jsx. أو ts. أو tsx.. تقترن كل صفحة بمسار يتعلق باسم الملف، فلو أنشأت على سبيل المثال الملف pages/no-js-form.js، ستتمكن من الوصول إليه من خلال العنوان your-domain.tld/no-js-form.

لنستخدم نفس الشيفرة السابقة:

export default function PageWithoutJSbasedForm() {
  return (
    <form action="/api/form" method="post">
      <label htmlFor="first">First Name</label>
      <input type="text" id="first" name="first" required />

      <label htmlFor="last">Last Name</label>
      <input type="text" id="last" name="last" required />

      <button type="submit">Submit</button>
    </form>
  )
}

عندما تنقر على زر الإرسال وتكون شيفرة JavaScript معطّلة، سيؤدي ذلك إلى وقوع حدث النقر ويسبب تجميع بيانات النموذج وإرسالها إلى الوصلة المحددة في السمة action عبر طلب HTTP POST. سيُعاد توجيهك بعد ذلك إلى الوصلة api/form/، فهكذا تعمل السمة action في النماذج. تُرسل البيانات إلى الخادم كطلب req إلى الدالة التي كتبناها سابقًا. ستعالج هذه الدالة البيانات وتعيد نصًا بتنسيق JSON كاستجابة res تضم الاسم الذي أرسلته.

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

القسم السادس: إرسال النماذج في حال تفعيل JavaScript

أنشئ في المجلد pages/ ملفًا جديدًا باسم js-form.js والذي سينشئ بدوره الصفحة js-form/ في تطبيق Next.js.

حالما يُرسل النموذج، سنمنع السلوك الافتراضي له الذي يؤدي إلى إعادة تحميل الصفحة. سنأخذ بيانات النموذج ونحولها إلى نص بتنسيق JSON ثم نرسلها إلى الخادم (تمثله وصلة API في حالتنا). يستجيب الخادم أخيرًا معيدًا نفس الاسم الذي أُرسل إليه. يجري كل ذلك من خلال دالة JavaScript بسيطة هي ()handleSubmit.

إليك الطريقة التي قد تُكتب بها هذه الدالة، وقد وثّقناها خطوة خطوة لفهم الأمر:

export default function PageWithJSbasedForm() {
  // يتعامل مع حدث إرسال النموذج
  const handleSubmit = async (event) => {
    // يمنع النموذج من إعادة تحديث الصفحة بعد الإرسال
    event.preventDefault()

    // الحصول على بيانات النموذج
    const data = {
      first: event.target.first.value,
      last: event.target.last.value,
    }

    // JSON إرسال البيانات إلى الخادم بصيغة 
    const JSONdata = JSON.stringify(data)

    //التي نرسل البيانات إليها API وصلة 
    const endpoint = '/api/form'

    // تشكيل الطلب الذي يرسل البيانات إلى الخادم
    const options = {
      // POST إرسال البيانات بطلب من النوع 
      method: 'POST',
      // JSON إبلاغ الخادم بإرسال بيانات بتنسيق 
      headers: {
        'Content-Type': 'application/json',
      },
      //التي أنشأناها سابقًا JSON جسم الطلب هو بيانات 
      body: JSONdata,
    }

    // Vercel على API إرسال بيانات النموذج إلى وصلة 
    const response = await fetch(endpoint, options)

    // JSON الحصول على البيانات من الخادم بتنسيق 
    //  إن أعاد الخادم الاسم الذي أرسل فالنموذج يعمل بشكل صحيح
    const result = await response.json()
    alert(`Is this your full name: ${result.data}`)
  }
  return (
    // عند الإرسال handleSubmit() تمرير الحدث إلى الدالة 
    <form onSubmit={handleSubmit}>
      <label htmlFor="first">First Name</label>
      <input type="text" id="first" name="first" required />

      <label htmlFor="last">Last Name</label>
      <input type="text" id="last" name="last" required />

      <button type="submit">Submit</button>
    </form>
  )
}

تمثل الشيفرة السابقة صفحة بمكوّن دوال React يُدعى PageWithJSbasedForm مع عنصر نموذج <form> مكتوب بلغة JSX. لا يمتلك النموذج السمة action، بل نستخدم معالج الحدث onSubmit لإرسال البيانات إلى الدالة {handleSubmit}.

تعالج الدالة ()handleSubmit البيانات عبر سلسلة من الخطوات:

  • تمنع الدالة ()event.preventDefaultالنموذج من تحديث كامل الصفحة.
  • أنشانا كائن JavaScript يُدعى data يحمل القيمتين first و last من النموذج.
  • استخدمنا التعليمة JSON.stringify(data) لتحويل البيانات إلى تنسيق JSON.
  • استخدمنا الدالة ()fetch لإرسال البيانات إلى الوصلة api/form/ باستخدام JSON وطلب HTTP من نوع POST.
  • يستجيب الخادم بإعادة الاسم الذي أرسلناه.

خلاصة

غطينا في هذا الدليل ما يلي:

  • عنصر نموذج HTML الأساسي <form>.
  • فهم نماذج React.js.
  • التحقق من بيانات النماذج باستخدام وبلا استخدام JavaScript.
  • استخدام مسار API في للتعامل مع الطلب req والاستجابة res بين العميل والخادم.

المصادر