إذا كنت قد قمت ببناء نموذج اتصال من قبل وشاهدت الصفحة بأكملها تُعاد تحميلها بعد أن ينقر المستخدم على "إرسال"، فأنت تعرف بالفعل مدى الانزعاج من هذه التجربة. باستخدام تقنيات إرسال نماذج HTML بـ fetch javascript، يمكنك إرسال بيانات النموذج إلى نقطة النهاية الخلفية في الخلفية، والحفاظ على المستخدم في نفس الصفحة، وإظهار رسالة نجاح أو خطأ واضحة دون أي تحديث كامل للصفحة. يرشدك هذا الدليل التعليمي خلال كل خطوة، من كتابة HTML الأساسي إلى توجيه استدعاء fetch() إلى نقطة نهاية Sendform بحيث تصل مساهماتك مباشرة إلى صندوق البريد الوارد أو سير العمل المتصل.
النقاط الرئيسية:
- واجهة Fetch API تتيح لك إرسال بيانات النماذج دون إعادة تحميل الصفحة، مما يوفر تجربة أكثر سلاسة للمستخدمين.
- التقاط حدث
submitواستدعاءpreventDefault()هو أساس أي نمط إرسال نماذج ajax. - يوفر Sendform رابط نقطة نهاية جاهز، لذا لا تحتاج إلى أي كود خلفي لاستقبال وتخزين المساهمات.
- التعامل الصحيح مع الاستجابة (إظهار ملاحظات النجاح أو الخطأ) مهم بنفس قدر أهمية إرسال البيانات بشكل صحيح.
جدول المحتويات
لماذا نستخدم fetch() بدلاً من الإرسال الافتراضي للنموذج
سلوك إرسال النموذج الافتراضي في المتصفح يقوم بشيء واحد بالضبط: يقوم بتسلسل حقول النموذج، ويرسل طلب POST (أو GET) إلى رابط action، ثم يحمل أي استجابة يرجعها الخادم. هذا يعني أن المستخدم يرى وميضاً أبيض، ويفقد موضع التمرير، وينتظر رسم صفحة جديدة. على اتصال بطيء، قد يبدو هذا معطلاً.
واجهة Fetch API تحل هذه المشكلة من خلال إجراء طلبات HTTP برمجياً، بالكامل في JavaScript، دون التنقل بعيداً. هذا يتيح نمط إرسال النماذج دون إعادة تحميل الصفحة الذي يحافظ على تفاعل المستخدمين ويتيح لك التحكم في كل جانب من جوانب تجربة المستخدم، بما في ذلك حالات التحميل، وملاحظات التحقق المضمنة، ولافتات النجاح المتحركة.
أسباب عملية إضافية لتفضيل fetch():
- يمكنك إرفاق رؤوس مخصصة (على سبيل المثال، رمز CSRF أو مفتاح تفويض) لا يمكن لنموذج HTML عادي إرسالها.
- يمكنك تسلسل البيانات كـ JSON أو
FormDataأو سلاسل مُرمزة بـ URL حسب ما تتوقعه نقطة النهاية. - معالجة الأخطاء واضحة. أنت تقرر ما يعنيه "الفشل" وكيفية التواصل معه.
- يعمل على أي موقع ثابت، بما في ذلك تلك المستضافة على GitHub Pages أو Netlify أو CDN، لأن المنطق يعيش بالكامل في المتصفح.
ملاحظة: إذا كنت تعمل مع منشئ مواقع مثل Webflow أو WordPress أو Hugo، فإن نفس نهج fetch() ينطبق. اطلع على دليلنا حول كيفية دمج Sendform مع منشئ موقعك للحصول على نصائح خاصة بالمنصة.
إعداد نموذج HTML الأساسي
قبل كتابة سطر واحد من JavaScript، تحتاج إلى نموذج HTML منظم بشكل جيد. التفصيل الرئيسي هنا هو أنك لا تحتاج إلى خاصية action تشير إلى أي مكان، لأن JavaScript ستتعامل مع الإرسال. ومع ذلك، تريد خصائص name ذات معنى في كل إدخال - هذه تصبح مفاتيح الحقول في الحمولة المرسلة.
<form id="contact-form" novalidate>
<div>
<label for="name">اسمك</label>
<input type="text" id="name" name="name" required placeholder="أحمد محمد">
</div>
<div>
<label for="email">عنوان البريد الإلكتروني</label>
<input type="email" id="email" name="email" required placeholder="[email protected]">
</div>
<div>
<label for="message">الرسالة</label>
<textarea id="message" name="message" rows="5" required></textarea>
</div>
<button type="submit">إرسال الرسالة</button>
<!-- منطقة الملاحظات -->
<div id="form-feedback" aria-live="polite"></div>
</form>بعض الأشياء التي تستحق الملاحظة في هذا الترميز:
novalidateعلى عنصر النموذج يعطل فقاعات التحقق الأصلية للمتصفح، مما يمنحك السيطرة الكاملة على رسائل الخطأ في JavaScript.- الـ div
id="form-feedback"معaria-live="polite"هو المكان الذي ستظهر فيه رسائل النجاح والخطأ. خاصية ARIA تضمن إعلان قارئات الشاشة عن الملاحظات تلقائياً. - كل إدخال له كل من
id(لارتباط التسمية) وname(لحمولة النموذج).
التقاط حدث الإرسال
الخطوة الأولى في أي إرسال نماذج javascript هي اعتراض السلوك الافتراضي للمتصفح. تفعل ذلك من خلال الاستماع لحدث submit على عنصر النموذج واستدعاء event.preventDefault() فوراً.
const form = document.getElementById('contact-form');
form.addEventListener('submit', async function (event) {
event.preventDefault(); // إيقاف التنقل الافتراضي للصفحة
// التحقق الأساسي من جانب العميل
const name = form.elements['name'].value.trim();
const email = form.elements['email'].value.trim();
const message = form.elements['message'].value.trim();
if (!name || !email || !message) {
showFeedback('يرجى ملء جميع الحقول.', 'error');
return;
}
// المتابعة لإرسال البيانات (القسم التالي)
await submitForm({ name, email, message });
});من خلال فصل منطق التحقق عن استدعاء الشبكة، تحافظ على الكود قابل للقراءة وسهل التوسيع. الكلمة المفتاحية async على معالج الحدث تتيح لك استخدام await بداخلها، مما يجعل استدعاء Fetch API form data يبدو متزامناً ويتجنب سلاسل الوعود المتداخلة بعمق.
توجيه fetch() إلى نقطة نهاية Sendform
هنا يحدث العمل الحقيقي. بدلاً من بناء خادمك الخاص لاستقبال وتخزين وإعادة توجيه مساهمات النماذج، يمكنك استخدام Sendform كخلفية لك. بعد إنشاء نموذج في لوحة تحكم Sendform، تحصل على رابط نقطة نهاية فريد. هذا الرابط هو كل ما تحتاجه.
دالة الإرسال أدناه تستخدم واجهة FormData API لبناء الحمولة، والتي يقبلها Sendform أصلياً:
async function submitForm(data) {
// استبدل هذا الرابط برابط نقطة نهاية Sendform الفعلية
const SENDFORM_ENDPOINT = 'https://sendform.net/ar/YOUR_FORM_ID';
const formData = new FormData();
formData.append('name', data.name);
formData.append('email', data.email);
formData.append('message', data.message);
try {
const response = await fetch(SENDFORM_ENDPOINT, {
method: 'POST',
body: formData,
});
if (response.ok) {
showFeedback('شكراً لك! تم إرسال رسالتك.', 'success');
form.reset();
} else {
const errorData = await response.json().catch(() => ({}));
const errorMsg = errorData.message || 'حدث خطأ ما. يرجى المحاولة مرة أخرى.';
showFeedback(errorMsg, 'error');
}
} catch (networkError) {
showFeedback('خطأ في الشبكة. تحقق من اتصالك وحاول مرة أخرى.', 'error');
}
}القرارات الرئيسية المتخذة في هذا الكود:
- لا يتم تعيين رأس
Content-Typeيدوياً. عندما تمرر كائنFormDataكجسم، يقوم المتصفح بتعيين الحدود الصحيحة لـmultipart/form-dataتلقائياً. - فحص
response.okيغطي جميع رموز حالة HTTP 2xx، وليس فقط 200. هذا أكثر قوة من مقارنةresponse.status === 200. - الـ
try/catchالخارجي يلتقط فشل مستوى الشبكة (أخطاء DNS، حالة عدم الاتصال) التي لن يراهاresponse.okأبداً.
التعامل مع الاستجابة - رسائل النجاح والخطأ
إرسال البيانات هو نصف المهمة فقط. يحتاج المستخدمون إلى ملاحظات فورية وواضحة. دالة المساعدة showFeedback() المشار إليها أعلاه تكتب رسالة في div الملاحظات الذي أضفته إلى HTML:
function showFeedback(message, type) {
const feedbackEl = document.getElementById('form-feedback');
feedbackEl.textContent = message;
feedbackEl.className = type === 'success' ? 'feedback-success' : 'feedback-error';
}هذا بسيط عمداً. في مشروع حقيقي قد تستبدل textContent بمكون متحرك أو مكتبة إشعارات منبثقة، لكن النمط يبقى كما هو: تحديث DOM بناء على نتيجة استدعاء fetch().
للسيناريوهات الأكثر تقدماً، مثل إعادة التوجيه إلى صفحة شكر مخصصة أو تشغيل أتمتة لاحقة بعد الإرسال، اطلع على مقالتنا حول كيفية أتمتة سير عمل النماذج باستخدام webhooks وZapier وAPIs.
أفضل الممارسات والنصائح
جعل الكود يعمل شيء واحد. شحنه بطريقة تصمد في الإنتاج شيء آخر. إليك أهم النصائح التي يجب وضعها في الاعتبار:
- عطل زر الإرسال أثناء الطلب. اضبط
button.disabled = trueقبل استدعاءfetch()وأعد تمكينه في كتلةfinally. هذا يمنع الإرسالات المكررة إذا نقر المستخدم عدة مرات. - أظهر حالة التحميل. غير نص الزر إلى "جاري الإرسال..." أو أضف فئة دوارة أثناء الطلب قيد التنفيذ. المستخدمون الذين لا يرون أي ملاحظات غالباً ما يفترضون أنه لم يحدث شيء وينقرون مرة أخرى.
- تحقق من جانب الخادم أيضاً. التحقق من جانب العميل مخصص لتجربة المستخدم. Sendform وأي خدمة خلفية يجب أن تتعامل مع جميع البيانات الواردة كغير موثوقة.
- استخدم HTTPS في كل مكان. إرسال بيانات النموذج عبر HTTP العادي يعرض إدخال المستخدم أثناء النقل. نقاط نهاية Sendform هي HTTPS افتراضياً، لكن تأكد من أن صفحتك الخاصة تُقدم عبر HTTPS أيضاً.
- أضف حماية من الرسائل غير المرغوبة. حقل honeypot أو تكامل CAPTCHA يقلل الإرسالات غير المرغوبة بشكل كبير. للحصول على نظرة أعمق في هذا الموضوع، اطلع على دليلنا حول أفضل ممارسات حماية النماذج من الرسائل غير المرغوبة.
- اختبر مسار الخطأ عمداً. غير رابط نقطة النهاية مؤقتاً إلى شيء غير صالح وتأكد من ظهور رسالة الخطأ الخاصة بك. معظم المطورين يختبرون المسار السعيد فقط.
- احتفظ برابط نقطة النهاية خارج التحكم في الإصدار. إذا كان مشروعك مفتوح المصدر، احفظ نقطة نهاية Sendform في متغير بيئة أو ملف تكوين مدرج في
.gitignore.
مستخدمو المواقع الثابتة: إذا كان مشروعك هو موقع Hugo أو Eleventy أو HTML عادي بدون خادم، فإن نهج fetch() الموصوف هنا هو الطريقة الموصى بها. اقرأ المزيد في دليلنا إلى التعامل مع النماذج بدون خادم للمواقع الثابتة.
الخلاصة
استبدال إرسال النموذج الافتراضي باستدعاء fetch() هو أحد التحسينات عالية التأثير التي يمكنك إجراؤها على أي نموذج اتصال أو التقاط عملاء محتملين. النتيجة هي تجربة أسرع وأكثر احترافية تحافظ على المستخدمين في صفحتك وتمنحك السيطرة الكاملة على رسائل الملاحظات. اقرن ذلك مع نقطة نهاية Sendform وتلغي الحاجة إلى أي كود من جانب الخادم تماماً. نموذجك مباشر، وإرسالاتك تصل إلى صندوق البريد الوارد، ومستخدموك لا يرون أبداً إعادة تحميل صفحة مزعجة. أنشئ نقطة نهاية Sendform المجانية اليوم واحصل على أول إرسالة تُسلم في دقائق.
الأسئلة الشائعة
نعم. لأن fetch() يعمل بالكامل في المتصفح، فهو يعمل على مواقع HTML الثابتة ومشاريع JAMstack وأي منصة تقدم HTML. لا تحتاج إلى خادم خاص بك. المطلب الوحيد هو نقطة نهاية (مثل رابط Sendform) يمكنها استقبال طلب POST.
fetch() هو البديل الحديث لـ XMLHttpRequest. يستخدم Promises، ويدعم async/await، وله واجهة برمجة تطبيقات أنظف. للمشاريع الجديدة، fetch() مفضل دائماً. كلاهما يحقق نفس نتيجة إرسال نماذج ajax، لكن fetch() يتطلب كود أقل بكثير.
لا. عندما تمرر كائن FormData كـ body، يقوم المتصفح تلقائياً بتعيين Content-Type إلى multipart/form-data ويتضمن سلسلة الحدود الصحيحة. تعيينها يدوياً سيكسر الطلب فعلياً بحذف قيمة الحدود تلك.
سجل في Sendform، أنشئ نموذجاً جديداً في لوحة التحكم، وانسخ رابط نقطة النهاية المُولد. الصق هذا الرابط كهدف في استدعاء fetch(). ستُعاد توجيه الإرسالات إلى عنوان بريدك الإلكتروني المُكوّن فوراً.
فشل الشبكة يسبب رفض Promise الخاص بـ fetch()، والذي يتم التقاطه بواسطة كتلة try/catch الخارجية في كود المثال. يرى المستخدم رسالة "خطأ في الشبكة" التي حددتها. الإرسال لا يُقوم تلقائياً؛ يجب على المستخدم المحاولة مرة أخرى بمجرد استعادة الاتصال.