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/fa/7-bank-project/2-forms/README.md

26 KiB

ساخت اپلیکیشن بانکی قسمت دوم: ساخت فرم ورود و ثبت‌نام

آزمون پیش از درس

آزمون پیش از درس

مقدمه

در تقریباً تمام اپلیکیشن‌های وب مدرن، شما می‌توانید یک حساب کاربری ایجاد کنید تا فضای خصوصی خود را داشته باشید. از آنجا که چندین کاربر می‌توانند به طور همزمان به یک اپلیکیشن وب دسترسی داشته باشند، نیاز به مکانیزمی دارید که داده‌های شخصی هر کاربر را جداگانه ذخیره کند و مشخص کند کدام اطلاعات نمایش داده شود. ما نحوه مدیریت هویت کاربر به صورت امن را پوشش نمی‌دهیم، زیرا این موضوع به خودی خود گسترده است، اما مطمئن می‌شویم که هر کاربر بتواند یک (یا چند) حساب بانکی در اپلیکیشن ما ایجاد کند.

در این بخش، از فرم‌های HTML برای افزودن ورود و ثبت‌نام به اپلیکیشن وب خود استفاده خواهیم کرد. خواهیم دید که چگونه داده‌ها را به صورت برنامه‌ریزی شده به یک API سرور ارسال کنیم و در نهایت چگونه قوانین اعتبارسنجی اولیه برای ورودی‌های کاربر تعریف کنیم.

پیش‌نیاز

برای این درس، باید بخش قالب‌های HTML و مسیریابی اپلیکیشن وب را تکمیل کرده باشید. همچنین باید Node.js را نصب کنید و API سرور را به صورت محلی اجرا کنید تا بتوانید داده‌ها را برای ایجاد حساب‌ها ارسال کنید.

توجه کنید شما باید دو ترمینال به صورت همزمان اجرا کنید:

  1. برای اپلیکیشن اصلی بانکی که در درس قالب‌های HTML و مسیریابی ساختیم.
  2. برای API سرور اپلیکیشن بانکی که همین حالا تنظیم کردیم.

برای ادامه درس، باید هر دو سرور فعال باشند. این سرورها روی پورت‌های مختلف (پورت 3000 و پورت 5000) گوش می‌دهند، بنابراین همه چیز باید به خوبی کار کند.

می‌توانید با اجرای این دستور در یک ترمینال، بررسی کنید که سرور به درستی اجرا شده است:

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

فرم و کنترل‌ها

عنصر <form> بخشی از یک سند HTML را محصور می‌کند که در آن کاربر می‌تواند داده‌ها را با کنترل‌های تعاملی وارد و ارسال کند. انواع مختلفی از کنترل‌های رابط کاربری (UI) وجود دارد که می‌توانند در یک فرم استفاده شوند، رایج‌ترین آن‌ها عناصر <input> و <button> هستند.

انواع مختلفی از ورودی‌ها وجود دارد. به عنوان مثال، برای ایجاد یک فیلد که کاربر بتواند نام کاربری خود را وارد کند، می‌توانید از این استفاده کنید:

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

ویژگی name به عنوان نام ویژگی زمانی که داده‌های فرم ارسال می‌شوند استفاده خواهد شد. ویژگی id برای مرتبط کردن یک <label> با کنترل فرم استفاده می‌شود.

لیست کامل انواع <input> و سایر کنترل‌های فرم را بررسی کنید تا ایده‌ای از تمام عناصر رابط کاربری بومی که می‌توانید هنگام ساخت رابط کاربری خود استفاده کنید، به دست آورید.

توجه داشته باشید که <input> یک عنصر خالی است که نباید یک تگ بسته مطابقت‌دهنده به آن اضافه کنید. با این حال، می‌توانید از نماد خودبسته <input/> استفاده کنید، اما این ضروری نیست.

عنصر <button> در یک فرم کمی خاص است. اگر ویژگی type آن را مشخص نکنید، به طور خودکار داده‌های فرم را به سرور ارسال می‌کند. در اینجا مقادیر ممکن برای type آورده شده است:

  • submit: مقدار پیش‌فرض در یک <form>، دکمه عمل ارسال فرم را اجرا می‌کند.
  • reset: دکمه تمام کنترل‌های فرم را به مقادیر اولیه خود بازنشانی می‌کند.
  • button: هیچ رفتار پیش‌فرضی هنگام فشار دادن دکمه اختصاص نمی‌دهد. سپس می‌توانید با استفاده از جاوااسکریپت اقدامات سفارشی به آن اختصاص دهید.

وظیفه

بیایید با افزودن یک فرم به قالب 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) هستیم.

برای ارسال داده‌های فرم به سرور بدون اجبار به بارگذاری مجدد صفحه، باید از کد جاوااسکریپت استفاده کنیم. به جای قرار دادن یک URL در ویژگی action عنصر <form>، می‌توانید از هر کد جاوااسکریپت که با رشته 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 و Await برای مدیریت وعده‌ها

🎥 روی تصویر بالا کلیک کنید تا ویدیو درباره async/await را مشاهده کنید.

ما از API 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: اجازه می‌دهد یک الگوی عبارت منظم تعریف شود تا بررسی شود که داده‌های وارد شده معتبر هستند یا نه. نکته: شما می‌توانید ظاهر کنترل‌های فرم خود را بسته به اینکه معتبر هستند یا نه، با استفاده از شبه‌کلاس‌های CSS به نام :valid و :invalid سفارشی کنید.

وظیفه

برای ایجاد یک حساب کاربری معتبر جدید، دو فیلد ضروری وجود دارد: نام کاربری و ارز. سایر فیلدها اختیاری هستند. فرم 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">

اکنون اگر دکمه ثبت‌نام را فشار دهید و یک فیلد قوانین اعتبارسنجی تعریف‌شده را رعایت نکند، باید چیزی شبیه به این ببینید:

تصویری که خطای اعتبارسنجی را هنگام تلاش برای ارسال فرم نشان می‌دهد

اعتبارسنجی که قبل از ارسال هر داده به سرور انجام می‌شود، اعتبارسنجی سمت کاربر نامیده می‌شود. اما توجه داشته باشید که همیشه امکان انجام تمام بررسی‌ها بدون ارسال داده وجود ندارد. به عنوان مثال، نمی‌توانیم بررسی کنیم که آیا حسابی با همان نام کاربری قبلاً وجود دارد یا خیر، بدون ارسال درخواست به سرور. اعتبارسنجی اضافی که در سرور انجام می‌شود، اعتبارسنجی سمت سرور نامیده می‌شود.

معمولاً هر دو باید پیاده‌سازی شوند، و در حالی که استفاده از اعتبارسنجی سمت کاربر تجربه کاربری را با ارائه بازخورد فوری بهبود می‌بخشد، اعتبارسنجی سمت سرور برای اطمینان از اینکه داده‌های کاربر که با آن کار می‌کنید معتبر و ایمن هستند، ضروری است.


🚀 چالش

یک پیام خطا در HTML نشان دهید اگر کاربر قبلاً وجود داشته باشد.

در اینجا یک نمونه از صفحه ورود نهایی پس از کمی استایل‌دهی آورده شده است:

تصویری از صفحه ورود پس از اضافه کردن استایل‌های CSS

آزمون پس از درس

آزمون پس از درس

مرور و مطالعه شخصی

توسعه‌دهندگان در تلاش‌های خود برای ساخت فرم‌ها، به‌ویژه در مورد استراتژی‌های اعتبارسنجی، بسیار خلاق شده‌اند. درباره جریان‌های مختلف فرم با مرور CodePen یاد بگیرید؛ آیا می‌توانید فرم‌های جالب و الهام‌بخشی پیدا کنید؟

تکلیف

اپلیکیشن بانکی خود را استایل دهید

سلب مسئولیت:
این سند با استفاده از سرویس ترجمه هوش مصنوعی Co-op Translator ترجمه شده است. در حالی که ما تلاش می‌کنیم دقت را حفظ کنیم، لطفاً توجه داشته باشید که ترجمه‌های خودکار ممکن است شامل خطاها یا نادرستی‌ها باشند. سند اصلی به زبان اصلی آن باید به عنوان منبع معتبر در نظر گرفته شود. برای اطلاعات حیاتی، توصیه می‌شود از ترجمه حرفه‌ای انسانی استفاده کنید. ما مسئولیتی در قبال سوء تفاهم‌ها یا تفسیرهای نادرست ناشی از استفاده از این ترجمه نداریم.