Yii2技术问题:如何保存Typeahead多选参考编号的数据
在Yii2中保存Typeahead多选的参考编号
我来帮你搞定这个问题——Typeahead本身默认是单选组件,要实现多选并保存,核心是前端收集选中的参考编号,然后把数据传给Yii2后端完成持久化。下面是一步步的具体实现方案:
一、前端:处理多选选中事件并收集数据
首先,你需要在页面上添加一个隐藏输入框(用来存储所有选中的参考编号,用JSON格式存数组方便后端解析),同时可以添加一个区域显示已选标签(方便用户查看和删除):
<!-- 隐藏输入框:存储选中的参考编号数组 --> <input type="hidden" id="selected-refs" name="selected_refs[]"> <!-- 已选标签显示区域 --> <div id="selected-tags" class="mt-2"></div>
然后修改你的Typeahead初始化代码,监听typeahead:selected事件,把选中的项添加到隐藏框,同时渲染已选标签:
var surveyReferences = new Bloodhound({ datumTokenizer: Bloodhound.tokenizers.obj.whitespace('ref_no'), queryTokenizer: Bloodhound.tokenizers.whitespace, prefetch: 'survey', remote: { url: 'survey/?q=%QUERY', wildcard: '%QUERY' } }); $('#the-ref-id').typeahead(null, { limit: 50, name: 'ref-numbers', display: 'ref_no', source: surveyReferences, templates: { suggestion: function(data) { return '<p>' + data.ref_no + '</p>'; // 补全你的模板内容 } } }).on('typeahead:selected', function(event, datum) { // 从隐藏框获取已选数组(首次为空则初始化空数组) let selectedRefs = $('#selected-refs').val() ? JSON.parse($('#selected-refs').val()) : []; // 避免重复添加相同的参考编号 if (!selectedRefs.includes(datum.ref_no)) { selectedRefs.push(datum.ref_no); $('#selected-refs').val(JSON.stringify(selectedRefs)); // 在页面渲染已选标签(带删除按钮) $('#selected-tags').append(` <span class="badge bg-secondary me-1"> ${datum.ref_no} <button class="btn-close btn-close-white ms-1 remove-tag" data-ref="${datum.ref_no}"></button> </span> `); } // 清空输入框,方便继续选择下一个 $(this).typeahead('val', ''); }); // 处理标签删除逻辑 $(document).on('click', '.remove-tag', function() { const targetRef = $(this).data('ref'); let selectedRefs = JSON.parse($('#selected-refs').val()); // 过滤掉要删除的参考编号 selectedRefs = selectedRefs.filter(ref => ref !== targetRef); $('#selected-refs').val(JSON.stringify(selectedRefs)); // 删除页面上的标签 $(this).parent('.badge').remove(); });
二、Yii2后端:接收并保存数据
接下来在Yii2控制器中编写处理保存的动作,接收前端传过来的参考编号数组,根据你的业务需求选择保存方式:
方式1:保存到JSON类型字段
如果你的表中有一个JSON类型的字段(比如refs)用来存储多个参考编号:
public function actionSaveReferences() { if (Yii::$app->request->isPost) { // 获取前端提交的选中数组(默认空数组防止报错) $selectedRefs = Yii::$app->request->post('selected_refs', []); // 验证数据:比如检查参考编号是否存在(可选但推荐) $validRefs = []; foreach ($selectedRefs as $ref) { // 假设你有一个Reference模型,检查ref_no是否合法 if (Reference::find()->where(['ref_no' => $ref])->exists()) { $validRefs[] = $ref; } } // 保存到模型(这里假设是Survey模型,替换成你的实际模型) $model = new Survey(); // 或者是更新现有模型:$model = Survey::findOne($id); $model->refs = json_encode($validRefs); if ($model->save(false)) { // 若已有模型验证,可去掉false return $this->asJson([ 'success' => true, 'message' => '参考编号保存成功' ]); } return $this->asJson([ 'success' => false, 'message' => '保存失败,请重试' ]); } return $this->render('your-view'); }
方式2:保存到关联表(多对多关系)
如果参考编号和主表是多对多关系(比如有survey_reference关联表,存储survey_id和ref_no):
public function actionSaveReferences() { if (Yii::$app->request->isPost) { $surveyId = Yii::$app->request->post('survey_id'); // 你的主表ID $selectedRefs = Yii::$app->request->post('selected_refs', []); // 先清空现有关联数据(避免重复) SurveyReference::deleteAll(['survey_id' => $surveyId]); // 批量插入新的关联数据 foreach ($selectedRefs as $ref) { if (Reference::find()->where(['ref_no' => $ref])->exists()) { $surveyRef = new SurveyReference(); $surveyRef->survey_id = $surveyId; $surveyRef->ref_no = $ref; $surveyRef->save(false); } } return $this->asJson([ 'success' => true, 'message' => '参考编号关联成功' ]); } return $this->render('your-view'); }
三、提交数据到后端
你可以用普通表单提交,或者AJAX异步提交:
普通表单提交
确保表单包含隐藏输入框,提交时会自动把selected_refs传给后端:
<form action="survey/save-references" method="post"> <!-- 你的其他表单字段 --> <input type="hidden" name="_csrf" value="<?= Yii::$app->request->csrfToken ?>"> <input type="hidden" id="selected-refs" name="selected_refs[]"> <button type="submit" class="btn btn-primary">保存</button> </form>
AJAX异步提交
如果需要无刷新保存,用AJAX提交:
$('#save-btn').click(function() { $.ajax({ url: 'survey/save-references', method: 'POST', data: { _csrf: '<?= Yii::$app->request->csrfToken ?>', selected_refs: JSON.parse($('#selected-refs').val()), // 若需要主表ID,添加:survey_id: 123 }, success: function(res) { alert(res.message); }, error: function() { alert('请求失败,请稍后重试'); } }); });
内容的提问来源于stack exchange,提问作者Moeez
相关产品推荐
相关产品推荐

