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

Yii2 kartik\select2:如何显示下拉列表外的已选值?

解决Yii2 kartik\select2显示下拉列表外旧值的问题

核心思路

要实现显示已停用的旧值,但禁止用户再次选择,关键是在初始化组件时,把当前模型的旧值(即使不在下拉数据源里)临时加入可选列表,同时通过前端样式和验证限制选择,后端保留原有值的保存逻辑。

步骤1:构造包含旧值的数据源

在视图中,先获取正常启用的下拉选项,再判断当前模型是否存在不在启用列表中的旧值,若有则将其追加到数据源中并标记为已停用:

use kartik\select2\Select2;
use yii\helpers\ArrayHelper;

// 获取启用状态的选项(根据你的业务筛选条件调整)
$activeOptions = ArrayHelper::map(
    \app\models\TargetModel::find()->where(['status' => 1])->all(),
    'id',
    'name'
);

// 检查模型是否有不在启用列表的旧值
$oldValue = $model->target_attribute;
if ($oldValue && !isset($activeOptions[$oldValue])) {
    $inactiveItem = \app\models\TargetModel::findOne($oldValue);
    if ($inactiveItem) {
        // 将旧值追加到选项最前面,标注已停用
        $activeOptions = [$oldValue => $inactiveItem->name . '(已停用)'] + $activeOptions;
    }
}

// 渲染Select2组件
echo Select2::widget([
    'model' => $model,
    'attribute' => 'target_attribute',
    'data' => $activeOptions,
    'options' => ['placeholder' => '请选择...'],
    'pluginOptions' => [
        // 前端给已停用选项加灰色样式
        'templateResult' => new \yii\web\JsExpression("function(item) {
            if (item.text.includes('(已停用)')) {
                return $(`<span style='color:#999;'>${item.text}</span>`);
            }
            return item.text;
        }"),
        'escapeMarkup' => new \yii\web\JsExpression("function(markup) { return markup; }"),
    ],
]);

步骤2:后端验证规则调整

在模型的rules()中,不要强制字段值必须在启用列表内,而是自定义验证规则:只限制新选择的选项必须有效,更新时未修改的旧值允许保留:

public function rules()
{
    return [
        [['target_attribute'], 'required'],
        ['target_attribute', function ($attribute, $params) {
            // 更新时未修改值,直接通过验证
            if (!$this->isNewRecord && $this->$attribute == $this->getOldAttribute($attribute)) {
                return;
            }
            // 新选择的值必须在启用列表中
            $validIds = \app\models\TargetModel::find()->where(['status' => 1])->select('id')->column();
            if (!in_array($this->$attribute, $validIds)) {
                $this->addError($attribute, '请选择有效的选项');
            }
        }],
    ];
}

步骤3:前端禁用已停用选项(可选增强)

通过JS监听选择事件,禁止用户选择已停用的选项:

$('#model-target_attribute').on('select2:select', function(e) {
    const selectedText = e.params.data.text;
    if (selectedText.includes('(已停用)')) {
        $(this).val('').trigger('change');
        alert('该选项已停用,无法选择');
    }
});

设置完成后,表单会显示已停用的旧值(灰色样式),但用户无法再次选择它;提交表单时旧值会被正常保存,新选择仅允许启用状态的选项。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 16:15:43