28 KiB
بینکنگ ایپ بنائیں حصہ 2: لاگ ان اور رجسٹریشن فارم بنائیں
لیکچر سے پہلے کا کوئز
تعارف
تقریباً تمام جدید ویب ایپس میں آپ اپنا اکاؤنٹ بنا سکتے ہیں تاکہ آپ کی اپنی ذاتی جگہ ہو۔ چونکہ ایک وقت میں کئی صارفین ویب ایپ تک رسائی حاصل کر سکتے ہیں، آپ کو ایک ایسا طریقہ کار درکار ہوتا ہے جو ہر صارف کے ذاتی ڈیٹا کو الگ الگ محفوظ کرے اور یہ منتخب کرے کہ کون سی معلومات دکھانی ہیں۔ ہم صارف کی شناخت کو محفوظ طریقے سے منظم کرنے کا احاطہ نہیں کریں گے کیونکہ یہ خود ایک وسیع موضوع ہے، لیکن ہم یہ یقینی بنائیں گے کہ ہر صارف ہماری ایپ پر ایک (یا زیادہ) بینک اکاؤنٹ بنا سکے۔
اس حصے میں ہم HTML فارم استعمال کریں گے تاکہ اپنی ویب ایپ میں لاگ ان اور رجسٹریشن شامل کریں۔ ہم دیکھیں گے کہ ڈیٹا کو سرور API پر پروگرام کے ذریعے کیسے بھیجا جائے، اور آخر میں صارف کے ان پٹ کے لیے بنیادی توثیق کے اصول کیسے بیان کیے جائیں۔
پیشگی شرط
آپ کو اس سبق کے لیے ویب ایپ کے HTML ٹیمپلیٹس اور روٹنگ مکمل کرنے کی ضرورت ہے۔ آپ کو Node.js انسٹال کرنے اور سرور API چلانے کی بھی ضرورت ہے تاکہ آپ اکاؤنٹس بنانے کے لیے ڈیٹا بھیج سکیں۔
نوٹ کریں آپ کے پاس ایک وقت میں دو ٹرمینلز چل رہے ہوں گے جیسا کہ نیچے درج ہے۔
- مرکزی بینک ایپ کے لیے جو ہم نے HTML ٹیمپلیٹس اور روٹنگ سبق میں بنائی تھی۔
- بینک ایپ سرور 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>اقسام کی پوری فہرست اور دیگر فارم کنٹرولز پر ایک نظر ڈالیں تاکہ آپ کے UI بنانے کے وقت تمام نیٹیو UI عناصر کے بارے میں ایک خیال حاصل ہو۔
✅ نوٹ کریں کہ <input> ایک خالی عنصر ہے جس پر آپ کو بند کرنے والا ٹیگ شامل نہیں کرنا چاہیے۔ تاہم، آپ خود بند ہونے والے <input/> نوٹیشن کا استعمال کر سکتے ہیں، لیکن یہ ضروری نہیں ہے۔
فارم کے اندر <button> عنصر تھوڑا خاص ہے۔ اگر آپ اس کے type ایٹریبیوٹ کی وضاحت نہیں کرتے ہیں، تو جب دبایا جائے گا تو یہ خود بخود فارم ڈیٹا کو سرور پر جمع کر دے گا۔ یہاں ممکنہ type کی قدریں ہیں:
submit: فارم کے اندر ڈیفالٹ، بٹن فارم جمع کرنے کی کارروائی کو متحرک کرتا ہے۔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> عناصر UI کنٹرولز کو نام دینے کے لیے استعمال کیے جاتے ہیں، جیسے کہ ہمارا یوزر نیم فیلڈ۔ لیبلز آپ کے فارم کی پڑھنے کی صلاحیت کے لیے اہم ہیں، لیکن اضافی فوائد کے ساتھ بھی آتے ہیں:
- فارم کنٹرول کے ساتھ لیبل کو منسلک کرکے، یہ معاون ٹیکنالوجیز استعمال کرنے والے صارفین (جیسے اسکرین ریڈر) کو یہ سمجھنے میں مدد کرتا ہے کہ ان سے کس ڈیٹا کی توقع کی جا رہی ہے۔
- آپ لیبل پر کلک کر سکتے ہیں تاکہ متعلقہ ان پٹ پر براہ راست فوکس کیا جا سکے، جس سے ٹچ اسکرین پر مبنی ڈیوائسز پر پہنچنا آسان ہو جائے۔
ویب پر رسائی ایک بہت اہم موضوع ہے جسے اکثر نظر انداز کیا جاتا ہے۔ سیمینٹک 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 قسم ہے۔ کیا یہ دوسرے ان پٹس سے مختلف نظر آتا ہے؟ اس کے ساتھ تعامل کرنے کی کوشش کریں۔
✅ کیا آپ صرف کی بورڈ کا استعمال کرتے ہوئے فارم کو نیویگیٹ اور ان کے ساتھ تعامل کر سکتے ہیں؟ آپ یہ کیسے کریں گے؟
ڈیٹا کو سرور پر بھیجنا
اب جب کہ ہمارے پاس ایک فعال UI ہے، اگلا مرحلہ ڈیٹا کو ہمارے سرور پر بھیجنا ہے۔ آئیے اپنے موجودہ کوڈ کا استعمال کرتے ہوئے ایک فوری ٹیسٹ کرتے ہیں: کیا ہوتا ہے اگر آپ لاگ ان یا رجسٹر بٹن پر کلک کریں؟
کیا آپ نے اپنے براؤزر کے URL سیکشن میں تبدیلی دیکھی؟
ایک <form> کے لیے ڈیفالٹ ایکشن موجودہ سرور URL پر GET method کا استعمال کرتے ہوئے فارم کو جمع کرنا ہے، فارم ڈیٹا کو براہ راست URL میں شامل کرتے ہوئے۔ تاہم، اس طریقے میں کچھ خامیاں ہیں:
- بھیجے گئے ڈیٹا کا سائز بہت محدود ہے (تقریباً 2000 حروف)
- ڈیٹا براہ راست URL میں نظر آتا ہے (پاس ورڈز کے لیے اچھا نہیں)
- یہ فائل اپلوڈز کے ساتھ کام نہیں کرتا
اسی لیے آپ اسے POST method استعمال کرنے کے لیے تبدیل کر سکتے ہیں جو HTTP درخواست کے باڈی میں فارم ڈیٹا کو سرور پر بھیجتا ہے، بغیر کسی پچھلی حدود کے۔
اگرچہ POST ڈیٹا بھیجنے کے لیے سب سے زیادہ استعمال ہونے والا طریقہ ہے، کچھ مخصوص منظرناموں میں GET طریقہ استعمال کرنا بہتر ہوتا ہے، جیسے کہ سرچ فیلڈ کو نافذ کرتے وقت۔
کام
رجسٹریشن فارم میں action اور method پراپرٹیز شامل کریں:
<form id="registerForm" action="//localhost:5000/api/accounts" method="POST">
اب اپنے نام کے ساتھ نیا اکاؤنٹ رجسٹر کرنے کی کوشش کریں۔ رجسٹر بٹن پر کلک کرنے کے بعد آپ کو کچھ ایسا نظر آنا چاہیے:
اگر سب کچھ ٹھیک ہو جائے تو سرور آپ کی درخواست کا جواب ایک JSON جواب کے ساتھ دے گا جس میں وہ اکاؤنٹ ڈیٹا ہوگا جو بنایا گیا تھا۔
✅ دوبارہ اسی نام کے ساتھ رجسٹر کرنے کی کوشش کریں۔ کیا ہوتا ہے؟
صفحہ ری لوڈ کیے بغیر ڈیٹا بھیجنا
جیسا کہ آپ نے شاید محسوس کیا ہو، اس طریقہ کار کے ساتھ ایک معمولی مسئلہ ہے جو ہم نے ابھی استعمال کیا: فارم جمع کراتے وقت، ہم اپنی ایپ سے باہر نکل جاتے ہیں اور براؤزر سرور URL پر ری ڈائریکٹ ہو جاتا ہے۔ ہم اپنی ویب ایپ کے ساتھ تمام صفحہ ری لوڈز سے بچنے کی کوشش کر رہے ہیں، کیونکہ ہم ایک سنگل پیج ایپلیکیشن (SPA) بنا رہے ہیں۔
فارم ڈیٹا کو سرور پر بھیجنے کے لیے بغیر صفحہ ری لوڈ کیے، ہمیں جاوا اسکرپٹ کوڈ استعمال کرنا ہوگا۔ <form> عنصر کے action پراپرٹی میں URL ڈالنے کے بجائے، آپ کسی بھی جاوا اسکرپٹ کوڈ کو 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 کلیدی لفظ کے ساتھ استعمال کیا جاتا ہے، تو یہ غیر متزامن کوڈ کے عمل کا انتظار کرنے کی اجازت دیتا ہے - جیسے یہاں سرور کے جواب کا انتظار کرنا - جاری رکھنے سے پہلے۔
fetch() API کا استعمال کرتے ہوئے ہم JSON ڈیٹا کو سرور پر بھیجتے ہیں۔ یہ طریقہ 2 پیرامیٹرز لیتا ہے:
- سرور کا URL، لہذا ہم یہاں
//localhost:5000/api/accountsواپس ڈال دیتے ہیں۔ - درخواست کی ترتیبات۔ یہ وہ جگہ ہے جہاں ہم طریقہ کو
POSTپر سیٹ کرتے ہیں اور درخواست کے لیےbodyفراہم کرتے ہیں۔ چونکہ ہم JSON ڈیٹا کو سرور پر بھیج رہے ہیں، ہمیںContent-Typeہیڈر کوapplication/jsonپر سیٹ کرنے کی بھی ضرورت ہے تاکہ سرور مواد کو سمجھ سکے۔
چونکہ سرور درخواست کا جواب JSON کے ساتھ دے گا، ہم JSON مواد کو پارس کرنے اور نتیجے میں آنے والے آبجیکٹ کو واپس کرنے کے لیے await response.json() استعمال کر سکتے ہیں۔ نوٹ کریں کہ یہ طریقہ غیر متزامن ہے، لہذا ہم یہاں واپس آنے سے پہلے کسی بھی غلطی کو پکڑنے کے لیے await کلیدی لفظ استعمال کرتے ہیں۔
اب register فنکشن میں کچھ کوڈ شامل کریں تاکہ createAccount() کو کال کریں:
const result = await createAccount(jsonData);
چونکہ ہم یہاں await کلیدی لفظ استعمال کرتے ہیں، ہمیں register فنکشن سے پہلے async کلیدی لفظ شامل کرنے کی ضرورت ہے:
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 (Bad Request) اسٹیٹس کوڈ کے ساتھ ایک غلطی واپس کرتا ہے۔
سرور پر ڈیٹا بھیجنے سے پہلے یہ ایک اچھا عمل ہے کہ فارم ڈیٹا کی توثیق پہلے سے کی جائے جب ممکن ہو، تاکہ آپ یقینی بنائیں کہ آپ ایک درست درخواست بھیج رہے ہیں۔ HTML5 فارم کنٹرولز مختلف ایٹریبیوٹس کا استعمال کرتے ہوئے بلٹ ان توثیق فراہم کرتے ہیں:
required: فیلڈ کو بھرنا ضروری ہے ورنہ فارم جمع نہیں کیا جا سکتا۔minlengthاورmaxlength: ٹیکسٹ فیلڈز میں حروف کی کم از کم اور زیادہ سے زیادہ تعداد کی وضاحت کرتا ہے۔minاورmax: عددی فیلڈ کی کم از کم اور زیادہ سے زیادہ قدر کی وضاحت کرتا ہے۔type: متوقع ڈیٹا کی قسم کی وضاحت کرتا ہے، جیسےnumber,email,fileیا دیگر بلٹ ان اقسام۔ یہ ایٹریبیوٹ فارم کنٹرول کے بصری رینڈرنگ کو بھی تبدیل کر سکتا ہے۔pattern: ایک ریگولر ایکسپریشن پیٹرن کی وضاحت کرنے کی اجازت دیتا ہے تاکہ یہ جانچ سکے کہ درج کردہ ڈیٹا درست ہے یا نہیں۔
ٹپ: آپ اپنے فارم کنٹرولز کی ظاہری شکل کو ان کے درست یا غلط ہونے کے مطابق
:validاور:invalidCSS پیسوڈو-کلاسز کا استعمال کرتے ہوئے حسب ضرورت بنا سکتے ہیں۔
کام
ایک نیا اکاؤنٹ بنانے کے لیے دو فیلڈز ضروری ہیں: یوزر نیم اور کرنسی، جبکہ دیگر فیلڈز اختیاری ہیں۔ فارم کے 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 Challenge 🚀
Agent موڈ کا استعمال کرتے ہوئے درج ذیل چیلنج مکمل کریں:
تفصیل: رجسٹریشن فارم کو جامع کلائنٹ-سائیڈ ویلیڈیشن اور یوزر فیڈبیک کے ساتھ بہتر بنائیں۔ یہ چیلنج آپ کو فارم ویلیڈیشن، ایرر ہینڈلنگ، اور انٹرایکٹو فیڈبیک کے ذریعے یوزر کے تجربے کو بہتر بنانے کی مشق کرنے میں مدد دے گا۔
پرومپٹ: رجسٹریشن فارم کے لیے مکمل فارم ویلیڈیشن سسٹم بنائیں جس میں شامل ہو: 1) ہر فیلڈ کے لیے ریئل-ٹائم ویلیڈیشن فیڈبیک جیسے ہی یوزر ٹائپ کرے، 2) ہر ان پٹ فیلڈ کے نیچے کسٹم ویلیڈیشن میسیجز ظاہر ہوں، 3) پاس ورڈ کنفرمیشن فیلڈ جس میں میچنگ ویلیڈیشن ہو، 4) بصری اشارے (جیسے درست فیلڈز کے لیے سبز چیک مارکس اور غلط فیلڈز کے لیے سرخ وارننگز)، 5) ایک سبمٹ بٹن جو صرف اس وقت فعال ہو جب تمام ویلیڈیشنز پاس ہوں۔ HTML5 ویلیڈیشن ایٹریبیوٹس، CSS اسٹائلنگ کے لیے، اور انٹرایکٹو بیہیویر کے لیے JavaScript کا استعمال کریں۔
🚀 چیلنج
HTML میں ایک ایرر میسیج دکھائیں اگر یوزر پہلے سے موجود ہو۔
یہاں ایک مثال ہے کہ تھوڑی سی اسٹائلنگ کے بعد حتمی لاگ ان صفحہ کیسا نظر آ سکتا ہے:
لیکچر کے بعد کا کوئز
جائزہ اور خود مطالعہ
ڈیولپرز نے اپنے فارم بنانے کی کوششوں میں خاصی تخلیقی صلاحیت کا مظاہرہ کیا ہے، خاص طور پر ویلیڈیشن حکمت عملیوں کے حوالے سے۔ مختلف فارم فلو کے بارے میں جاننے کے لیے CodePen کو دیکھیں؛ کیا آپ کچھ دلچسپ اور متاثر کن فارم تلاش کر سکتے ہیں؟
اسائنمنٹ
ڈسکلیمر:
یہ دستاویز AI ترجمہ سروس Co-op Translator کا استعمال کرتے ہوئے ترجمہ کی گئی ہے۔ ہم درستگی کے لیے کوشش کرتے ہیں، لیکن براہ کرم آگاہ رہیں کہ خودکار ترجمے میں غلطیاں یا غیر درستیاں ہو سکتی ہیں۔ اصل دستاویز کو اس کی اصل زبان میں مستند ذریعہ سمجھا جانا چاہیے۔ اہم معلومات کے لیے، پیشہ ور انسانی ترجمہ کی سفارش کی جاتی ہے۔ ہم اس ترجمے کے استعمال سے پیدا ہونے والی کسی بھی غلط فہمی یا غلط تشریح کے ذمہ دار نہیں ہیں۔




