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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:03:41