forked from kartik-v/yii2-grid
-
Notifications
You must be signed in to change notification settings - Fork 0
/
EditableColumn.php
executable file
·160 lines (150 loc) · 6.74 KB
/
EditableColumn.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<?php
/**
* @package yii2-grid
* @author Kartik Visweswaran <[email protected]>
* @copyright Copyright © Kartik Visweswaran, Krajee.com, 2014 - 2017
* @version 3.1.7
*/
namespace kartik\grid;
use Closure;
use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\Json;
use kartik\editable\Editable;
use kartik\base\Config;
/**
* The EditableColumn converts the data to editable using the Editable widget [[\kartik\editable\Editable]].
*
* To add an EditableColumn to the gridview, add it to the [[GridView::columns|columns]] configuration as follows:
*
* ```php
* 'columns' => [
* // ...
* [
* 'class' => EditableColumn::className(),
* // you may configure additional properties here
* ],
* ]
* ```
*
* @author Kartik Visweswaran <[email protected]>
* @since 1.0
*/
class EditableColumn extends DataColumn
{
/**
* @var array|Closure the configuration options for the [[\kartik\editable\Editable]] widget. If not set as an
* array, this can be passed as a callback function of the signature: `function ($model, $key, $index)`, where:
* - `$model`: _\yii\base\Model_, is the data model.
* - `$key`: _string|object_, is the primary key value associated with the data model.
* - `$index`: _integer_, is the zero-based index of the data model among the model array returned by [[dataProvider]].
* - `$column`: _EditableColumn_, is the column object instance.
*
* This property allows to configure these additional settings for configuring the widget options:
* - `class`: _string_, the Editable widget class name. If not set this defaults to `kartik\editable\Editable`.
*/
public $editableOptions = [];
/**
* @var boolean whether to refresh the grid on successful submission of editable
*/
public $refreshGrid = false;
/**
* @var boolean|Closure whether to prevent rendering the editable behavior and display a readonly data. You can
* also set this up as an anonymous function of the form `function($model, $key, $index, $widget)` that will return
* a boolean value, where:
* - `$model`: _\yii\base\Model_, is the data model.
* - `$key`: _string|object_, is the primary key value associated with the data model.
* - `$index`: _integer_, is the zero-based index of the data model among the model array returned by [[dataProvider]].
* - `$column`: _EditableColumn_, is the column object instance. */
public $readonly = false;
/**
* @var array the computed editable options
*/
protected $_editableOptions = [];
/**
* @var string the css class to be appended for the editable inputs in this column
*/
protected $_css;
/**
* @inheritdoc
* @throws InvalidConfigException
*/
public function init()
{
parent::init();
$this->_css = 'kv-edcol-' . hash('crc32', uniqid(rand(1, 100), true));
if ($this->refreshGrid) {
EditableColumnAsset::register($this->_view);
}
}
/**
* @inheritdoc
* @throws InvalidConfigException
*/
public function renderDataCellContent($model, $key, $index)
{
$readonly = $this->readonly;
if ($readonly instanceof Closure) {
$readonly = call_user_func($readonly, $model, $key, $index, $this);
}
if ($readonly === true) {
return parent::renderDataCellContent($model, $key, $index);
}
$this->_editableOptions = $this->editableOptions;
if (!empty($this->editableOptions) && $this->editableOptions instanceof Closure) {
$this->_editableOptions = call_user_func($this->editableOptions, $model, $key, $index, $this);
}
if (!is_array($this->_editableOptions)) {
$this->_editableOptions = [];
}
if (empty($this->_editableOptions['class'])) {
Config::checkDependency('editable\Editable', 'yii2-editable', 'for GridView EditableColumn');
} elseif (!class_exists($this->_editableOptions['class'])) {
throw new InvalidConfigException(
"The widget class '" . $this->_editableOptions['class'] . "' set in `editableOptions` does not exist."
);
}
$options = ArrayHelper::getValue($this->_editableOptions, 'containerOptions', []);
Html::addCssClass($options, $this->_css);
$this->_editableOptions['containerOptions'] = $options;
if ($this->grid->pjax && empty($this->_editableOptions['pjaxContainerId'])) {
$this->_editableOptions['pjaxContainerId'] = $this->grid->pjaxSettings['options']['id'];
}
if (!isset($key)) {
throw new InvalidConfigException('Invalid or no primary key found for the grid data.');
}
$strKey = !is_string($key) && !is_numeric($key) ? (is_array($key) ? Json::encode($key) : (string) $key) : $key;
if ($this->attribute !== null) {
$this->_editableOptions['model'] = $model;
$this->_editableOptions['attribute'] = "[{$index}]{$this->attribute}";
} elseif (empty($this->_editableOptions['name']) && empty($this->_editableOptions['model']) ||
!empty($this->_editableOptions['model']) && empty($this->_editableOptions['attribute'])
) {
throw new InvalidConfigException(
"You must setup the 'attribute' for your EditableColumn OR set one of 'name' OR 'model' & 'attribute'" .
" in 'editableOptions' (Exception at index: '{$index}', key: '{$strKey}')."
);
}
$val = $this->getDataCellValue($model, $key, $index);
if (!isset($this->_editableOptions['displayValue']) && $val !== null && $val !== '') {
$this->_editableOptions['displayValue'] = parent::renderDataCellContent($model, $key, $index);
}
$params = Html::hiddenInput('editableIndex', $index) . Html::hiddenInput('editableKey', $strKey) .
Html::hiddenInput('editableAttribute', $this->attribute);
if (empty($this->_editableOptions['beforeInput'])) {
$this->_editableOptions['beforeInput'] = $params;
} else {
$output = $this->_editableOptions['beforeInput'];
$this->_editableOptions['beforeInput'] = function ($form, $widget) use ($output, $params) {
return $params . ($output instanceof Closure ? call_user_func($output, $form, $widget) : $output);
};
}
if ($this->refreshGrid) {
$id = $this->grid->options['id'];
$this->_view->registerJs("kvRefreshEC('{$id}','{$this->_css}');");
}
$editableClass = ArrayHelper::remove($this->_editableOptions, 'class', Editable::className());
return $editableClass::widget($this->_editableOptions);
}
}