You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Grocery CRUD依赖下拉多选及批量插入至同表技术问询

实现Grocery CRUD支持全选的多选依赖下拉并保存至同一表

嘿,针对你需要在Grocery CRUD里实现支持全选的多选依赖下拉、并将选中数据存入同一数据表的需求,我整理了一套可行的解决方案,一步步来:

1. 提前准备数据表字段

首先确保你的目标表tbl_donation_ppl中有一个字段用来存储多选结果,比如fld_selected_items,建议用TEXTJSON类型(TEXT存逗号分隔ID,JSON存数组更规范)。

2. 替换默认关联字段为自定义多选下拉

Grocery CRUD原生的set_relation只支持单选,所以我们需要用回调函数自定义表单字段,同时加入全选/取消全选按钮:

$this->load->library('grocery_CRUD');
$crud = new grocery_CRUD();
$crud->set_theme('flexigrid');
$crud->set_table('tbl_donation_ppl');

// 保留原有关联字段
$crud->set_relation('fld_home_id', 'tbl_home_name', 'fld_name');
$crud->set_relation('fld_user_id','tbl_recipient', 'fld_name');

// --------------------------
// 自定义添加页面的多选下拉
// --------------------------
$crud->callback_add_field('fld_selected_items', function() {
    // 初始加载所有选项(如果是依赖下拉,后续用AJAX更新)
    $options = $this->db->get('tbl_target_options')->result(); // 替换为你的选项表
    $html = '<select multiple="multiple" name="fld_selected_items[]" id="multi-select" style="height:150px;">';
    foreach($options as $opt) {
        $html .= sprintf('<option value="%d">%s</option>', $opt->id, $opt->fld_name);
    }
    $html .= '</select>';
    // 添加全选/取消按钮
    $html .= '<div style="margin-top:8px;">';
    $html .= '<button type="button" onclick="toggleMultiSelect(true)" class="btn btn-sm btn-primary">全选</button>';
    $html .= '<button type="button" onclick="toggleMultiSelect(false)" class="btn btn-sm btn-default" style="margin-left:5px;">取消全选</button>';
    $html .= '</div>';
    // 全选逻辑JS
    $html .= '<script>
        function toggleMultiSelect(isSelectAll) {
            const select = document.getElementById("multi-select");
            Array.from(select.options).forEach(opt => opt.selected = isSelectAll);
        }
    </script>';
    return $html;
});

// --------------------------
// 自定义编辑页面的多选下拉(回显已选值)
// --------------------------
$crud->callback_edit_field('fld_selected_items', function($value, $primary_key) {
    // 解析已存值:如果是逗号分隔转数组,JSON的话用json_decode($value, true)
    $selectedIds = explode(',', $value);
    $options = $this->db->get('tbl_target_options')->result();
    $html = '<select multiple="multiple" name="fld_selected_items[]" id="multi-select" style="height:150px;">';
    foreach($options as $opt) {
        $selected = in_array($opt->id, $selectedIds) ? 'selected' : '';
        $html .= sprintf('<option value="%d" %s>%s</option>', $opt->id, $selected, $opt->fld_name);
    }
    $html .= '</select>';
    // 同样添加全选按钮和JS
    $html .= '<div style="margin-top:8px;">';
    $html .= '<button type="button" onclick="toggleMultiSelect(true)" class="btn btn-sm btn-primary">全选</button>';
    $html .= '<button type="button" onclick="toggleMultiSelect(false)" class="btn btn-sm btn-default" style="margin-left:5px;">取消全选</button>';
    $html .= '</div>';
    $html .= '<script>
        function toggleMultiSelect(isSelectAll) {
            const select = document.getElementById("multi-select");
            Array.from(select.options).forEach(opt => opt.selected = isSelectAll);
        }
    </script>';
    return $html;
});

3. 处理表单提交数据

把多选的数组值转成适合存储的格式(逗号分隔字符串或JSON):

// 新增前处理
$crud->callback_before_insert(function($postArray) {
    if(isset($postArray['fld_selected_items'])) {
        // 逗号分隔存储,JSON的话用json_encode($postArray['fld_selected_items'])
        $postArray['fld_selected_items'] = implode(',', $postArray['fld_selected_items']);
    }
    return $postArray;
});

// 更新前处理
$crud->callback_before_update(function($postArray, $primaryKey) {
    if(isset($postArray['fld_selected_items'])) {
        $postArray['fld_selected_items'] = implode(',', $postArray['fld_selected_items']);
    }
    return $postArray;
});

4. 列表页面友好显示已选内容(可选)

把存储的ID转成对应的名称,提升可读性:

$crud->callback_column('fld_selected_items', function($value, $row) {
    if(empty($value)) return '-';
    $ids = explode(',', $value);
    // 获取对应名称
    $names = $this->db->where_in('id', $ids)->get('tbl_target_options')->result_array();
    $nameList = array_column($names, 'fld_name');
    return implode(', ', $nameList);
});

5. 实现依赖下拉联动(如果需要)

如果你的多选下拉需要依赖其他字段(比如fld_home_id选中后更新选项),添加AJAX联动逻辑:

callback_add_field的HTML末尾加入:

<script>
// 监听依赖字段变化
document.getElementById('fld_home_id').addEventListener('change', function() {
    const homeId = this.value;
    fetch('<?=site_url('your_controller/get_options_by_home')?>', {
        method: 'POST',
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        body: `home_id=${homeId}`
    }).then(res => res.json())
      .then(data => {
          const select = document.getElementById('multi-select');
          select.innerHTML = '';
          data.forEach(opt => {
              const option = document.createElement('option');
              option.value = opt.id;
              option.textContent = opt.fld_name;
              select.appendChild(option);
          });
      });
});
</script>

然后在控制器添加方法:

public function get_options_by_home() {
    $homeId = $this->input->post('home_id');
    // 根据home_id筛选选项
    $options = $this->db->where('fld_home_id', $homeId)->get('tbl_target_options')->result();
    echo json_encode($options);
}

注意事项

  • 确保多选下拉的name属性是数组形式fld_selected_items[],否则PHP无法接收多个值。
  • 如果用JSON存储,记得把字段类型设为JSON,并且处理时替换explode/implodejson_decode/json_encode
  • 全选按钮的JS可以根据项目是否使用jQuery调整,比如用$('#multi-select option').prop('selected', isSelectAll)更简洁。

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

火山引擎 最新活动