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
相关产品推荐
相关产品推荐

