How to put button in ActionColumn at header only in yii2 - yii

I want to put reset button under the action column only one time in GridView widget..
Any solution or suggestions?
Thanks

Set header property of ActionColumn:
[
'class' => 'yii\grid\ActionColumn',
'template' => '<div class="pull-right" >{update}{delete}</div>',
'header' => '<button>Button</button>'
]
Update:
As already answered you can create custom column, and you may add only additional filter property so that you can customize this property for each grid.
class CustomActionColumn extends yii\grid\ActionColumn
{
public $filter = "";
protected function renderFilterCellContent()
{
return $this->filter;
}
}
Then you set filter in grid definition:
[
'class' => 'CustomActionColumn',
'template' => '<div class="pull-right" >{update}{delete}</div>',
'filter' => '<button>Button</button>'
]

To, put button in ActionColumn on header so, follow below steps:
Create a file CustomActionColumn.php in components folder.
Put below code in above file
namespace app\components;
use yii\grid\ActionColumn;
use yii\helpers\Html;
class CustomActionColumn extends ActionColumn
{
protected function renderFilterCellContent()
{
return Html::button('Reset', ['class' => 'btn btn-primary']);
}
}
Now in your Gridview widget use CustomActionColumn instead of ActionColumn
Like as
[
'class' => 'app\components\CustomButton',
],
Done.
Note:- Using these steps you can just display button in header.

To display both a button and ActionColumn label you could override yii\grid\ActionColumn renderFilterCellContent() method with your own class like this:
namespace app\components;
class FilterActionColumn extends ActionColumn
{
public $filterContent;
/**
* Renders the filter cell content.
* The default implementation simply renders a blank space.
* This method may be overridden to customize the rendering of the filter cell (if any).
* #return string the rendering result
*/
protected function renderFilterCellContent()
{
return $this->filterContent;
}
}
Then you able to add both label and button to GridView replace default ActionColumn like this
In your view
use app\components\FilterActionColumn;
Replace default GridView ActionColumn
[
'class' => FilterActionColumn::className(),
// Add your own filterContent
'filterContent' => Html::a('Your button', ['some/url'], [
'class' => 'btn btn-default', 'title' => 'Some btn title',
]),
'header'=> 'Your label',
// Another ActionColumn options
// ..
],
You could see extended example here, i.e. if you need more than one button https://github.com/nick-denry/yii2-filter-action-column

GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'emptyCell' => Html::a('<i class="fa fa-refresh"></i> Reset', ['index'], ['class' => 'btn btn-primary btn-xs', 'style' => 'margin: 2px;']),
]);
use emptyCell to set button...

Related

Laravel 8: Extending UserCrudController from Package BackPack Permission-Manager

I want to add Department field in User entity, so I decided to extend the default UserCrudController from this package https://github.com/Laravel-Backpack/PermissionManager.
So I created a custom controller with this command php artisan make:controller Admin\UserController
In file \app\Providers\AppServiceProvider.php I also add this (as instructed)
public function register()
{
$this->app->bind(
\Backpack\PermissionManager\app\Http\Controllers\UserCrudController::class,
\App\Http\Controllers\Admin\UserController::class,
);
}
Then here is the content of \App\Http\Controllers\Admin\UserController
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Backpack\PermissionManager\app\Http\Controllers\UserCrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
class UserController extends UserCrudController
{
public function setupCreateOperation()
{
parent::setupCreateOperation();
$fields['departments'] = [
'label' => 'Departments',
'type' => 'select2_multiple',
'name' => 'tags',
'entity' => 'tags',
'attribute' => 'name',
'model' => "App\Models\Tag",
'pivot' => true,
'wrapper' => ['class' => 'form-group col-6 col-md-4'],
'options' => (function ($query) {
return $query->where('type', 'Department')->get();
}),
];
foreach($fields as $key=>$field) {
CRUD::addField($field);
}
}
public function setupUpdateOperation()
{
parent::setupUpdateOperation();
$this->setupCreateOperation();
}
}
All seems fine, I can see all default information such as: username, email, roles, permission and my custom department fields.
The problem is, when I try to modify an existing user adding some Departments, I got this error
The email has already been taken.
The password field is required.
Somehow it's treated as new user registration. What could be the problems?
Somehow, I solved it by copying setupCreateOperation to setupUpdateOperation.
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Backpack\PermissionManager\app\Http\Controllers\UserCrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
class UserController extends UserCrudController
{
...
public function setupUpdateOperation()
{
parent::setupUpdateOperation();
$fields['departments'] = [
'label' => 'Departments',
'type' => 'select2_multiple',
'name' => 'tags',
'entity' => 'tags',
'attribute' => 'name',
'model' => "App\Models\Tag",
'pivot' => true,
'wrapper' => ['class' => 'form-group col-6 col-md-4'],
'options' => (function ($query) {
return $query->where('type', 'Department')->get();
}),
];
foreach($fields as $key=>$field) {
CRUD::addField($field);
}
}
}
Hopefully there's a shorter way to reduce this duplication.

How to get values from my object model and display my banner on header in Prestashop

I developed a custom multi-banner module to display on the header of my prestashop page. When i save my changes on form i would like to display it on header.
My module form:
My table to see all banner inserted:
I tried to use smarty and orm to retrieve all information but i don't know how to display on my header.
Any issues? I hope i can understand my trobles :)
Thanks
Here's the code of some of my files:
//in main file:
public function hookDisplayHeaderBanner($params) {
$banner = Banner::getBannerToDisplay();
// If there is a banner to display
if ($banner) {
$this->context->smarty->assign([
'banner' => $banner
]);
return $this->display(__FILE__, 'views/templates/hook/display-custom-banner.tpl');
}
// Nothing to display
return false;
}
//In classes/Banner.php
class Banner extends ObjectModel
{
public $id;
public $color;
public $background_color;
public $content;
public static $definition = [
'table' => 'custom_banner',
'primary' => 'id_custom_banner',
'multilang' => false,
'fields' => [
'color' => [
'type' => self::TYPE_STRING,
],
'background_color' => [
'type' => self::TYPE_STRING,
],
'content' => [
'type' => self::TYPE_STRING
]
]
];
/*
*
* Return the banner to display
*
* Here we put the logic to select the right banner
*/
public static function getBannerToDisplay()
{
$sql = 'SELECT *
FROM `' . _DB_PREFIX_ . self::$definition['table'] . '`
WHERE active = 1';
return Db::getInstance()->getRow($sql);
}
}
//In display-custom-banner.tpl
<div id="banner" style="background-color:{$banner.background_color}!important;">
<p style="color:{$banner.color}!important;">
{$banner.content}
</p>
</div>
Using:
return Db::getInstance()->getRow($sql);
only retrieve the first row of the result, if you would like to return more than one banner you would like to use Db::getInstance()->executeS($sql); to get all results.
Also check your DB table structure and a var_dump() of the involved variables, this would help understanding if there are more issues.

Nested Whgridview. Grids disappear on sort or pagination click

I'm a newbie in Yii programming.
I'm using boostrap library on Yii via Yiistrap/Yiiwheels
I've created a relation table view
The related view is a Whgridview itself
The first (master grid) has a TbRelationColum clicking it i display the second grid (detail grid).
When I click on the row to display the sub grid, everything appears ok. When I change the sort order or the page of the sub grid disappear both grid.
I understand we should differentiate the css class of the pager and the sort of sub grid from the main grid. How to do this specifically in Yii-Way?
Is This the problem?
This is the view of the main grid:
$this->widget('yiiwheels.widgets.grid.WhGridView',array(
'id'=>'masterGrid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'template' => "{summary}{items}<div class=\"row-fluid\"><div class=\"pull-right\">{pager}</div></div>",
'type' => array(TbHtml::GRID_TYPE_BORDERED, TbHtml::GRID_TYPE_STRIPED),
'columns'=>array(
array(
'class' => 'yiiwheels.widgets.grid.WhRelationalColumn',
//'name' => 'multiMembers.id',
'type' => 'raw',
'header' => 'Sub Items',
'url' => $this->createUrl('multiGroup/ajaxSubItems'),
'cacheData' => false,
'value' => "CHtml::tag('button',array('class'=>'btn btn-primary'),'Sub Items')",
'htmlOptions'=>array('style'=>'width:90px;'),
'cssClass' => 'showSubItems',
),
'id',
'title',
array(
'class'=>'bootstrap.widgets.TbButtonColumn',
),
),
));
This is the sub-grid:
echo CHtml::tag('h3',array(),'Sub Items Group #"'.$id.'"');
$this->widget('yiiwheels.widgets.grid.WhGridView', array(
'id'=>'subGrid_'.$id,
'type'=>array(TbHtml::GRID_TYPE_BORDERED, TbHtml::GRID_TYPE_STRIPED),
'dataProvider' => $gridDataProvider,
'template' => "{summary}{items}<div class=\"row-fluid\"><div class=\"pull-right\">{pager}</div></div>",
'columns' => $gridColumns,
));
This is the controller:
/**
* Manages all models.
*/
public function actionAdmin()
{
$model=new MultiGroup('search');
$model->unsetAttributes(); // clear any default values
if (isset($_GET['MultiGroup'])) {
$model->attributes=$_GET['MultiGroup'];
}
$this->render('admin',array(
'model'=>$model,
));
}
public function actionAjaxSubItems()
{
$id = Yii::app()->getRequest()->getParam('id');
$model = $this->loadModel($id);
if($model->numSubItems > 0) {
$this->renderPartial('_child', array('id' => $id,
'gridDataProvider' => $this->getGridDataProvider($id),
'gridColumns' => $this->getGridColumns()
), false, true);
} else {
echo 'Non ci sono Sub Items.';
}
}
public function getGridDataProvider($id) {
$sql = 'SELECT * FROM multi_member WHERE groupid = :groupid ORDER BY lastname,firstname';
$cmd = Yii::app()->db->createCommand($sql);
$cmd->bindParam(':groupid', $id, PDO::PARAM_INT);
$result = $cmd->queryAll();
$dataProvider = new CArrayDataProvider(
$result, array(
'sort' => array(
'attributes' => array('id','groupid','firstname','lastname','membersince'),
'defaultOrder' => array('lastname' => CSort::SORT_ASC, 'firstname' => CSort::SORT_ASC),
),
'pagination' => array(
'pageSize' => 2,
),
));
return $dataProvider;
}
public function getGridColumns() {
return array('id', 'lastname', 'firstname', 'membersince');
}
How can I do?
thank you ..
If the extensions you're using all extend CGgridView, then you should be able to use option 'ajaxUpdate' (link to documentation).
Try setting 'ajaxUpdate'=>false in one of the grids (or in both of them) to see whether it helps you.
Sometimes setting ajaxUpdate to false is the only way I get get some grids to behave the way I want them to...

passing value from Yii CController class to CForm (Form Builder) config array

I'm new to Yii, and I'm trying to do my initial project the "right" way. I've created a CFormModel class that needs three fields to query for some data, a CForm config to construct the form, and a CController to tie it together (all given below).
The data request needs an account, and this can come from a couple of different places. I think retrieving it should be in the controller. However, I don't know how to get it into the form's hidden "account" field from the controller, so that it makes it to the arguments assigned to the CFormModel after submission. More generally, I know how to pass from CController to view script, but not to CForm. Is the registry (Yii::app()->params[]) my best bet?
I suppose I can just leave it out of the form (and required fields) and wait to populate it in the submit action (actionSummaries). Does that break the intention of CForm? Is there a best practice? Even taking this solution, can someone address the first issue, in case it comes up again?
Any other, gentle critique is welcome.
models/SummariesForm.php
class SummariesForm extends CFormModel
{
public $account;
public $userToken;
public $year;
public function rules () {...}
public function fetchSummary () {...}
static public function getYearOptions () {...}
}
views/account/select.php
<?php
$this->pageTitle=Yii::app()->name;
?>
<div class="form">
<?php echo $form->render(); ?>
</div>
controllers/AccountController.php
class AccountController extends CController
{
public $layout = 'extranet';
public function actionSelect ()
{
$model = new SummariesForm();
// retrieve account
require_once 'AccountCookie.php';
/*
*
* Here, I insert the account directly into the
* model used to build the form, but $model isn't
* available to selectForm.php. So, it doesn't
* become part of the form, and this $model doesn't
* persist to actionSummaries().
*
*/
$model->account = AccountCookie::decrypt();
if ($model->account === false) {
throw new Exception('Unable to retrieve account.');
}
$form = new CForm('application.views.account.selectForm', $model);
$this->render('select', array(
'form' => $form,
'account' => $model->account,
));
}
public function actionSummaries ()
{
$model = new SummariesForm();
if (isset($_POST['SummariesForm'])) {
$model->attributes = $_POST['SummariesForm'];
/*
*
* Should I just omit "account" from the form altogether
* and fetch it here? Does that break the "model"?
*
*/
if ($model->validate() === true) {
try {
$summaries = $model->fetchSummary();
} catch (Exception $e) {
...
CApplication::end();
}
if (count($summaries) === 0) {
$this->render('nodata');
CApplication::end();
}
$this->render('summaries', array('model' => $model, 'summaries' => $summaries));
} else {
throw new Exception('Invalid year.');
}
}
}
}
views/account/selectForm.php
<?php
return array(
'title' => 'Select year',
'action' => Yii::app()->createUrl('Account/Summaries'),
'method' => 'post',
'elements' => array(
'account' => array(
'type' => 'hidden',
'value' => $account,
),
'userToken' => array(
'type' => 'hidden',
'value' => /* get token */,
),
'year' => array(
'type' => 'dropdownlist',
'items' => SummariesForm::getYearOptions(),
),
),
'buttons' => array(
'view' => array(
'type' => 'submit',
'label' => 'View summaries',
),
),
);
The answer is NO to do what you asked. You can see $form variable which acted almost like array when it was passed from controller to view. The solution is you add more property $account into selectForm model and treat it like other elements. I don't think leaving the new field outside the form will be properly way if you want to submit its value also.
Edited:

CgridView pagination link

In my project, i am using cgridview to display some information and using the pagination built with the cgrid view. but now i am facing a usability problem with pagination. that's, consider i have 3 pages and the pagination looks like << < 1 2 3 > >>.
when i clicked the 3rd page the pagination should look like << < 1 2 3 and in case of 1st page the pagination should look like 1 2 3 > >>. how can i do this. please provide me a solution.
my widget looks like.
$widget = $this->widget('zii.widgets.grid.CGridView', array(
'id' => 'request-grid',
'dataProvider' => $model->search(),
'cssFile' => Yii::app()->baseUrl . '/media/css/gridview.css',
'summaryText' => '',
'enablePagination' => true,
'template' => '{items}',
'pager' => array(
'class' => 'LinkPager',
'cssFile' => false,
'header' => false,
'firstPageLabel' => 'First',
'prevPageLabel' => 'Previous',
'nextPageLabel' => 'Next',
'lastPageLabel' => 'Last',
),
'columns' => array(......));
also i am extending the CLinkPager class in the the component LinkPager.
class LinkPager extends CLinkPager
{
public $maxButtonCount=3;
}
in your css file you need to write
.yiiPager .hidden, .yiiPager .first, .yiiPager .last {
display: none;
}