Yii2 Kartik EditableColumn下拉关联更新后返回错误值问题
这个问题我之前也碰到过——EditableColumn在更新status_id后,直接把整数ID显示出来了,而不是我们想要的关联表中的related_value字符串。核心原因是:编辑完成后,组件默认只会返回你修改的status_id字段值,不会自动去关联查询RelatedFields表获取对应的文本值,而初次加载时因为你用了status.related_value,关联数据已经被加载,所以显示正常。
下面给你几个不需要刷新整个网格的解决方案,亲测有效:
方法一:用afterSave回调返回正确的显示值
在editableOptions里加一个afterSave回调,当保存完成后,根据新的status_id查询对应的related_value,然后修改响应的输出值:
'editableOptions'=> [ 'inputType' => Editable::INPUT_DROPDOWN_LIST, 'data'=> ArrayHelper::map(RelatedFields::find()->where(['model' =>"Leads","field"=>"status_id"])->all(), 'related_id', 'related_value'), 'afterSave' => function($model, $response) { // 根据新的status_id查询对应的关联值 $relatedValue = RelatedFields::find() ->where([ 'model' => 'Leads', 'field' => 'status_id', 'related_id' => $model->status_id ]) ->select('related_value') ->scalar(); // 把响应里的输出改成我们要的文本值 $response['output'] = $relatedValue; return $response; } ]
方法二:给模型加虚拟属性,让Editable直接绑定文本值
这种方法更优雅,通过给Leads模型加一个虚拟属性,把关联值封装起来,让EditableColumn直接操作这个属性:
- 先在
Leads模型里添加虚拟属性和自动赋值逻辑:
public $status_value; public function afterFind() { parent::afterFind(); // 每次模型加载时,自动把关联的文本值赋值给虚拟属性 $this->status_value = $this->status->related_value; }
- 然后修改EditableColumn的配置:
[ 'class' => 'kartik\grid\EditableColumn', 'attribute' => 'status_value', // 绑定虚拟属性 'vAlign'=>'middle', 'hAlign'=>'center', 'pageSummary' => true, 'readonly' => false, 'width'=>'10%', 'filter'=>Html::activeDropDownList($searchModel, 'status', ArrayHelper::map(RelatedFields::find()->where(['model' =>"Leads","field"=>"status_id"])->all(), 'related_id', 'related_value'),['class' => 'form-control','prompt' => Yii::t('app', '')]), 'editableOptions'=> [ 'inputType' => Editable::INPUT_DROPDOWN_LIST, 'data'=> ArrayHelper::map(RelatedFields::find()->where(['model' =>"Leads","field"=>"status_id"])->all(), 'related_id', 'related_value'), // 保存时把选择的ID赋值给真实的status_id字段 'beforeSave' => function($model, $form) { $model->status_id = $form->status_value; return true; }, ], ],
注意:如果你的搜索模型需要过滤这个字段,记得调整LeadsSearch里的过滤逻辑,或者保持原来的status过滤字段不变就行。
方法三:用displayValue强制显示关联文本
直接在editableOptions里设置displayValue,让组件始终用关联的文本值显示,不管返回的是什么ID:
'editableOptions'=> [ 'inputType' => Editable::INPUT_DROPDOWN_LIST, 'data'=> ArrayHelper::map(RelatedFields::find()->where(['model' =>"Leads","field"=>"status_id"])->all(), 'related_id', 'related_value'), 'displayValue' => function($model) { return $model->status->related_value; } ]
这里要注意:确保你的Leads数据查询时用了with('status')预加载关联,比如在LeadsSearch的search方法里加$query->joinWith(['status']);,避免N+1查询,同时保证编辑后关联数据能正确获取。
这几种方法都能解决问题,不需要刷新整个网格,你可以根据自己的代码习惯选一个最顺手的。
内容的提问来源于stack exchange,提问作者The Humble Rat

