You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ActionColumn.php 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\grid;
  8. use Yii;
  9. use Closure;
  10. use yii\helpers\Html;
  11. use yii\helpers\Url;
  12. /**
  13. * ActionColumn is a column for the [[GridView]] widget that displays buttons for viewing and manipulating the items.
  14. *
  15. * To add an ActionColumn to the gridview, add it to the [[GridView::columns|columns]] configuration as follows:
  16. *
  17. * ```php
  18. * 'columns' => [
  19. * // ...
  20. * [
  21. * 'class' => ActionColumn::className(),
  22. * // you may configure additional properties here
  23. * ],
  24. * ]
  25. * ```
  26. *
  27. * @author Qiang Xue <qiang.xue@gmail.com>
  28. * @since 2.0
  29. */
  30. class ActionColumn extends Column
  31. {
  32. /**
  33. * @inheritdoc
  34. */
  35. public $headerOptions = ['class' => 'action-column'];
  36. /**
  37. * @var string the ID of the controller that should handle the actions specified here.
  38. * If not set, it will use the currently active controller. This property is mainly used by
  39. * [[urlCreator]] to create URLs for different actions. The value of this property will be prefixed
  40. * to each action name to form the route of the action.
  41. */
  42. public $controller;
  43. /**
  44. * @var string the template used for composing each cell in the action column.
  45. * Tokens enclosed within curly brackets are treated as controller action IDs (also called *button names*
  46. * in the context of action column). They will be replaced by the corresponding button rendering callbacks
  47. * specified in [[buttons]]. For example, the token `{view}` will be replaced by the result of
  48. * the callback `buttons['view']`. If a callback cannot be found, the token will be replaced with an empty string.
  49. *
  50. * As an example, to only have the view, and update button you can add the ActionColumn to your GridView columns as follows:
  51. *
  52. * ```php
  53. * ['class' => 'yii\grid\ActionColumn', 'template' => '{view} {update}'],
  54. * ```
  55. *
  56. * @see buttons
  57. */
  58. public $template = '{view} {update} {delete}';
  59. /**
  60. * @var array button rendering callbacks. The array keys are the button names (without curly brackets),
  61. * and the values are the corresponding button rendering callbacks. The callbacks should use the following
  62. * signature:
  63. *
  64. * ```php
  65. * function ($url, $model, $key) {
  66. * // return the button HTML code
  67. * }
  68. * ```
  69. *
  70. * where `$url` is the URL that the column creates for the button, `$model` is the model object
  71. * being rendered for the current row, and `$key` is the key of the model in the data provider array.
  72. *
  73. * You can add further conditions to the button, for example only display it, when the model is
  74. * editable (here assuming you have a status field that indicates that):
  75. *
  76. * ```php
  77. * [
  78. * 'update' => function ($url, $model, $key) {
  79. * return $model->status === 'editable' ? Html::a('Update', $url) : '';
  80. * },
  81. * ],
  82. * ```
  83. */
  84. public $buttons = [];
  85. /** @var array visibility conditions for each button. The array keys are the button names (without curly brackets),
  86. * and the values are the boolean true/false or the anonymous function. When the button name is not specified in
  87. * this array it will be shown by default.
  88. * The callbacks must use the following signature:
  89. *
  90. * ```php
  91. * function ($model, $key, $index) {
  92. * return $model->status === 'editable';
  93. * }
  94. * ```
  95. *
  96. * Or you can pass a boolean value:
  97. *
  98. * ```php
  99. * [
  100. * 'update' => \Yii::$app->user->can('update'),
  101. * ],
  102. * ```
  103. * @since 2.0.7
  104. */
  105. public $visibleButtons = [];
  106. /**
  107. * @var callable a callback that creates a button URL using the specified model information.
  108. * The signature of the callback should be the same as that of [[createUrl()]].
  109. * If this property is not set, button URLs will be created using [[createUrl()]].
  110. */
  111. public $urlCreator;
  112. /**
  113. * @var array html options to be applied to the [[initDefaultButtons()|default buttons]].
  114. * @since 2.0.4
  115. */
  116. public $buttonOptions = [];
  117. /**
  118. * @inheritdoc
  119. */
  120. public function init()
  121. {
  122. parent::init();
  123. $this->initDefaultButtons();
  124. }
  125. /**
  126. * Initializes the default button rendering callbacks.
  127. */
  128. protected function initDefaultButtons()
  129. {
  130. if (!isset($this->buttons['view'])) {
  131. $this->buttons['view'] = function ($url, $model, $key) {
  132. $options = array_merge([
  133. 'title' => Yii::t('yii', 'View'),
  134. 'aria-label' => Yii::t('yii', 'View'),
  135. 'data-pjax' => '0',
  136. ], $this->buttonOptions);
  137. return Html::a('<span class="glyphicon glyphicon-eye-open"></span>', $url, $options);
  138. };
  139. }
  140. if (!isset($this->buttons['update'])) {
  141. $this->buttons['update'] = function ($url, $model, $key) {
  142. $options = array_merge([
  143. 'title' => Yii::t('yii', 'Update'),
  144. 'aria-label' => Yii::t('yii', 'Update'),
  145. 'data-pjax' => '0',
  146. ], $this->buttonOptions);
  147. return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, $options);
  148. };
  149. }
  150. if (!isset($this->buttons['delete'])) {
  151. $this->buttons['delete'] = function ($url, $model, $key) {
  152. $options = array_merge([
  153. 'title' => Yii::t('yii', 'Delete'),
  154. 'aria-label' => Yii::t('yii', 'Delete'),
  155. 'data-confirm' => Yii::t('yii', 'Are you sure you want to delete this item?'),
  156. 'data-method' => 'post',
  157. 'data-pjax' => '0',
  158. ], $this->buttonOptions);
  159. return Html::a('<span class="glyphicon glyphicon-trash"></span>', $url, $options);
  160. };
  161. }
  162. }
  163. /**
  164. * Creates a URL for the given action and model.
  165. * This method is called for each button and each row.
  166. * @param string $action the button name (or action ID)
  167. * @param \yii\db\ActiveRecord $model the data model
  168. * @param mixed $key the key associated with the data model
  169. * @param integer $index the current row index
  170. * @return string the created URL
  171. */
  172. public function createUrl($action, $model, $key, $index)
  173. {
  174. if (is_callable($this->urlCreator)) {
  175. return call_user_func($this->urlCreator, $action, $model, $key, $index);
  176. } else {
  177. $params = is_array($key) ? $key : ['id' => (string) $key];
  178. $params[0] = $this->controller ? $this->controller . '/' . $action : $action;
  179. return Url::toRoute($params);
  180. }
  181. }
  182. /**
  183. * @inheritdoc
  184. */
  185. protected function renderDataCellContent($model, $key, $index)
  186. {
  187. return preg_replace_callback('/\\{([\w\-\/]+)\\}/', function ($matches) use ($model, $key, $index) {
  188. $name = $matches[1];
  189. if (isset($this->visibleButtons[$name])) {
  190. $isVisible = $this->visibleButtons[$name] instanceof \Closure
  191. ? call_user_func($this->visibleButtons[$name], $model, $key, $index)
  192. : $this->visibleButtons[$name];
  193. } else {
  194. $isVisible = true;
  195. }
  196. if ($isVisible && isset($this->buttons[$name])) {
  197. $url = $this->createUrl($name, $model, $key, $index);
  198. return call_user_func($this->buttons[$name], $url, $model, $key);
  199. } else {
  200. return '';
  201. }
  202. }, $this->template);
  203. }
  204. }