需求:列表頁直接點擊單元格修改數據,無需跳轉詳情頁。Yii2 官方 GridView 不支持行內編輯,需引入 kartik-v/yii2-grid 與 kartik-v/yii2-editable。本文從安裝、基礎配置、TextArea、TouchSpin 數字微調、下拉框選項、後端控制器實現五個維度給出生產級方案。
composer require kartik-v/yii2-grid "@dev"
composer require kartik-v/yii2-editable "@dev"
# 若需數字微調組件
composer require kartik-v/yii2-widget-touchspin "@dev"
config/main.php 註冊模塊:
'modules' => [
'gridview' => [
'class' => '\kartik\grid\Module',
],
],
use kartik\grid\GridView;
use kartik\editable\Editable;
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'export' => false, // 禁用導出工具欄
'columns' => [
['class' => 'kartik\grid\SerialColumn'],
'id',
// ... 可編輯列將在下文展開
['class' => 'kartik\grid\ActionColumn'],
],
]);
[
'attribute' => 'title',
'class' => 'kartik\grid\EditableColumn',
'editableOptions' => [
'asPopover' => true, // 默認彈窗
],
],
[
'attribute' => 'title',
'class' => 'kartik\grid\EditableColumn',
'editableOptions' => [
'asPopover' => false, // 關鍵:內聯模式
],
],
[
'attribute' => 'description',
'class' => 'kartik\grid\EditableColumn',
'editableOptions' => [
'asPopover' => false,
'inputType' => Editable::INPUT_TEXTAREA,
'options' => ['rows' => 4],
],
],
[
'attribute' => 'price',
'class' => 'kartik\grid\EditableColumn',
'editableOptions' => [
'asPopover' => false,
'inputType' => Editable::INPUT_WIDGET,
'widgetClass' => 'kartik\touchspin\TouchSpin',
'options' => [
'pluginOptions' => [
'min' => 0,
'max' => 10000,
'step' => 0.01,
'decimals' => 2,
'prefix' => '¥ ',
],
],
],
'format' => ['decimal', 2],
],
[
'attribute' => 'status',
'class' => 'kartik\grid\EditableColumn',
'editableOptions' => [
'asPopover' => false,
'inputType' => Editable::INPUT_DROPDOWN_LIST,
'data' => [
0 => '草稿',
1 => '發布',
2 => '下架',
],
'options' => ['prompt' => '請選擇'],
],
'value' => function ($model) {
return [0 => '草稿', 1 => '發布', 2 => '下架'][$model->status] ?? '未知';
},
],
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\Article;
class ArticleController extends Controller
{
public function actionIndex()
{
$searchModel = new ArticleSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* EditableColumn 會 POST 以下參數:
* - editableKey: 主鍵值
* - editableAttribute: 屬性名
* - Article[title]: 新值 (模型名作為前綴)
*/
public function actionEditable()
{
if (Yii::$app->request->isPost) {
$model = Article::findOne(Yii::$app->request->post('editableKey'));
if ($model) {
$attr = Yii::$app->request->post('editableAttribute');
$value = Yii::$app->request->post('Article')[$attr] ?? null;
if ($value !== null) {
$model->$attr = $value;
if ($model->save(false)) { // false 跳過驗證,或 true 開啟驗證
return \yii\helpers\Json::encode(['output' => '', 'message' => '']);
}
}
}
return \yii\helpers\Json::encode(['output' => '', 'message' => '保存失敗']);
}
return \yii\helpers\Json::encode(['output' => '', 'message' => '非法請求']);
}
}
| 問題 | 原因 | 解決 |
|---|---|---|
| 點擊「應用」按鈕轉圈無響應 | 後端未返回正確 JSON 格式、或驗證失敗無提示 | 控制器返回 ['output'=>'', 'message'=>''];開啟驗證時需返回錯誤消息 |
| 下拉框顯示數字而非文本 | GridView 列未配置 value 回調轉換 | 在列配置中添加 value 閉包返回顯示文本 |
| TouchSpin 不顯示 | 未安裝/註冊 kartik-v/yii2-widget-touchspin | composer require kartik-v/yii2-widget-touchspin "@dev" |
| 主鍵非 id 字段 | EditableColumn 默認發送 editableKey 對應主鍵 | 模型需正確定義 primaryKey(),或控制器手動映射 |
| 批量編輯性能 | 頻繁 AJAX 請求 | 啟用 PJAX 容器、或改用批量更新接口 |
public function actionEditable()
{
// 權限檢查
if (!Yii::$app->user->can('article-edit')) {
throw new \yii\web\ForbiddenHttpException('無權限');
}
// ... 保存邏輯
// 審計日志
\app\models\AuditLog::log([
'user_id' => Yii::$app->user->id,
'action' => 'editable_update',
'model' => 'Article',
'pk' => $model->id,
'field' => $attr,
'old_value' => $old,
'new_value' => $value,
]);
}
通過 kartik-v/yii2-grid 的 EditableColumn 搭配 yii2-editable,可快速構建類 Excel 的行內編輯體驗。關鍵在於:視圖層正確配置 inputType、widgetClass、data;控制器層處理 editableKey/editableAttribute 並返回標準 JSON。結合權限、審計、驗證,即可滿足企業級後台管理系統的列表編輯需求。