forked from kartik-v/yii2-grid
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEditableColumn.php
148 lines (137 loc) · 6.07 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
<?php
/**
* @package yii2-grid
* @author Kartik Visweswaran <[email protected]>
* @copyright Copyright © Kartik Visweswaran, Krajee.com, 2014 - 2016
* @version 3.1.1
*/
namespace kartik\grid;
use Yii;
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]]
*
* @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 mixed is the data model
* - $key mixed is the key associated with the data model
* - $index integer is the zero-based index of the data model among the models array returned by
* [[GridView::dataProvider]].
* - $widget EditableColumn is the editable column widget instance
*/
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 mixed is the data model
* - $key mixed is the key associated with the data model
* - $index integer is the zero-based index of the data model among the models array
* returned by [[GridView::dataProvider]].
* - $widget EditableColumn is the editable column widget 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();
Config::checkDependency('editable\Editable', 'yii2-editable', 'for GridView EditableColumn');
$this->_css = 'kv-edcol-' . hash('crc32', uniqid(rand(1, 100), true));
if ($this->refreshGrid) {
EditableColumnAsset::register($this->_view);
}
}
/**
* Renders the data cell content.
*
* @param mixed $model the data model
* @param mixed $key the key associated with the data model
* @param integer $index the zero-based index of the data model among the models array returned by
* [[GridView::dataProvider]].
*
* @return string the rendering result
* @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 = [];
}
$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}');");
}
return Editable::widget($this->_editableOptions);
}
}