I have a grid view which is like this. The columns are calculated with the help of MySQL query and displayed accordingly.
<?php
$subquery = Adanalytics::find()->
select('id,ad_id,date_event,max(cpc) cpclick,max(cpv) cpview,max(impression) impression,max(view) view,max(clicks) clicks,visitor_ip,publisher_id')->
from('ad_analytics')->
where(['publisher_id' => Yii::$app->user->identity->id ])->
groupBy('ad_id,date_event,visitor_ip');
$query=Adanalytics::find()->
select('ad_id,date_event,sum(cpclick) total_click_cost,sum(cpview) total_view_cost,sum(impression) total_impression,sum(view) total_views,sum(clicks) total_clicks,publisher_id')->
from(['t'=>$subquery])->
groupBy('t.ad_id,t.date_event');
?>
<?= GridView::widget([
'dataProvider'=>new ActiveDataProvider([
'query' => $query,
]),
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'ad_id',
'total_impression',
'total_views',
'total_clicks',
'total_click_cost',
'total_view_cost',
'date_event',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
I want to show a grand total column at the bottom of this grid view.
For example
'grand_total_impression',
'grand_total_views', //This is the sum of all displayed views
'grand_total_clicks',//This is the sum of all displayed clicks
'grand_total_click_cost',//THis is the sum of all displayed cost
'grand_total_view_cost',//This is the sum of all displayed view cost
To do that I have code in my controller which is like this.
public function actionIndex()
{
$searchModel = new Adanalytics2Search();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
$grandTotal = [];
foreach ($dataProvider->getModels() as $value) {
// var_dump($value);
// exit();
$grandTotal['total_click_cost'] += $value['total_click_cost'];
$grandTotal['total_view_cost'] += $value['total_view_cost'];
}
//var_dump($dataProvider);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'grandTotal' => $grandTotal,
]);
}
But it is producing the error in at this way.
Undefined index: total_click_cost
Where am I going wrong? Or is there any other way to solve this problem?
I strongly advise you to use katrik gridview. It handles page summary much better and implements a lot of other usages. Alternatively add 'showPageSummary' => true at your gridview to display columns summary.
use kartik\grid\GridView;
// Create a panel layout for your GridView widget
echo GridView::widget([
'dataProvider'=> $dataProvider,
'filterModel' => $searchModel,
'columns' => $gridColumns,
'showPageSummary' => true
]);
Similar question: Yii2: Kartik Gridview sum of a column in footer
This has solved the problem anyway.
This in grid column.
[
'attribute'=>'total_impression',
'pageSummary' => true
],
And in grid view
'showPageSummary' => true,
Related
I'm loading a gridview inside a page with an ajax request.
Then, after the page is loaded, i want to let the user order and search as usual with gridview, obviously not reloading the page.
While the sorting works, the search reloads the page (and since the action loading the ajax content is different from the current one the page changes entirely). I know Pjax reloads the entire page after the timeout value, but that is not the problem as i changed to a really high value and i still get the reload.
Also, that is the only pjax on the page.
What could be the problem?
This is the code for the view with the gridview
<?php Pjax::begin([
"id" => "associates-ajax-list",
"enablePushState" => FALSE,
"enableReplaceState" => FALSE,
"timeout" => 5000,
]); ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'name',
'surname',
],
]); ?>
<?php Pjax::end(); ?>
</div>
This is the code for the ajax action
public function actionAssociatesList($id) {
$searchModel = new \app\models\AssociateSearch();
$searchModel->associates_for = $id;
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
if (Yii::$app->request->isAjax) {
return $this->renderAjax('associates_list', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
} else {
return $this->render('associates_list', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
}
The page where this content is loaded is a standard view page generated with Gii
Can you try with adding this script in the view?
<?php
$this->registerJs(
'$("document").ready(function(){
$("#associates-ajax-list").on("pjax:end", function() {
$.pjax.reload({container:"#associates-ajax-list"}); //Reload GridView
});
});'
);
?>
You might need to alter some selectors since I don't know how the HTML looks like in your project.
AND you might need some JS to prevent the default submit action if the search fields are in a <form>. If not, the form will submit before the PJAX can trigger.
The problem was the gridview.
You need to specify an id.
The funny thing is that this gridview was the only one generated for this page, so apparently there was no conflict.
<?= GridView::widget([
'id' => "grid-view-name",
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
I have problems with loading data from database.
My goal is to implement a MVC which dynamically shows in the view the values stored in the db table. So, in the Project model I have this code:
public function search($params)
{
$query = project::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'position' => $this->position,
'created_at' => $this->created_at,
'is_deleted' => $this->is_deleted,
]);
$query->andFilterWhere(['ilike', 'title', $this->title])
->andFilterWhere(['ilike', 'description', $this->description])
->andFilterWhere(['ilike', 'link', $this->link])
->andFilterWhere(['ilike', 'image', $this->image]);
return $dataProvider;
}
In the Controller:
public function actionIndex()
{
$searchModel = new SeachProject();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
And in the view (index.php):
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'title',
'description',
'image',
],
]); ?>
Well, it works but I need to print the values into Uikit cards and not through Gridview limitations (which is actually the only way I know). I should have one card for each record in the table with an image (the url in the image field of the table) and a link (the url in the link field of the table).
Any words of advise would be good, thanks in advance!
You can use ListView and create any kind of structure using UiKit cards or material design.
The ListView widget is used to display data from a data provider. Each
data model is rendered using the specified view file. Since it
provides features such as pagination, sorting and filtering out of the
box, it is handy both to display information to end user and to create
data managing UI.
A typical usage is as follows:
use yii\widgets\ListView;
use yii\data\ActiveDataProvider;
echo ListView::widget([
'dataProvider' => $dataProvider,
'itemView' => '_ui-card',
'viewParams' => [
'fullView' => true,
'context' => 'main-page',
],
]);
The _ui-card view file could contain the following basic card html :
<?php
use yii\helpers\Html;
use yii\helpers\HtmlPurifier;
?>
<div class="uk-card">
<div class="uk-card-header">
<h3 class="uk-card-title"><?= Html::encode ( $model->title ) ?></h3>
</div>
<div class="uk-card-body"><img src="<?= Html::encode ( $model->image ) ?>"><?= Html::encode ( $model->link ) ?></div>
<div class="uk-card-footer"></div>
</div>
This way you can show every project as a separate card using the view file.
Hope this helps
I want to multiply two columns in the yii2 grid the grid view is as follows
<?= GridView::widget([
//'dataProvider' => $dataProvider,
'dataProvider'=>new ActiveDataProvider([
'query' => Adanalytics::find()->
where(['publisher_id' => Yii::$app->user->identity->id ])->
select('id,ad_id,MAX(impression) AS impression, MAX(view) AS view, MAX(clicks) AS clicks,MAX(cpc) AS cpclick,MAX(cpv) AS cpview, (MAX(clicks)*MAX(cpc)) AS totalccost')->
groupBy('ad_id, visitor_ip'),
]),
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
//'id',
'ad_id',
//'advertiser_id',
//'publisher_id',
//'visitor_ip',
//'type_ad',
'impression',
'view',
'clicks',
//'placed_date',
//'cpc',
//'cpv',
'cpclick',
'cpview',
'totalccost',
//'cpi',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
But it is not giving me the desired output where am I going wrong how can i do this?
If you need the column only as display value in the gridview you can create a calculated column.
'cpview',
[
'label' => 'Totalcost',
'value' => function($model){
return $model->cpclick * $model->clicks;
}
],
Or else you can add at the start of your Adanalytics class
public $totalccost;
if you want to use the calculation anywhere you can do following.
in your model
public function getTotalcost()
{
return $this->clicks * $this->cpclick;
}
and you can label to this attribute
public function attributeLabels()
{
return [
...
'totalcost' => Yii::t('app', 'Total cost'),
];
}
in grid view column
...
'cpview',
'totalcost'
You can use this function anywhere as $model->totalcost
I have solved the problem by using yii2 db query which is like this way.
$subquery = Adanalytics::find()->
select('id,ad_id,date_event,max(cpc) cpclick,max(cpv) cpview,max(impression) impression,max(view) view,max(clicks) clicks,visitor_ip,publisher_id')->
from('ad_analytics')->
where(['publisher_id' => Yii::$app->user->identity->id ])->
groupBy('ad_id,date_event,visitor_ip');
$query=Adanalytics::find()->
select('ad_id,date_event,sum(cpclick) total_click_cost,sum(cpview) total_view_cost,sum(impression) total_impression,sum(view) total_views,sum(clicks) total_clicks,publisher_id')->
from(['t'=>$subquery])->
groupBy('t.ad_id,t.date_event');
And called the column in grid view.
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'ad_id',
'total_impression',
'total_views',
'total_clicks',
'total_click_cost',
'total_view_cost',
'date_event',
['class' => 'yii\grid\ActionColumn'],
],
Defined them in model before calling.
public $total_click_cost;
public $total_view_cost;
public $total_impression;
public $total_views;
public $total_clicks;
i'm developing a web application with Yii2 framework, and i'm facing a problem right now. I want to display the data from a many-to-many relation in a gridview and be able to filter from those fields later on.
I've read the official documentation here, some stackoverflow post like this and other resources but can't seem to get it to work. I have 3 tables: actividad, plan_actividad and circulo_icare, actividad is related to plan_actividad and circulo_icare is also related to it (plan_actividad is the junction table). So i have defined the following relations in my Actividad model:
class Actividad extends \yii\db\ActiveRecord
{
....
public function getPlanActividad()
{
return $this->hasMany(PlanActividad::classname(), ['act_id' => 'act_id']);
}
public function getCirculo()
{
return $this->hasMany(CirculoIcare::classname(), ['cirica_id' => 'act_id'])->via('planActividad');
}
...
}
The in my view index.php i'm trying to show the values in a gridview like this:
<?= GridView::widget([
'dataProvider' => $dataProvider,
// 'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
// 'act_id',
['attribute' => 'Codigo Evento', 'value' => 'act_numorden'],
['attribute' => 'Nombre Evento', 'value' => 'act_nombre'],
['attribute' => 'Fecha Evento', 'value' => 'act_fecha'],
['attribute' => 'Locacion', 'value' => 'locacion.loc_nombre'],
[
'attribute' => 'Circulo',
'value' => 'circulo.cirica_nombre',
],
['attribute' => 'Circulo id',
'value' => 'planActividad.cirica_id',
],
// 'act_horaini',
// 'act_horafin',
// 'act_idencuesta',
// 'act_vigencia:boolean',
// 'loc_id',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
The problem is, i can't get any values to show with the circulo relation, it always shows (not set). If i change hasMany in getPlanActividad() with hasOne() then it shows some values (only 2 of 11 it should, based on the cirica_id that exist on plan_actividad table) but these are not correct anyway. I know that i can filter for those fields later on in search view but i don't really understand why the relations doesn't work as i expected.
Any help would be greatly appreciated, let me know if more info is needed and thank you in advance.
Answering my own question (credits to softark from the yii official forums).
In order for the relation to work as expected, I had to change:
public function getCirculos()
{
return $this->hasMany(CirculoIcare::classname(), ['cirica_id' => 'act_id'])->via('planActividad');
}
to
public function getCirculos()
{
return $this->hasMany(CirculoIcare::classname(), ['cirica_id' => 'cirica_id'])->via('planActividad');
}
and use a callback function in the gridview to display the correct values, since a hasMany relation gives an array of models and not a single model. So I modified the gridview code to:
<?= GridView::widget([
'dataProvider' => $dataProvider,
// 'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
...
['attribute' => 'circulo',
'value' => function($model){
$items = [];
foreach($model->circulos as $circulo){
$items[] = $circulo->cirica_nombre;
}
return implode(', ', $items);
}],
...
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
This gives the expected results. You can then apply filter by the relation fields easily by adapting the search model.
What data must be sended to dataprovider?
In my controller:
public function actionIndex() {
$searchModel = new UserSearch();
$dataProvider = $searchModel->search( Yii::$app->request->queryParams );
//other stuff and sending array of params to view
in a view:
echo ListView::widget( [
'dataProvider' => $dataProvider,
] );
but i got only id`s:
And if i`m set single view like:
'itemView' => '_single',
how send data to _single.php ?
I mean - need default template for view list items like in GridView:
GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
'username',
'email:email',
'password',
'role',
//....
And then i got perfect grid:
Controller - SiteController.php
<?php
// Yii2 Listview Example : by Songwut Kanchanakosai, Thailand.
use common\models\Members;
use common\models\SearchMembers;
...
public function actionIndex() {
$searchModel = new SearchMembers();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
?>
View (1) - index.php
<?php
use yii\widgets\ListView;
...
echo ListView::widget( [
'dataProvider' => $dataProvider,
'itemView' => '_item',
] ); ?>
View (2) - _item.php
<?php
use yii\helpers\Html;
?>
<?=$model->name;?>
<?=$model->age;?>
<?=$model->mobile;?>
Example Result :
Songwut 36 +668-3949-5153
Prawee 41 +668-7323-2334
Kosol 32 +668-8014-0165
Utehn 39 +668-7874-5643
how send data to _single.php ?
Here is how, use $viewParams
$viewParams public property array $viewParams = []
Additional parameters to be passed to $itemView when it is being
rendered. This property is used only when $itemView is a string
representing a view name.
echo ListView::widget( [
'dataProvider' => $dataProvider,
'viewParams'=>['name'=>'My Name is Stefano'], //acccessed in view as $name with value 'My Name is Stefano'
] );
in official docs http://www.yiiframework.com/doc-2.0/yii-widgets-listview.html#$itemView-detail
$itemView public property
The name of the view for rendering each data item, or a callback (e.g. an anonymous function) for rendering
each data item. If it specifies a view name, the following variables
will be available in the view:
$model: mixed, the data model
$key: mixed, the key value associated with the data item
$index: integer, the zero-based index of the data item in the items array returned by $dataProvider.
$widget: ListView, this widget instance
So your User model data should be available in _single.php as $model->username
So i suppose can use Detail View in _single.php i think:
DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'username',
'email:email',
//....