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

