You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/ar/7-bank-project/2-forms/README.md

25 KiB

بناء تطبيق مصرفي الجزء الثاني: إنشاء نموذج تسجيل الدخول والتسجيل

اختبار ما قبل المحاضرة

اختبار ما قبل المحاضرة

المقدمة

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

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

المتطلبات الأساسية

يجب أن تكون قد أكملت قوالب HTML والتوجيه لتطبيق الويب لهذه الدرس. كما تحتاج إلى تثبيت Node.js وتشغيل واجهة برمجة التطبيقات للخادم محليًا حتى تتمكن من إرسال البيانات لإنشاء الحسابات.

ملاحظة ستحتاج إلى تشغيل نافذتي طرفية في نفس الوقت كما هو موضح أدناه:

  1. لتطبيق البنك الرئيسي الذي قمنا ببنائه في درس قوالب HTML والتوجيه
  2. لواجهة برمجة التطبيقات لخادم البنك Bank APP server API التي قمنا بإعدادها للتو أعلاه.

يجب تشغيل كلا الخادمين لمتابعة بقية الدرس. يستمعان على منافذ مختلفة (المنفذ 3000 والمنفذ 5000) لذا يجب أن يعمل كل شيء بشكل جيد.

يمكنك اختبار تشغيل الخادم بشكل صحيح عن طريق تنفيذ هذا الأمر في الطرفية:

curl http://localhost:5000/api
# -> should return "Bank API v1.0.0" as a result

النموذج وعناصر التحكم

عنصر <form> يضم قسمًا من مستند HTML حيث يمكن للمستخدم إدخال البيانات وإرسالها باستخدام عناصر التحكم التفاعلية. هناك جميع أنواع عناصر واجهة المستخدم (UI) التي يمكن استخدامها داخل النموذج، وأكثرها شيوعًا هما عنصرا <input> و<button>.

هناك العديد من الأنواع المختلفة من <input>، على سبيل المثال لإنشاء حقل حيث يمكن للمستخدم إدخال اسم المستخدم الخاص به يمكنك استخدام:

<input id="username" name="username" type="text">

سيتم استخدام خاصية name كاسم الخاصية عند إرسال بيانات النموذج. يتم استخدام خاصية id لربط عنصر <label> بعنصر التحكم في النموذج.

ألقِ نظرة على القائمة الكاملة لأنواع <input> وعناصر التحكم الأخرى للنماذج للحصول على فكرة عن جميع عناصر واجهة المستخدم الأصلية التي يمكنك استخدامها عند بناء واجهة المستخدم الخاصة بك.

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

عنصر <button> داخل النموذج له خصائص خاصة. إذا لم تحدد خاصية type الخاصة به، فسيقوم تلقائيًا بإرسال بيانات النموذج إلى الخادم عند الضغط عليه. فيما يلي القيم الممكنة لـ type:

  • submit: القيمة الافتراضية داخل <form>، الزر يقوم بتشغيل إجراء إرسال النموذج.
  • reset: الزر يعيد تعيين جميع عناصر التحكم في النموذج إلى قيمها الأولية.
  • button: لا يتم تعيين سلوك افتراضي عند الضغط على الزر. يمكنك بعد ذلك تعيين إجراءات مخصصة له باستخدام JavaScript.

المهمة

لنبدأ بإضافة نموذج إلى قالب login. سنحتاج إلى حقل اسم المستخدم وزر تسجيل الدخول.

<template id="login">
  <h1>Bank App</h1>
  <section>
    <h2>Login</h2>
    <form id="loginForm">
      <label for="username">Username</label>
      <input id="username" name="user" type="text">
      <button>Login</button>
    </form>
  </section>
</template>

إذا نظرت عن كثب، يمكنك ملاحظة أننا أضفنا أيضًا عنصر <label> هنا. يتم استخدام عناصر <label> لإضافة اسم لعناصر واجهة المستخدم، مثل حقل اسم المستخدم الخاص بنا. تُعد التسميات مهمة لسهولة قراءة النماذج الخاصة بك، ولكنها تأتي أيضًا بفوائد إضافية:

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

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

الآن سنضيف نموذجًا ثانيًا للتسجيل، أسفل النموذج السابق مباشرة:

<hr/>
<h2>Register</h2>
<form id="registerForm">
  <label for="user">Username</label>
  <input id="user" name="user" type="text">
  <label for="currency">Currency</label>
  <input id="currency" name="currency" type="text" value="$">
  <label for="description">Description</label>
  <input id="description" name="description" type="text">
  <label for="balance">Current balance</label>
  <input id="balance" name="balance" type="number" value="0">
  <button>Register</button>
</form>

باستخدام خاصية value يمكننا تحديد قيمة افتراضية لإدخال معين. لاحظ أيضًا أن الإدخال الخاص بـ balance يحتوي على نوع number. هل يبدو مختلفًا عن الإدخالات الأخرى؟ حاول التفاعل معه.

هل يمكنك التنقل والتفاعل مع النماذج باستخدام لوحة المفاتيح فقط؟ كيف يمكنك القيام بذلك؟

إرسال البيانات إلى الخادم

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

هل لاحظت التغيير في قسم عنوان URL في المتصفح؟

لقطة شاشة لتغيير عنوان URL في المتصفح بعد النقر على زر التسجيل

الإجراء الافتراضي لـ <form> هو إرسال النموذج إلى عنوان URL الحالي للخادم باستخدام طريقة GET، مع إلحاق بيانات النموذج مباشرة بعنوان URL. ومع ذلك، فإن لهذه الطريقة بعض العيوب:

  • البيانات المرسلة محدودة الحجم (حوالي 2000 حرف)
  • البيانات مرئية مباشرة في عنوان URL (وهذا ليس جيدًا بالنسبة لكلمات المرور)
  • لا تعمل مع تحميل الملفات

لهذا السبب يمكنك تغييرها لاستخدام طريقة POST التي ترسل بيانات النموذج إلى الخادم في جسم طلب HTTP، دون أي من القيود السابقة.

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

المهمة

أضف خصائص action وmethod إلى نموذج التسجيل:

<form id="registerForm" action="//localhost:5000/api/accounts" method="POST">

الآن حاول تسجيل حساب جديد باسمك. بعد النقر على زر التسجيل يجب أن ترى شيئًا مثل هذا:

نافذة متصفح على العنوان localhost:5000/api/accounts، تعرض سلسلة JSON تحتوي على بيانات المستخدم

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

حاول التسجيل مرة أخرى بنفس الاسم. ماذا يحدث؟

إرسال البيانات دون إعادة تحميل الصفحة

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

لإرسال بيانات النموذج إلى الخادم دون إجبار الصفحة على إعادة التحميل، علينا استخدام كود JavaScript. بدلاً من وضع عنوان URL في خاصية action لعنصر <form>، يمكنك استخدام أي كود JavaScript مسبوقًا بسلسلة javascript: لتنفيذ إجراء مخصص. استخدام هذا يعني أيضًا أنك ستحتاج إلى تنفيذ بعض المهام التي كانت تُنفذ تلقائيًا بواسطة المتصفح:

  • استرداد بيانات النموذج
  • تحويل وترميز بيانات النموذج إلى تنسيق مناسب
  • إنشاء طلب HTTP وإرساله إلى الخادم

المهمة

استبدل خاصية action لنموذج التسجيل بـ:

<form id="registerForm" action="javascript:register()">

افتح app.js وأضف وظيفة جديدة باسم register:

function register() {
  const registerForm = document.getElementById('registerForm');
  const formData = new FormData(registerForm);
  const data = Object.fromEntries(formData);
  const jsonData = JSON.stringify(data);
}

هنا نسترد عنصر النموذج باستخدام getElementById() ونستخدم أداة FormData لاستخراج القيم من عناصر التحكم في النموذج كمجموعة من أزواج المفتاح/القيمة. ثم نقوم بتحويل البيانات إلى كائن عادي باستخدام Object.fromEntries() وأخيرًا نقوم بتسلسل البيانات إلى JSON، وهو تنسيق يُستخدم عادةً لتبادل البيانات على الويب.

البيانات الآن جاهزة للإرسال إلى الخادم. قم بإنشاء وظيفة جديدة باسم createAccount:

async function createAccount(account) {
  try {
    const response = await fetch('//localhost:5000/api/accounts', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: account
    });
    return await response.json();
  } catch (error) {
    return { error: error.message || 'Unknown error' };
  }
}

ماذا تفعل هذه الوظيفة؟ أولاً، لاحظ الكلمة الرئيسية async هنا. هذا يعني أن الوظيفة تحتوي على كود سيتم تنفيذه بشكل غير متزامن. عند استخدامها مع الكلمة الرئيسية await، تسمح بانتظار تنفيذ الكود غير المتزامن - مثل انتظار استجابة الخادم هنا - قبل المتابعة.

إليك فيديو سريع عن استخدام async/await:

Async and Await لإدارة الوعود

🎥 انقر على الصورة أعلاه لمشاهدة فيديو عن async/await.

نستخدم واجهة برمجة التطبيقات fetch() لإرسال بيانات JSON إلى الخادم. تأخذ هذه الطريقة معلمتين:

  • عنوان URL الخاص بالخادم، لذا نضع هنا //localhost:5000/api/accounts.
  • إعدادات الطلب. هذا هو المكان الذي نحدد فيه الطريقة كـ POST ونوفر body للطلب. بما أننا نرسل بيانات JSON إلى الخادم، نحتاج أيضًا إلى تعيين رأس Content-Type إلى application/json حتى يعرف الخادم كيفية تفسير المحتوى.

نظرًا لأن الخادم سيرد على الطلب بـ JSON، يمكننا استخدام await response.json() لتحليل محتوى JSON وإرجاع الكائن الناتج. لاحظ أن هذه الطريقة غير متزامنة، لذا نستخدم الكلمة الرئيسية await هنا قبل الإرجاع للتأكد من أن أي أخطاء أثناء التحليل يتم التقاطها أيضًا.

الآن أضف بعض الكود إلى وظيفة register لاستدعاء createAccount():

const result = await createAccount(jsonData);

نظرًا لأننا نستخدم الكلمة الرئيسية await هنا، نحتاج إلى إضافة الكلمة الرئيسية async قبل وظيفة register:

async function register() {

أخيرًا، دعنا نضيف بعض السجلات للتحقق من النتيجة. يجب أن تبدو الوظيفة النهائية كما يلي:

async function register() {
  const registerForm = document.getElementById('registerForm');
  const formData = new FormData(registerForm);
  const jsonData = JSON.stringify(Object.fromEntries(formData));
  const result = await createAccount(jsonData);

  if (result.error) {
    return console.log('An error occurred:', result.error);
  }

  console.log('Account created!', result);
}

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

لقطة شاشة تظهر رسالة سجل في وحدة تحكم المتصفح

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

التحقق من البيانات

إذا حاولت تسجيل حساب جديد دون إدخال اسم مستخدم أولاً، يمكنك أن ترى أن الخادم يعيد خطأ برمز الحالة 400 (طلب غير صالح).

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

  • required: يجب ملء الحقل وإلا لن يتم إرسال النموذج.
  • minlength وmaxlength: تحدد الحد الأدنى والأقصى لعدد الأحرف في الحقول النصية.
  • min وmax: تحدد الحد الأدنى والأقصى لقيمة الحقل الرقمي.
  • type: يحدد نوع البيانات المتوقعة، مثل number، email، file أو أنواع أخرى مدمجة. قد يغير هذا السمة أيضًا العرض المرئي لعنصر التحكم في النموذج.
  • pattern: يسمح بتحديد نمط التعبير العادي لاختبار ما إذا كانت البيانات المدخلة صالحة أم لا.

نصيحة: يمكنك تخصيص مظهر عناصر التحكم في النموذج بناءً على كونها صالحة أم لا باستخدام الفئات الزائفة :valid و :invalid في CSS.

المهمة

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

<label for="user">Username (required)</label>
<input id="user" name="user" type="text" required>
...
<label for="currency">Currency (required)</label>
<input id="currency" name="currency" type="text" value="$" required>

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

أضف خاصية maxlength إلى حقول النص:

<input id="user" name="user" type="text" maxlength="20" required>
...
<input id="currency" name="currency" type="text" value="$" maxlength="5" required>
...
<input id="description" name="description" type="text" maxlength="100">

الآن إذا ضغطت على زر تسجيل وكان هناك حقل لا يحترم قاعدة التحقق التي قمنا بتعريفها، يجب أن ترى شيئًا مثل هذا:

لقطة شاشة تظهر خطأ التحقق عند محاولة إرسال النموذج

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

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



تحدي GitHub Copilot Agent 🚀

استخدم وضع الوكيل لإكمال التحدي التالي:

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

المهمة: قم بإنشاء نظام تحقق كامل للنموذج يتضمن: 1) ردود فعل فورية للتحقق من كل حقل أثناء الكتابة، 2) رسائل تحقق مخصصة تظهر أسفل كل حقل إدخال، 3) حقل تأكيد كلمة المرور مع تحقق من المطابقة، 4) مؤشرات بصرية (مثل علامات خضراء للحقول الصالحة وتحذيرات حمراء للحقول غير الصالحة)، 5) زر إرسال يصبح مفعلاً فقط عندما يتم اجتياز جميع عمليات التحقق. استخدم خصائص التحقق في HTML5، وCSS لتنسيق حالات التحقق، وJavaScript للسلوك التفاعلي.

🚀 التحدي

اعرض رسالة خطأ في HTML إذا كان المستخدم موجودًا بالفعل.

إليك مثالًا لما يمكن أن يبدو عليه صفحة تسجيل الدخول النهائية بعد إضافة بعض أنماط CSS:

لقطة شاشة لصفحة تسجيل الدخول بعد إضافة أنماط CSS

اختبار ما بعد المحاضرة

اختبار ما بعد المحاضرة

المراجعة والدراسة الذاتية

لقد أصبح المطورون مبدعين للغاية في جهودهم لبناء النماذج، خاصة فيما يتعلق باستراتيجيات التحقق. تعرف على تدفقات النماذج المختلفة من خلال تصفح CodePen؛ هل يمكنك العثور على نماذج مثيرة وملهمة؟

الواجب

صمم تطبيق البنك الخاص بك


إخلاء المسؤولية:
تم ترجمة هذا المستند باستخدام خدمة الترجمة بالذكاء الاصطناعي Co-op Translator. بينما نسعى لتحقيق الدقة، يرجى العلم أن الترجمات الآلية قد تحتوي على أخطاء أو عدم دقة. يجب اعتبار المستند الأصلي بلغته الأصلية المصدر الرسمي. للحصول على معلومات حاسمة، يُوصى بالترجمة البشرية الاحترافية. نحن غير مسؤولين عن أي سوء فهم أو تفسيرات خاطئة تنشأ عن استخدام هذه الترجمة.