yii2 Set default configuration of ActionColumn in GridView - php

I want to set a default configuration for all my GridViews.
I did this as following:
app\config\web.php:
require __DIR__ . '/container.php';
app\config\container.php:
use yii\helpers\Html;
use yii\helpers\Url;
\Yii::$container->set('yii\grid\GridView', [
'layout' => "{items}\n{summary}\n{pager}",
'columns' => [
[
'class' => 'yii\grid\ActionColumn',
'template' => '{edit}{update}',
'buttons' => [
'edit' => function ($url, $model) {
return Html::a('<span class="glyphicon glyphicon-pencil"></span>', [Url::to(['edit', 'id' => $model->id])]);
},
],
],
],
]);
the part where I define the layout works fine.
But apparently the part with the ActionColumn doesn't work, because the whole array-index 'columns' gets overwritten by the column-names when I actually use the GridView in a list.
How can I set default settings for ActionColumn for all GridViews?

Try setting the default values for ActionColumn separately:
\Yii::$container->set('yii\grid\ActionColumn', [
'template' => '{edit}{update}',
'buttons' => [
'edit' => function ($url, $model) {
return Html::a('<span class="glyphicon glyphicon-pencil"></span>', [Url::to(['edit', 'id' => $model->id])]);
},
],
]);

Related

Yii2 pjax corrupts styles

I'm using Yii2 and i have a view which displays a table:
<div class="table-responsive">
<?php yii\widgets\Pjax::begin()?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'summary'=> "",
'tableOptions' => ['id'=>'smartTable',
'class' => 'display table-bordered-custom',
'cellspacing' => 0,
'width' => "100%"
],
'columns' => [
[
'class' => 'yii\grid\SerialColumn'],
'product_code',
'product_name',
'product_status',
[
'class' => 'yii\grid\ActionColumn',
'header' => 'Operation',
'template' => '{view}',
'headerOptions' => ['class' => 'no-sort'],
'buttons' => [
'view' => function ($url, $model) {
return Html::a(
'Edit<i class="material-icons">chevron_right</i>',
['update', 'id'=>$model->product_id],
[
'class' => 'btn',
'data-pjax' => '',
]
);
},
],
],
],
]);
?>
<?php Pjax::end(); ?>
</div>
My controller:
class ProductController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all Product models.
* #return mixed
*/
public function actionIndex()
{
$dataProvider = new ActiveDataProvider([
'query' => Product::find(),
'sort' => false,
'pagination'=> [
'pageSize' => 4
]
]);
return $this->render('index', [
'dataProvider' => $dataProvider,
]);
}
}
Edit: My controller has a simple action called index.
My problem is that when i click on the page number and get new info, all the styles I've given to my table disappear.
If i remove Pjax everything is okay because the entire page reloads.
Why? please help me.
I finally managed to fix this! but i'm not sure it's the best.
With pjax events you can solve such problems:
$(document).on("pjax:success", function() {
$('#smartTable').DataTable({
"paging": false,
"responsive": true,
"dom": 'iftlp',
"bProcessing": true,
"aoColumnDefs": [ // EXCEPT SORTING
{'bSortable': false, 'aTargets': ['no-sort']}
],
});
$('#simpleTable').DataTable({
"responsive": true,
"dom": 't'
});
});
So every time our pjax is successfully executed, we will re-apply the style we need.
That's it, i hope to be useful to others.
Thanks to pjax that we can reload selective content easily.
Issue
In Yii2, pjax also do try to loads the anchors (links) etc present inside the pjax container within the same container. Which means it doesn't allow such links to load, full pages. This causes crippling of the other parts / tags in followed pages.
Solution
In order to avoid this, you need to figure out a way to load your links/pages outside the pjax container. One method that worked for my action links is as following:
Example
This is my custom actions column:
[
'label'=>'Options',
'format' => 'raw',
'value'=>function ($data) {
return Html::a('<i class="glyphicon glyphicon-eye-open"></i>', ['short-message/conversation', 'id'=> $data["id"]], ['onclick' =>'window.location.href=this.getAttribute("href")']);
},
],
Explanation
You can see that I have used onclick method to follow the link using JavaScript:
['onclick' =>'window.location.href=this.getAttribute("href")']

How to use buttonOptions on GridView on Yii2

I would like to change the default button name on grid view On YII2
on Yii 1 we have this:
http://www.yiiframew...s-in-cgridview/
array
(
'class'=>'CButtonColumn',
'template'=>'{email}{down}{delete}',
'buttons'=>array
(
'email' => array
(
'label'=>'Send an e-mail to this user',
'imageUrl'=>Yii::app()->request->baseUrl.'/images/email.png',
'url'=>'Yii::app()->createUrl("users/email", array("id"=>$data->id))',
),
'down' => array
(
'label'=>'[-]',
'url'=>'"#"',
'visible'=>'$data->score > 0',
'click'=>'function(){alert("Going down!");}',
),
),
),
I would like something like that for Yii2
For now I would like to change only the label.
Reading the documentation for Yii2 I tried that:
[
'class' => 'yii\grid\ActionColumn',
'buttonOptions' => [
[
'name' => 'update',
'additionalOptions' => [
'label' => 'Super Update',
]
],
[
'name' => 'delete',
'additionalOptions' => [
'label' => 'Super Delete',
]
],
],
],
But it does not work.
I know I can recreate the button from scratch with :
'buttons' => [
'update' => function ($url, $model) {
$t = 'index.php?r=site/update&id='.$model->id;
return Html::button('<span class="glyphicon glyphicon-pencil"></span>', ['value'=>Url::to($t), 'class' => 'btn btn-default btn-xs']);
},
],
But I do not want to do that.
thanks
buttonOptions will be applied to all default buttons, you can't separate them, but it's possible to apply general options (to all buttons):
'class' => 'yii\grid\ActionColumn',
'buttonOptions' => [
'title' => 'This is custom title for default 3 buttons',
],
If you want to use custom HTML options, you'll have to create new class, extend ActionColumn and overwrite (2) protected methods, for example:
<?php
namespace app\models;
use yii\grid\ActionColumn;
use yii\helpers\Html;
use Yii;
class customActionColumn extends ActionColumn
{
/**
* Initializes the default button rendering callbacks.
*/
protected function initDefaultButtons()
{
$this->initDefaultButton('view', 'eye-open', [
'title' => 'Super View',
]);
$this->initDefaultButton('update', 'pencil', [
'title' => 'Super Update',
]);
$this->initDefaultButton('delete', 'trash', [
'data-confirm' => Yii::t('yii', 'Are you sure you want to delete this item?'),
'data-method' => 'post',
'title' => 'Super Delete'
]);
}
/**
* Initializes the default button rendering callback for single button
* #param string $name Button name as it's written in template
* #param string $iconName The part of Bootstrap glyphicon class that makes it unique
* #param array $additionalOptions Array of additional options
* #since 2.0.11
*/
protected function initDefaultButton($name, $iconName, $additionalOptions = [])
{
if (!isset($this->buttons[$name]) && strpos($this->template, '{' . $name . '}') !== false) {
$this->buttons[$name] = function ($url, $model, $key) use ($name, $iconName, $additionalOptions) {
$title = Yii::t('yii', ucfirst($name));
$options = array_merge([
'title' => $title,
'aria-label' => $title,
'data-pjax' => '0',
'title' => 'atata'
], $additionalOptions, $this->buttonOptions);
$icon = Html::tag('span', '', ['class' => "glyphicon glyphicon-$iconName"]);
return Html::a($icon, $url, $options);
};
}
}
}
Now in GridView you just need to specify custom class and that's all.
[
'class' => app\models\customActionColumn::className(),
],

Yii2 custom delete ActionColumn alert twice

I have a custom action column with just the delete button:
[
'class' => 'yii\grid\ActionColumn',
'template' => '{delete}',
'buttons' => [
'delete' => function($url, $data){
return Html::a('<span class="glyphicon glyphicon-trash"></span>', ['orders-lines/delete', 'id' => $data->id], [
'data' => [
'confirm' => Yii::t('app', 'Are you sure you want to delete this item?'),
'method' => 'post',
],
]);
}
]
],
and whenever i click the trash icon, then accept the alert box, the same alert box is triggered again so I have to accept twice the alert box.
What could i be missing?
Thanks
Try this
['class' => 'yii\grid\ActionColumn',
'template' => '{delete}',
'buttons' => [
'delete' => function ($url, $data) {
return Html::a('<span class="glyphicon glyphicon-trash" title="Delete"></span>', ['orders-lines/delete', 'id' => $data->id], ["data-pjax" => 0, 'onClick' => 'return confirm("Are you sure you want to delete this item?") ']);
},
],
],

Yii gridview How to set editable option based on the data

This is my grid view code
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'toolbar'=> [
['content'=>
Html::a('<i class="glyphicon glyphicon-plus"></i> Add New', ['create'],['class'=>'btn btn-shadow btn-success'])
],
'{toggleData}',
],
'columns' => [
['class' => 'kartik\grid\SerialColumn'],
[
'attribute'=>'Name',
'vAlign'=>GridView::ALIGN_MIDDLE,
],
[
'attribute'=>'Age',
'vAlign'=>GridView::ALIGN_MIDDLE,
'value'=>'Age',
'width'=>'5%',
'hAlign'=>'center',
],
[
'attribute'=>'Address',
'vAlign'=>GridView::ALIGN_MIDDLE,
],
[
'class' => 'kartik\grid\EditableColumn',
'attribute'=>'Status',
'vAlign'=>GridView::ALIGN_MIDDLE,
'hAlign'=>GridView::ALIGN_CENTER,
'width'=>'15%',
'filterType'=>GridView::FILTER_SELECT2,
'filterWidgetOptions'=>[
'options' => ['placeholder' => 'Search Status...'],
'pluginOptions' => [
'allowClear' => true
],
],
'value'=>function($model){
return ($model->Status=='0'?'Pending':($model->Status=='1'?'Accepted':'Rejected'));},
'filter'=>['Pending','Diterima'],
'label' => 'Status',
'refreshGrid'=>true,
'editableOptions'=>[
'format' => Editable::FORMAT_BUTTON,
'asPopover' => true,
'inputType' => Editable::INPUT_DROPDOWN_LIST,
'data'=>['0'=>'Pending', '1'=>'Accepted', '2'=>'Rejected'],
'options' => ['class'=>'form-control'],
]
],
[
'class' => 'kartik\grid\ActionColumn',
'template' => '
<li>{view}</li>
<li>{update}</li>
<li>{delete}</li>',
'dropdown'=>true,
'dropdownOptions'=>['class'=>'pull-right'],
'headerOptions'=>['class'=>'kartik-sheet-style'],
],
],
'panel'=>[
'type'=>GridView::TYPE_DEFAULT,
]
]); ?>
Help me with the Status attribute. The result from this gridview is like this :
what i want is like this :
So, it's like when the Status is Pending, the editableOption is on.But when the Status is Accepted or Rejected, the editableOption is disable. Is that possible ?
You need Change value option of Status Attribute.
Change in value option of Status Attribute.
[
'class' => 'kartik\grid\EditableColumn',
'attribute'=>'Status',
// ------- your code ------------
'format'=>'raw',
'value'=>function($model){
if($model->Status=='0')
{
// if status =0 than create button and append with string
$btn='<button type="button" id='.$model->id.' class="btn btn-default ><i class="fa fa-pencil-square-o"></i></button>';
return 'Pending'.$btn;
}
else
{
return($model->Status=='1'?'Accepted':'Rejected');
}
},
// ------- your code ------------
],
There are multiple ways to do what you have asked, if you have used editableOptions, then
For Editable::INPUT_DROPDOWN_LIST type -> use 'editableButtonOptions' => [ 'disabled' => $data->your_status_variable_condition],
For any other type add readonly property
'readonly' => function($data){
return $data->your_status_variable_condition;
},
I hope it helps someone who is looking for the same issue

How do I pass a array as a param for a Yii2 gridview column

I am trying to pass $arr_judete_v2 as a param to a callback function in a gridview and it does not work;
$model['county_id'] returns a number
$arr_judete_v2[1]['nume'] returns a name
my issue:
[
'attribute' => 'county_id',
'label' => Yii::t('diverse', 'Judet'),
'content' => function($model, $arr_judete_v2) {
return $arr_judete_v2[$model['county_id']]['nume'];
},
],
the entire gridview
<?php
echo GridView::widget([
'layout' => "{items}",
'dataProvider' => $dataProvider,
'columns' => [
'id',
[
'attribute' => 'nume',
'label' => Yii::t('companie', 'nume'),
],
'cui',
'email',
[
'attribute' => 'county_id',
'label' => Yii::t('diverse', 'Judet'),
'content' => function($model, $arr_judete_v2) {
return $arr_judete_v2[$model['county_id']]['nume'];
},
],
[
'class' => 'yii\grid\ActionColumn',
'template' => '{update} {delete}',
'buttons' => [
'update' => function ($url, $model) {
return Html::a('<span class="glyphicon glyphicon-pencil"></span>', ['update', 'id' => $model['id']], [
'title' => Yii::t('yii', 'Update'),
'data-pjax' => '0',
]);
}
]
],
],
]);
From the source code for \Yii\grid\Column
#var callable This is a callable that will be used to generated the content of each cell.
The signature of the function should be the following: function ($model, $key, $index, $column)
As Mihai has correctly pointed out you can use use() to include variables into the function's scope as follows:
"content" => function($model, $key, $index, $column) use ($arr_judete_v2) {
return $arr_judete_v2[$model['county_id']]['nume'];
}
Please note that the variables are copied into the function and as such any changes will not affect the variable outside of the function. A better explanation of this is given in this answer.
Use use (), see how the function is defined for the value of the column.
$invoice_status_data = array('' => 'Select a status') + ArrayHelper::map(InvoiceStatus::find()->asArray()->all(), 'id', 'name');
........................
'columns' => [
........................
[
'attribute'=>'Contact.name',
'format'=>'raw',
'value'=>function ($model, $key, $index, $widget) use ($invoice_status_data) {
.............................
$content .=
Html::dropDownList('dropdown'. $model->id, '', $invoice_status_data, [
'class' => 'form-control',
'onchange' => 'javascript: myInvoice.change($(this));',
'data-href' => Url::toRoute(['invoice/change-status', "Invoice_id"=>$model->id])]);
return $content;
},
],

Categories