فهرست مطالب

کدهای آماده برای طراحی فرم‌های مرحله‌ای (Multi-step Forms)

سلام رفیق برنامه‌نویس! اگه دنبال راهی هستی که فرم‌هات رو از حالت خسته‌کننده تک‌صفحه‌ای دربیاری و یه تجربه کاربری جذاب‌تر و کاربردی‌تر بسازی، اومدی سر جای درست. طراحی فرم‌های مرحله‌ای (Multi-step Forms) نه فقط نرخ تکمیل فرم رو بالا می‌بره، بلکه کاربرا رو هم کلافه نمی‌کنه. تو این مقاله قراره شیرجه بزنیم تو دنیای کدهای آماده برای ساخت این فرم‌ها، از صفر تا صد. تازه، اگه دنبال ابزارهای خفن برای توسعه پروژه‌هات هستی، یه سر به فروشگاه ابزارهای ما بزن؛ کلی چیز باحال اونجا منتظرته! برای مشاوره یا کمک فنی هم همیشه می‌تونی با ما تماس بگیری: 09202232789.

بریم که بترکونیم و فرم‌هامون رو حرفه‌ای‌تر کنیم! اگه هم دنبال یه منبع جامع برای برنامه‌نویسی هستی، یه سر به صفحه اصلی fa-tools.ir بزن.

✨ نقشه راه: فرم‌های مرحله‌ای در یک نگاه ✨

۱. چرا مرحله‌ای؟

➜ تجربه کاربری بهتر، نرخ تکمیل بالاتر، کاهش سردرگمی کاربر.

۲. اسکلت‌بندی (HTML)

➜ تقسیم فرم به بخش‌ها، دکمه‌های ناوبری، نوار پیشرفت.

۳. خوش‌تیپ کردن (CSS)

➜ استایل دادن به مراحل، دکمه‌ها، مخفی/نمایش مراحل.

۴. مغز متفکر (JavaScript)

➜ مدیریت مراحل، اعتبارسنجی، به‌روزرسانی نوار پیشرفت.

۵. نکات طلایی و عیب‌یابی

➜ UX، رسپانسیو، ذخیره پیشرفت، راه‌حل مشکلات رایج.

چرا اصلا فرم‌های مرحله‌ای؟ مزایاش چیه رفیق؟

تصور کن یه فرم طولانی داری با کلی فیلد و اطلاعات مختلف. اگه همه‌شون رو بریزی تو یه صفحه، کاربر با دیدنش شوکه میشه و احتمالا بی‌خیال میشه و میره. اما فرم‌های مرحله‌ای دقیقا برای حل همین مشکل اومدن تو بازی! این فرم‌ها اطلاعات رو به بخش‌های کوچیک و قابل هضم تقسیم می‌کنن. بذار چند تا از مزایای اصلیشون رو بگم:

  • کاهش بار شناختی: کاربر فقط یه بخش از اطلاعات رو می‌بینه و روش تمرکز می‌کنه. حس نمی‌کنه که یه کوه اطلاعات جلوشه.
  • افزایش نرخ تکمیل: وقتی کاربر پیشرفت خودش رو تو نوار پیشرفت می‌بینه، انگیزه بیشتری برای تکمیل فرم پیدا می‌کنه. این حس موفقیت، خیلی بهش کمک می‌کنه.
  • تجربه کاربری بهتر (UX): یه فرم مرحله‌ای خوش‌ساخت، روان و منطقی، حس خوبی به کاربر میده و تجربه کار با سایت یا اپلیکیشن رو لذت‌بخش‌تر می‌کنه.
  • امکان اعتبارسنجی بهتر: میتونی هر مرحله رو جداگانه اعتبارسنجی کنی. اینطوری کاربر اگه جایی اشتباه کرد، همونجا متوجه میشه و لازم نیست کل فرم رو پر کنه بعد ببینه اشکال داره.
  • جمع‌آوری داده هدفمند: می‌تونی اطلاعات رو مرحله به مرحله ذخیره کنی. حتی اگه کاربر فرم رو کامل نکرد، حداقل بخشی از اطلاعاتش رو داری.

بریم سراغ ساختار: اسکلت‌بندی فرم‌های چند مرحله‌ای

برای اینکه یه فرم مرحله‌ای داشته باشیم، اول باید یه اسکلت‌بندی درست و حسابی براش بچینیم. این اسکلت‌بندی شامل HTML، CSS و البته جاوااسکریپت میشه.

HTML پایه و اساس کار

فرمت HTML برای یه فرم مرحله‌ای خیلی ساده‌ست. هر مرحله رو داخل یه `div` جداگونه قرار میدیم و دکمه‌های “بعدی” و “قبلی” رو برای جابه‌جایی بین این `div`ها در نظر می‌گیریم. یه نوار پیشرفت هم معمولا برای نمایش وضعیت کاربر لازمه.

<!-- [برای کپی، روی کد کلیک کنید] -->
<div class="multi-step-form">
    <!-- نوار پیشرفت -->
    <div class="progress-bar-container">
        <div class="progress-bar" style="width: 0%;"></div>
    </div>

    <!-- مرحله ۱ -->
    <div class="form-step" id="step-1">
        <h3>اطلاعات شخصی</h3>
        <label for="name">نام:</label>
        <input type="text" id="name" name="name" required>
        <label for="email">ایمیل:</label>
        <input type="email" id="email" name="email" required>
        <button type="button" class="next-step-btn">مرحله بعدی</button>
    </div>

    <!-- مرحله ۲ -->
    <div class="form-step" id="step-2" style="display: none;">
        <h3>اطلاعات تماس</h3>
        <label for="phone">شماره تلفن:</label>
        <input type="tel" id="phone" name="phone">
        <label for="address">آدرس:</label>
        <input type="text" id="address" name="address">
        <button type="button" class="prev-step-btn">مرحله قبلی</button>
        <button type="button" class="next-step-btn">مرحله بعدی</button>
    </div>

    <!-- مرحله ۳ (نهایی) -->
    <div class="form-step" id="step-3" style="display: none;">
        <h3>تایید و ارسال</h3>
        <p>لطفاً اطلاعات وارد شده را بررسی و تایید کنید.</p>
        <button type="button" class="prev-step-btn">مرحله قبلی</button>
        <button type="submit">ارسال فرم</button>
    </div>
</div>

CSS برای خوش‌تیپ شدن فرم

حالا نوبت به استایل‌دهی می‌رسه. با CSS میتونیم فرممون رو قشنگ کنیم و مراحل رو طوری مخفی و آشکار کنیم که فقط مرحله فعلی معلوم باشه. نوار پیشرفت هم اینجا شکل می‌گیره. اگه مشکلی تو استایل‌دهی یا هر بخش فنی دیگه داشتی، یادت نره که می‌تونی با تیم فنی ما تماس بگیری.

<!-- [برای کپی، روی کد کلیک کنید] -->
<style>
.multi-step-form {
    max-width: 600px;
    margin: 50px auto;
    padding: 30px;
    border: 1px solid #ccc;
    border-radius: 8px;
    box-shadow: 0 0 15px rgba(0, 0, 0, 0.1);
    background-color: #fff;
    direction: rtl; /* برای راست‌چین کردن فرم */
    text-align: right;
}

.form-step {
    margin-bottom: 20px;
}

.form-step h3 {
    text-align: center;
    color: #333;
    margin-bottom: 25px;
    font-size: 24px;
}

.form-step label {
    display: block;
    margin-bottom: 8px;
    font-weight: bold;
    color: #555;
}

.form-step input[type="text"],
.form-step input[type="email"],
.form-step input[type="tel"] {
    width: calc(100% - 20px);
    padding: 12px;
    margin-bottom: 20px;
    border: 1px solid #ddd;
    border-radius: 5px;
    box-sizing: border-box;
    font-size: 16px;
}

.form-step button {
    background-color: #007bff;
    color: white;
    padding: 12px 25px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-size: 16px;
    margin-left: 10px;
    transition: background-color 0.3s ease;
}

.form-step button:hover {
    background-color: #0056b3;
}

.form-step .prev-step-btn {
    background-color: #6c757d;
}

.form-step .prev-step-btn:hover {
    background-color: #5a6268;
}

.progress-bar-container {
    width: 100%;
    background-color: #e0e0e0;
    border-radius: 5px;
    margin-bottom: 30px;
    height: 10px;
    overflow: hidden;
}

.progress-bar {
    height: 100%;
    background-color: #28a745;
    width: 0%;
    border-radius: 5px;
    transition: width 0.4s ease-in-out;
}

/* Responsive adjustments */
@media (max-width: 768px) {
    .multi-step-form {
        margin: 20px;
        padding: 20px;
    }
    .form-step button {
        width: 100%;
        margin-left: 0;
        margin-bottom: 10px;
    }
}
</style>

مغز متفکر: جاوااسکریپت برای مدیریت مراحل

اینجاست که جاوااسکریپت وارد عمل میشه و به فرم ما جون میده. وظیفه جاوااسکریپت اینه که مراحل رو مدیریت کنه، دکمه‌ها رو فعال و غیرفعال کنه، نوار پیشرفت رو به‌روزرسانی کنه و مهم‌تر از همه، اعتبارسنجی فیلدها رو انجام بده تا اطلاعات ناقص یا اشتباه ثبت نشن.

منطق قدم به قدم (Next/Prev)

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

<!-- [برای کپی، روی کد کلیک کنید] -->
<script>
document.addEventListener('DOMContentLoaded', function() {
    const formSteps = document.querySelectorAll('.form-step');
    const nextButtons = document.querySelectorAll('.next-step-btn');
    const prevButtons = document.querySelectorAll('.prev-step-btn');
    const progressBar = document.querySelector('.progress-bar');
    let currentStep = 0;

    function showStep(stepIndex) {
        formSteps.forEach((step, index) => {
            step.style.display = (index === stepIndex) ? 'block' : 'none';
        });
        updateProgressBar();
    }

    function updateProgressBar() {
        const progress = ((currentStep + 1) / formSteps.length) * 100;
        progressBar.style.width = `${progress}%`;
    }

    nextButtons.forEach(button => {
        button.addEventListener('click', () => {
            // اینجا میتونیم اعتبارسنجی رو قبل از رفتن به مرحله بعد انجام بدیم
            if (validateStep(currentStep)) {
                currentStep++;
                showStep(currentStep);
            }
        });
    });

    prevButtons.forEach(button => {
        button.addEventListener('click', () => {
            currentStep--;
            showStep(currentStep);
        });
    });

    // تابع اعتبارسنجی (بعداً کامل‌تر میشه)
    function validateStep(stepIndex) {
        const currentFormStep = formSteps[stepIndex];
        let isValid = true;
        const requiredInputs = currentFormStep.querySelectorAll('input[required]');
        requiredInputs.forEach(input => {
            if (!input.value.trim()) {
                input.style.border = '1px solid red';
                isValid = false;
            } else {
                input.style.border = '1px solid #ddd';
            }
        });
        if (!isValid) {
            alert('لطفاً همه فیلدهای الزامی را پر کنید.');
        }
        return isValid;
    }

    showStep(currentStep); // نمایش اولین مرحله
});
</script>

اعتبارسنجی (Validation) هر مرحله

یکی از مهم‌ترین بخش‌های هر فرم، اعتبارسنجی اطلاعات ورودی هست. ما نمی‌خوایم کاربر با اطلاعات ناقص یا غلط فرم رو سابمیت کنه. تابع `validateStep` رو تو کد بالا دیدی؟ اونجا می‌تونیم یه لاجیک درست و حسابی برای اعتبارسنجی هر فیلد بنویسیم.

<!-- [برای کپی، روی کد کلیک کنید] -->
// تابع کامل‌تر اعتبارسنجی برای هر مرحله
function validateStep(stepIndex) {
    const currentFormStep = formSteps[stepIndex];
    let isValid = true;
    const inputs = currentFormStep.querySelectorAll('input[required], input[type="email"], input[type="tel"]');

    inputs.forEach(input => {
        input.style.border = '1px solid #ddd'; // ریست کردن استایل خطا
        if (input.hasAttribute('required') && !input.value.trim()) {
            input.style.border = '1px solid red';
            isValid = false;
        } else if (input.type === 'email' && !/S+@S+.S+/.test(input.value)) {
            input.style.border = '1px solid red';
            isValid = false;
        } else if (input.type === 'tel' && input.value.trim() && !/^+?d{10,15}$/.test(input.value)) {
            // اعتبارسنجی ساده برای شماره تلفن (میتونه پیچیده‌تر باشه)
            input.style.border = '1px solid orange'; // خطای هشدار، نه الزاما خطا
        }
    });

    if (!isValid) {
        alert('لطفاً فیلدهای مشخص شده را به درستی پر کنید.');
    }
    return isValid;
}

نوار پیشرفت (Progress Bar) که کاربر گم نشه

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

<!-- [برای کپی، روی کد کلیک کنید] -->
function updateProgressBar() {
    // محاسبه درصد پیشرفت بر اساس مرحله فعلی و تعداد کل مراحل
    const progress = ((currentStep + 1) / formSteps.length) * 100;
    progressBar.style.width = `${progress}%`;
    // می‌تونی اینجا متن نوار پیشرفت رو هم آپدیت کنی
    // مثلا: progressBar.textContent = `${Math.round(progress)}%`;
}

کدهای آماده و فریم‌ورک‌های محبوب برای راحتی کار

خب، اگه حوصله کدنویسی از صفر رو نداری یا می‌خوای پروژه‌ت سریع‌تر پیش بره، می‌تونی از فریم‌ورک‌ها یا پلاگین‌های آماده استفاده کنی. فریم‌ورک‌هایی مثل React، Vue.js یا حتی کتابخونه‌هایی مثل jQuery کلی پلاگین آماده برای ساخت فرم‌های مرحله‌ای دارن. اما ما اینجا یه مثال کامل با جاوااسکریپت خالص (Vanilla JS) رو آوردم که کاملا مستقل و قابل فهم باشه.

یه نمونه کاربردی با جاوااسکریپت خالص (Vanilla JS)

اینجا یه کد کامل HTML، CSS و JS رو آوردم که با کپی کردنش می‌تونی یه فرم مرحله‌ای ساده اما کاربردی داشته باشی. این کد کاملا رسپانسیو طراحی شده و روی موبایل و تبلت و لپتاپ و حتی تلویزیون به درستی نمایش داده میشه.

<!-- [برای کپی، روی کد کلیک کنید] -->
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>فرم چند مرحله‌ای</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #f4f7f6;
            margin: 0;
            padding: 20px;
            display: flex;
            justify-content: center;
            align-items: flex-start;
            min-height: 100vh;
            box-sizing: border-box;
            direction: rtl; /* برای راست‌چین کردن کل صفحه */
        }
        .multi-step-form-container {
            max-width: 600px;
            width: 100%;
            background-color: #ffffff;
            padding: 30px;
            border-radius: 12px;
            box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1);
            border: 1px solid #e0e0e0;
        }
        .multi-step-form h2 {
            text-align: center;
            color: #2c3e50;
            margin-bottom: 30px;
            font-size: 28px;
        }
        .progress-bar-container {
            width: 100%;
            background-color: #e0e0e0;
            border-radius: 5px;
            margin-bottom: 35px;
            height: 12px;
            overflow: hidden;
            position: relative;
        }
        .progress-bar {
            height: 100%;
            background-color: #28a745;
            width: 0%;
            border-radius: 5px;
            transition: width 0.5s ease-in-out;
            display: flex;
            justify-content: center;
            align-items: center;
            color: white;
            font-size: 10px;
            font-weight: bold;
        }
        .form-step {
            margin-bottom: 25px;
            border: 1px solid #f0f0f0;
            padding: 20px;
            border-radius: 8px;
            background-color: #fdfdfd;
        }
        .form-step h3 {
            text-align: right;
            color: #34495e;
            margin-bottom: 20px;
            font-size: 22px;
        }
        .form-step label {
            display: block;
            margin-bottom: 10px;
            font-weight: bold;
            color: #555;
            font-size: 16px;
        }
        .form-step input[type="text"],
        .form-step input[type="email"],
        .form-step input[type="tel"],
        .form-step textarea {
            width: calc(100% - 24px); /* Account for padding */
            padding: 12px;
            margin-bottom: 20px;
            border: 1px solid #dcdcdc;
            border-radius: 6px;
            box-sizing: border-box;
            font-size: 16px;
            transition: border-color 0.3s ease;
        }
        .form-step input:focus, .form-step textarea:focus {
            border-color: #007bff;
            outline: none;
            box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
        }
        .form-step button {
            background-color: #007bff;
            color: white;
            padding: 12px 28px;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 17px;
            margin-left: 10px;
            transition: background-color 0.3s ease, transform 0.2s ease;
            min-width: 120px;
        }
        .form-step button:hover {
            background-color: #0056b3;
            transform: translateY(-2px);
        }
        .form-step .prev-step-btn {
            background-color: #6c757d;
        }
        .form-step .prev-step-btn:hover {
            background-color: #5a6268;
        }
        .form-step .submit-btn {
            background-color: #28a745;
        }
        .form-step .submit-btn:hover {
            background-color: #218838;
        }
        .error-message {
            color: #dc3545;
            font-size: 14px;
            margin-top: -15px;
            margin-bottom: 15px;
            display: block;
            text-align: right;
        }

        /* Responsive adjustments */
        @media (max-width: 768px) {
            .multi-step-form-container {
                margin: 10px;
                padding: 20px;
            }
            .form-step button {
                width: calc(50% - 5px); /* Two buttons per row */
                margin-left: 0;
                margin-bottom: 10px;
            }
            .form-step button:nth-last-child(2) { /* Adjust for last two buttons */
                 margin-right: 10px;
            }
        }
        @media (max-width: 480px) {
            .form-step button {
                width: 100%;
                margin-left: 0;
                margin-bottom: 10px;
            }
        }
    </style>
</head>
<body>

<div class="multi-step-form-container">
    <div class="multi-step-form">
        <h2>ثبت‌نام گام به گام</h2>

        <!-- نوار پیشرفت -->
        <div class="progress-bar-container">
            <div class="progress-bar"><span id="progress-text">0%</span></div>
        </div>

        <!-- مرحله ۱: اطلاعات شخصی -->
        <div class="form-step active" id="step-1">
            <h3>مرحله ۱: اطلاعات شخصی شما</h3>
            <label for="first_name">نام:</label>
            <input type="text" id="first_name" name="first_name" required data-error="نام الزامی است.">
            <span class="error-message"></span>

            <label for="last_name">نام خانوادگی:</label>
            <input type="text" id="last_name" name="last_name" required data-error="نام خانوادگی الزامی است.">
            <span class="error-message"></span>

            <button type="button" class="next-step-btn">مرحله بعدی</button>
        </div>

        <!-- مرحله ۲: اطلاعات تماس -->
        <div class="form-step" id="step-2" style="display: none;">
            <h3>مرحله ۲: نحوه ارتباط با شما</h3>
            <label for="email">ایمیل:</label>
            <input type="email" id="email" name="email" required data-error="ایمیل الزامی و معتبر نیست.">
            <span class="error-message"></span>

            <label for="phone">شماره تلفن:</label>
            <input type="tel" id="phone" name="phone" pattern="[0-9]{10,15}" data-error="شماره تلفن معتبر نیست.">
            <span class="error-message"></span>

            <button type="button" class="prev-step-btn">مرحله قبلی</button>
            <button type="button" class="next-step-btn">مرحله بعدی</button>
        </div>

        <!-- مرحله ۳: اطلاعات تکمیلی -->
        <div class="form-step" id="step-3" style="display: none;">
            <h3>مرحله ۳: توضیحات و نظر</h3>
            <label for="comments">نظرات یا توضیحات:</label>
            <textarea id="comments" name="comments" rows="5"></textarea>
            <span class="error-message"></span>

            <label for="agreement">
                <input type="checkbox" id="agreement" name="agreement" required data-error="پذیرش شرایط الزامی است.">
                من با <a href="#">شرایط و ضوابط</a> موافقم.
            </label>
            <span class="error-message"></span>

            <button type="button" class="prev-step-btn">مرحله قبلی</button>
            <button type="submit" class="submit-btn">ثبت نهایی</button>
        </div>
    </div>
</div>

<script>
    document.addEventListener('DOMContentLoaded', function() {
        const formSteps = document.querySelectorAll('.form-step');
        const nextButtons = document.querySelectorAll('.next-step-btn');
        const prevButtons = document.querySelectorAll('.prev-step-btn');
        const progressBar = document.querySelector('.progress-bar');
        const progressText = document.getElementById('progress-text');
        let currentStep = 0;

        function showStep(stepIndex) {
            formSteps.forEach((step, index) => {
                step.style.display = (index === stepIndex) ? 'block' : 'none';
                step.classList.remove('active'); // remove active class from all
            });
            formSteps[stepIndex].classList.add('active'); // add active class to current
            currentStep = stepIndex;
            updateProgressBar();
        }

        function updateProgressBar() {
            const progress = ((currentStep + 1) / formSteps.length) * 100;
            progressBar.style.width = `${progress}%`;
            progressText.textContent = `${Math.round(progress)}%`;
        }

        function validateStep(stepIndex) {
            const currentFormStep = formSteps[stepIndex];
            let isValid = true;
            const inputs = currentFormStep.querySelectorAll('input[required], input[type="email"], input[type="tel"], textarea[required], input[type="checkbox"][required]');

            inputs.forEach(input => {
                const errorMessageSpan = input.parentNode.querySelector('.error-message');
                errorMessageSpan.textContent = ''; // Clear previous errors
                input.style.borderColor = '#dcdcdc'; // Reset border color

                if (input.hasAttribute('required') && (input.type === 'checkbox' ? !input.checked : !input.value.trim())) {
                    input.style.borderColor = '#dc3545';
                    errorMessageSpan.textContent = input.dataset.error || 'این فیلد الزامی است.';
                    isValid = false;
                } else if (input.type === 'email' && input.value.trim() && !/S+@S+.S+/.test(input.value)) {
                    input.style.borderColor = '#dc3545';
                    errorMessageSpan.textContent = input.dataset.error || 'فرمت ایمیل نامعتبر است.';
                    isValid = false;
                } else if (input.type === 'tel' && input.value.trim() && !input.value.match(input.pattern)) {
                    input.style.borderColor = '#ffc107'; // Warning color
                    errorMessageSpan.textContent = input.dataset.error || 'فرمت شماره تلفن صحیح نیست.';
                    //isValid = false; // Decided not to block, just warn for tel for flexibility
                }
            });
            return isValid;
        }

        nextButtons.forEach(button => {
            button.addEventListener('click', () => {
                if (validateStep(currentStep)) {
                    showStep(currentStep + 1);
                }
            });
        });

        prevButtons.forEach(button => {
            button.addEventListener('click', () => {
                showStep(currentStep - 1);
            });
        });

        // Handle form submission (e.g., via AJAX)
        const submitButton = document.querySelector('.submit-btn');
        if (submitButton) {
            submitButton.addEventListener('click', function(event) {
                event.preventDefault(); // Prevent default form submission
                if (validateStep(currentStep)) {
                    alert('فرم با موفقیت ارسال شد! (این یک شبیه سازی است)');
                    // اینجا میتونی اطلاعات فرم رو جمع کنی و با AJAX به سرور بفرستی
                    const formData = new FormData(document.querySelector('.multi-step-form-container form')); // اگه فرم اصلی داشتیم
                    const data = {};
                    formSteps.forEach(step => {
                        step.querySelectorAll('input, textarea').forEach(input => {
                            if (input.name) {
                                data[input.name] = input.type === 'checkbox' ? input.checked : input.value;
                            }
                        });
                    });
                    console.log('Collected Data:', data);
                    // مثال ارسال با fetch:
                    /*
                    fetch('/api/submit-form', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                        },
                        body: JSON.stringify(data),
                    })
                    .then(response => response.json())
                    .then(result => {
                        console.log('Success:', result);
                        alert('فرم شما با موفقیت ثبت شد!');
                        // redirect or show success message
                    })
                    .catch(error => {
                        console.error('Error:', error);
                        alert('مشکلی در ثبت فرم پیش آمد.');
                    });
                    */
                }
            });
        }

        showStep(currentStep); // نمایش اولین مرحله بعد از بارگذاری
    });
</script>

</body>
</html>

نکات طلایی برای طراحی یه فرم مرحله‌ای بی‌نقص

رفیق، ساخت یه فرم مرحله‌ای فقط کدنویسی نیست. باید به تجربه کاربری (UX) هم حسابی دقت کنی. این چند تا نکته رو همیشه یادت باشه:

  • وضوح در هر مرحله: هر مرحله باید هدف مشخصی داشته باشه و عنوان واضحی داشته باشه. کاربر نباید گیج بشه که الان اینجا چی باید پر کنه.
  • بازخورد بصری: حتما از نوار پیشرفت یا نشانگرهای دیگه برای نشون دادن موقعیت کاربر استفاده کن.
  • اعتبارسنجی لحظه‌ای: سعی کن اعتبارسنجی رو همون لحظه که کاربر فیلد رو پر می‌کنه یا ازش خارج میشه انجام بدی (Real-time Validation)، نه اینکه صبر کنی تا دکمه “بعدی” رو بزنه.
  • ذخیره پیشرفت (Save Progress): اگه فرمت خیلی طولانی یا پیچیده‌ست، یه قابلیت برای ذخیره پیشرفت کاربر (مثلاً با Local Storage) در نظر بگیر تا اگه از صفحه خارج شد، اطلاعاتش نپره.
  • رسپانسیو بودن: فرمت باید روی تمام دستگاه‌ها (موبایل، تبلت، دسکتاپ) بدون مشکل کار کنه و ظاهرش به هم نریزه. همونطور که تو کد بالا دیدی، با Media Queries این کار انجام میشه.
  • مسیریابی واضح: دکمه‌های “قبلی” و “بعدی” باید همیشه واضح و در دسترس باشن.
  • آزمایش، آزمایش، آزمایش: همیشه فرمت رو با افراد مختلف تست کن تا اشکالات احتمالی رو پیدا کنی و رفع کنی.

چک لیست طراحی فرم مرحله‌ای

ویژگی توضیحات
نوار پیشرفت برای نمایش وضعیت تکمیل فرم به کاربر.
اعتبارسنجی دقیق برای هر فیلد و هر مرحله به صورت جداگانه.
دکمه‌های ناوبری واضح “بعدی” و “قبلی” با لیبل‌های مشخص.
قابلیت ذخیره موقت با Local Storage یا Session Storage برای فرم‌های طولانی.
رسپانسیو بودن سازگاری کامل با موبایل، تبلت و دسکتاپ.
بازخورد خطا پیام‌های خطای واضح و کاربرپسند در کنار فیلد مربوطه.

سناریوهای خاص: فرم‌های پیشرفته‌تر

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

  • منطق شرطی (Conditional Logic): اگه کاربر تو یه مرحله گزینه‌ای رو انتخاب کرد، یه فیلد یا یه مرحله جدید نمایش داده بشه وگرنه مخفی بمونه. این کار با دستکاری DOM و منطق جاوااسکریپت کمی پیشرفته‌تر ممکنه.
  • ارسال با AJAX: به جای سابمیت کردن کل فرم به روش سنتی، می‌تونیم با AJAX اطلاعات هر مرحله رو به صورت جداگانه یا کل فرم رو در انتها بدون بارگذاری مجدد صفحه ارسال کنیم.
  • نمایش خلاصه نهایی: قبل از ارسال نهایی، یه مرحله اضافه کنیم که خلاصه همه اطلاعات وارد شده رو به کاربر نشون بده تا تایید کنه.
  • پشتیبانی از فایل‌ها: اگه نیاز به آپلود فایل داری، باید منطق آپلود فایل رو هم با جاوااسکریپت مدیریت کنی (مثلا با FormData و Fetch API).

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

طبیعیه که تو مسیر کدنویسی یهو با مشکلاتی روبرو بشی. نگران نباش، اینا چند تا از رایج‌ترین مشکلاتی هستن که ممکنه باهاشون برخورد کنی و چجوری میشه حلشون کرد:

  • مشکل: دکمه‌های “بعدی/قبلی” کار نمی‌کنن.

    راه‌حل:

    1. مطمئن شو که `class`های `next-step-btn` و `prev-step-btn` رو به درستی تو HTML اضافه کردی.
    2. تو جاوااسکریپت، چک کن که `querySelectorAll` به درستی این دکمه‌ها رو پیدا می‌کنه.
    3. مطمئن شو که `addEventListener(‘click’, …)` به درستی به دکمه‌ها متصل شده.
    4. کنسول مرورگر رو برای خطاهای جاوااسکریپت چک کن.
  • مشکل: اعتبارسنجی (Validation) فیلدها انجام نمیشه یا ارورها نمایش داده نمی‌شن.

    راه‌حل:

    1. مطمئن شو که تابع `validateStep()` قبل از رفتن به مرحله بعدی فراخونی میشه (مثل کد ما).
    2. چک کن که انتخابگرهای CSS/JS برای پیدا کردن فیلدها و پیام‌های خطا (مثلا `input[required]`, `.error-message`) صحیح باشن.
    3. پیام‌های خطا رو با `display: block` نشون بده تا دیده بشن.
    4. مطمئن شو که `return isValid;` به درستی وضعیت اعتبارسنجی رو برمی‌گردونه.
  • مشکل: نوار پیشرفت (Progress Bar) به‌روزرسانی نمیشه.

    راه‌حل:

    1. مطمئن شو که `updateProgressBar()` هر بار که `showStep()` فراخونی میشه، اجرا میشه.
    2. چک کن که `progressBar.style.width` به درستی مقدار درصد رو دریافت می‌کنه (مثلاً `progress + ‘%’`).
    3. اشکال املایی: `progress-bar` و `progress-bar-container` رو دوباره بررسی کن.
  • مشکل: فرم روی موبایل یا تبلت به هم ریخته.

    راه‌حل:

    1. مطمئن شو که تگ `<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>` تو بخش `<head>` صفحه هست.
    2. از Media Queries تو CSS برای تنظیمات خاص موبایل و تبلت استفاده کن (مثل نمونه کدمون).
    3. از واحدهای رساپونسیو مثل `%`، `vw`، `vh` و `rem` به جای `px` ثابت استفاده کن.
    4. از `flexbox` یا `grid` برای چیدمان‌های انعطاف‌پذیر استفاده کن.

نتیجه‌گیری: فرم‌های مرحله‌ای، یه گام بزرگ به جلو

همونطور که دیدی رفیق، طراحی فرم‌های مرحله‌ای (Multi-step Forms) یه راهکار عالی برای بهبود تجربه کاربری و بالا بردن نرخ تکمیل فرم‌هاست. با استفاده از کدهای آماده HTML، CSS و جاوااسکریپت که اینجا باهم بررسی کردیم، می‌تونی به راحتی این قابلیت رو به پروژه‌هات اضافه کنی. یادت باشه که کلید موفقیت، تمرکز روی تجربه کاربری، اعتبارسنجی دقیق و البته رسپانسیو بودن فرم هست. امیدوارم این مقاله برات مفید بوده باشه و بتونی باهاش فرم‌های جذاب و کاربردی بسازی. بزن بریم!

پرسش‌های متداول (FAQ)

فرم مرحله‌ای (Multi-step Form) دقیقا چیه؟

فرم مرحله‌ای نوعی فرم آنلاینه که اطلاعات رو به چند بخش کوچک‌تر تقسیم می‌کنه و کاربر مرحله به مرحله اونها رو تکمیل می‌کنه. این کار باعث میشه فرم کمتر خسته‌کننده به نظر بیاد و نرخ تکمیل اون افزایش پیدا کنه.

چرا باید از فرم‌های مرحله‌ای استفاده کنم؟

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

آیا میشه اطلاعات فرم رو توی هر مرحله ذخیره کرد؟

بله، با استفاده از قابلیت‌های ذخیره‌سازی سمت کاربر مثل Local Storage یا Session Storage در جاوااسکریپت، می‌تونی اطلاعات هر مرحله رو به صورت موقت ذخیره کنی تا اگه کاربر از صفحه خارج شد، پیشرفتش حفظ بشه.

چطور فرم مرحله‌ای رو رسپانسیو کنم؟

با استفاده از Media Queries در CSS می‌تونی استایل‌های متفاوتی برای اندازه‌های مختلف صفحه (موبایل، تبلت، دسکتاپ) تعریف کنی. همچنین استفاده از واحدهای نسبی مثل درصد یا `rem` و استفاده از Flexbox یا Grid در CSS به رسپانسیو بودن فرم کمک زیادی می‌کنه.

آیا برای ساخت فرم مرحله‌ای حتما باید از فریم‌ورک خاصی استفاده کنم؟

خیر، همونطور که تو این مقاله دیدی، می‌تونی با جاوااسکریپت خالص (Vanilla JS) هم یه فرم مرحله‌ای کاربردی و کامل بسازی. البته فریم‌ورک‌هایی مثل React، Vue یا کتابخانه‌هایی مثل jQuery پلاگین‌های آماده‌ای دارن که کار رو برات راحت‌تر می‌کنن.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *