You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 5.5:Ajax提交含动态生成字段的多问题表单

如何通过Ajax收集动态添加的问题与答案并提交到Laravel控制器

我来帮你搞定这个Ajax提交的问题!核心是要给表单元素设置正确的数组式name属性,然后用JS把所有问题和对应的答案整理成结构化数据,再通过Ajax发送到Laravel控制器。下面分步骤来实现:

1. 修正表单元素的Name属性(静态+动态)

首先把初始表单的元素name改成数组格式,这样Laravel能自动识别分组数据,同时给关键元素加类名方便JS操作:

<form action="{{route('questions.store')}}" class="form" id="form" method="POST" enctype="multipart/form-data">
    {{csrf_field()}}
    <div class="q">
        <div class="box question-block">
            <div class="box-header">
                <strong>سوال</strong> <strong class="question-number">1</strong>
            </div>
            <div class="question">
                <!-- 问题文本:按索引分组 -->
                <div class="input-group">
                    <span class="input-group-addon">؟</span>
                    <input type="text" class="form-control question-text" placeholder="متن سوال" name="questions[0][text]">
                </div>
                <!-- 答案组:关联到对应问题 -->
                <div class="input-group answer-group">
                    <!-- 答案1 -->
                    <span class="input-group-addon">
                        <input value="1" type="checkbox" class="is-acceptable" name="questions[0][answers][0][is_acceptable]" checked>
                    </span>
                    <input type="text" class="form-control answer-text" required placeholder=" پاسخ اول" name="questions[0][answers][0][text]">
                    <!-- 答案2 -->
                    <span class="input-group-addon">
                        <input value="0" type="checkbox" class="is-acceptable" name="questions[0][answers][1][is_acceptable]">
                    </span>
                    <input type="text" class="form-control answer-text" placeholder=" پاسخ دوم" name="questions[0][answers][1][text]">
                    <!-- 答案3 -->
                    <span class="input-group-addon">
                        <input value="0" type="checkbox" class="is-acceptable" name="questions[0][answers][2][is_acceptable]">
                    </span>
                    <input type="text" class="form-control answer-text" placeholder=" پاسخ سوم" name="questions[0][answers][2][text]">
                    <!-- 答案4 -->
                    <span class="input-group-addon">
                        <input value="0" type="checkbox" class="is-acceptable" name="questions[0][answers][3][is_acceptable]">
                    </span>
                    <input type="text" class="form-control answer-text" placeholder=" پاسخ چهارم" name="questions[0][answers][3][text]">
                </div>
            </div>
        </div>
    </div>
    <div>
        <button type="button" id="add" class="btn btn-warning">more questions</button>
        <button type="button" id="ajax-submit" class="btn submit btn-primary">submit via Ajax</button>
    </div>
</form>

这里把重复的id="number"改成了类,避免DOM ID冲突。

2. 修改动态添加问题的脚本

动态添加时,通过已有问题的数量计算索引,生成对应数组格式的name属性,用模板字符串让代码更清晰:

<script>
$('#add').click(function () {
    // 获取当前问题数量,作为新问题的索引
    const questionIndex = $('.question-block').length;
    const questionNumber = questionIndex + 1;

    const newQuestion = `
        <div class="box question-block">
            <div class="box-header">
                <strong>سوال</strong> <strong class="question-number">${questionNumber}</strong>
            </div>
            <div class="question">
                <div class="input-group">
                    <span class="input-group-addon">؟</span>
                    <input type="text" class="form-control question-text" placeholder="متن سوال" name="questions[${questionIndex}][text]">
                </div>
                <div class="input-group answer-group">
                    <span class="input-group-addon">
                        <input value="1" type="checkbox" class="is-acceptable" name="questions[${questionIndex}][answers][0][is_acceptable]" checked>
                    </span>
                    <input type="text" class="form-control answer-text" required placeholder=" پاسخ اول" name="questions[${questionIndex}][answers][0][text]">
                    <span class="input-group-addon">
                        <input value="0" type="checkbox" class="is-acceptable" name="questions[${questionIndex}][answers][1][is_acceptable]">
                    </span>
                    <input type="text" class="form-control answer-text" placeholder=" پاسخ دوم" name="questions[${questionIndex}][answers][1][text]">
                    <span class="input-group-addon">
                        <input value="0" type="checkbox" class="is-acceptable" name="questions[${questionIndex}][answers][2][is_acceptable]">
                    </span>
                    <input type="text" class="form-control answer-text" placeholder=" پاسخ سوم" name="questions[${questionIndex}][answers][2][text]">
                    <span class="input-group-addon">
                        <input value="0" type="checkbox" class="is-acceptable" name="questions[${questionIndex}][answers][3][is_acceptable]">
                    </span>
                    <input type="text" class="form-control answer-text" placeholder=" پاسخ چهارم" name="questions[${questionIndex}][answers][3][text]">
                </div>
            </div>
        </div>
    `;

    $('.q').append(newQuestion);
});
</script>

3. 编写Ajax提交的脚本

手动收集所有问题和答案数据(避免复选框未选中不提交的问题),然后通过FormData发送:

<script>
$('#ajax-submit').click(function (e) {
    e.preventDefault(); // 阻止默认表单提交

    // 初始化FormData,带上CSRF令牌
    const formData = new FormData();
    formData.append('_token', '{{ csrf_token() }}');

    // 收集所有问题数据
    const questions = [];
    let isValid = true;

    $('.question-block').each(function (qIndex) {
        const questionText = $(this).find('.question-text').val();
        if (!questionText) {
            alert('请填写第' + (qIndex+1) + '个问题的文本!');
            isValid = false;
            return false;
        }

        // 收集当前问题的答案
        const answers = [];
        $(this).find('.answer-text').each(function (aIndex) {
            const answerText = $(this).val();
            if (!answerText) return;

            // 获取复选框状态
            const isAcceptable = $(this).closest('.input-group').find('.is-acceptable').eq(aIndex).is(':checked') ? 1 : 0;
            answers.push({
                text: answerText,
                is_acceptable: isAcceptable
            });
        });

        if (answers.length === 0) {
            alert('第' + (qIndex+1) + '个问题至少填写一个答案!');
            isValid = false;
            return false;
        }

        questions.push({
            text: questionText,
            answers: answers
        });
    });

    if (!isValid || questions.length === 0) return;

    // 将问题数组转为JSON字符串添加到FormData
    formData.append('questions', JSON.stringify(questions));

    // 发送Ajax请求
    $.ajax({
        url: '{{ route('questions.store') }}',
        type: 'POST',
        data: formData,
        processData: false,
        contentType: false,
        success: function (response) {
            alert('提交成功!');
            // 重置表单,只保留第一个空问题
            $('#form')[0].reset();
            $('.q').html($('.question-block:first').clone());
        },
        error: function (xhr) {
            alert('提交失败,请检查数据!');
            console.log(xhr.responseText); // 打印错误信息便于调试
        }
    });
});
</script>

4. Laravel控制器接收并处理数据

在QuestionsController的store方法中,可以这样获取和处理数据:

public function store(Request $request)
{
    // 验证提交的数据
    $request->validate([
        'questions' => 'required|string',
    ]);

    // 解析JSON字符串为数组
    $questions = json_decode($request->input('questions'), true);

    // 再次验证数组结构(可选但更安全)
    foreach ($questions as $qData) {
        \Validator::make($qData, [
            'text' => 'required|string',
            'answers' => 'required|array|min:1',
            'answers.*.text' => 'required|string',
            'answers.*.is_acceptable' => 'required|integer|in:0,1'
        ])->validate();
    }

    // 存储问题和答案到数据库(示例)
    foreach ($questions as $qData) {
        // 创建问题(如果关联职位,记得加上职位ID)
        $question = \App\Question::create([
            'text' => $qData['text'],
            // 'job_post_id' => $yourJobPostId
        ]);

        // 创建关联的答案
        foreach ($qData['answers'] as $aData) {
            $question->answers()->create($aData);
        }
    }

    return response()->json(['message' => 'Questions added successfully!'], 200);
}

这样整个流程就完整了:从动态添加表单元素,到收集结构化数据,再到Ajax提交和控制器处理,都能正常工作。

内容的提问来源于stack exchange,提问作者Vahid Saberi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:03:44