Closed Insolita closed 8 years ago
Example would be introduced of clarity into the issue.
Inheritance work for me, but for example - exists gridview class for sortable columns, exist gridview for grouping columns, exist kartk plugin... with many useful, but sometimes redundant functionality In my projects i need in all types, and i if want add some more functionality... such as support for dynamic change page size, or columns visibility, or smthing other, i must extends all of this, and write similar code, move functional from one to another and have many dependecies from their developer changes...Or create own casino with blackjack... May be not all of customizations are in need of events, but i think behavior-way made it more flexible for usage - need in pdf-export - attach behavior, need in floatheader - attach it etc.
In words, I like it. But implementation
Sounds OK but are events sufficient for creating such behaviors?
I propose to create a new class extending GridView
named ActiveGridView
The reasons:
GridView
doesn't communicate to each otherGridView
doesn't communicate to each other<tfooter>
is barely used.When making reports for example you use need to do things like calculate the total sum of a column, the average in a date range, the total sum in a row, the percentaje of a column based on the total sum.
Example
Sales
Month | Shoes | Tshirts | Pants | Total | |||
---|---|---|---|---|---|---|---|
xx | Quantity | Percentage | Quantity | Percentage | Quantity | Percentage | xx |
January | 10 | 20% | 15 | 30% | 25 | 50% | 50 |
February | 12 | 25% | 24 | 50% | 12 | 50% | 48 |
-------- | ---- | ------- | ------ | ------- | ----- | -------- | ---- |
Total | 22 | 22% | 39 | 38% | 37 | 40% | 98 |
Average per month | 11 | 22% | 19.5 | 38% | 18.5 | 40% | 49 |
Currently with GridView
this would be a lot of work, so much it would be easier to generate the data using yii\db\Query
and then simply use the yii views to do a lot of echo's on the data provided by the query.
I propose that ActiveGridView
and ActiveColumn
classes sp that you can call behaviors that communicate on each part of the process.
Example:
SumBehavior : everytime a cell is processed in a column it adds the value to a total and echo's it on the footer.
AverageBehavior : everytime a cell is processed it adds the value to a total and keeps a count on the number of cells have been processed, to echo's it on the footer.
SumRowBehavior : Everytime a cell in a row in processed it adds the value to a target column.
PercentageRowBehavior : configured with a 'totalColumn' and a parentColumn which will basically calculate the percentage of parentColumn with respect of totalColumn.
They will be used like this
$grid = ActiveGridView::begin([
'dataProvider' => $dataProvider,
'behaviors' => [
'sum' => SumBehavior::className(),
'average' => AverageBehavior::className(),
'rowSum' => [
'class' => SumRowBehavior::className(),
'totalColumn' => 'total', //adds the value of the column attribute to this column
],
'averageRow' => [
'class' => AverageRowBehavior::className(),
'totalColumn' => 'total', //gets the value of this column to calculate the average
],
],
'columns' => [
'month' => [
'label' => 'Month',
'attribute' => 'month',
'format' => ['date', 'php:m']
],
'shoes' => [
'class' => ActiveColumn::className(),
'label' => 'Shoes',
'attribute' => 'shoes',
'behaviors' => ['sum', 'average', 'sumRow', 'averageRow'],
],
'tshirts' => [
'class' => ActiveColumn::className(),
'label' => 'T-shirts',
'attribute' => 'tshirts',
'behaviors' => ['sum', 'average', 'sumRow', 'averageRow'],
],
'pants' => [
'class' => ActiveColumn::className(),
'label' => 'Pants',
'attribute' => 'pants',
'behaviors' => ['sum', 'average', 'sumRow', 'averageRow'],
],
'total' => [
'class' => TargetColumn::className(),
'format' => 'number',
'initialValue' => 0,
],
],
]);
$grid->startHead(/* $headOptions */);
$grid->head();
$grid->endHead();
$grid->startBody(/* $bodyOptions */);
$grid->body();
$grid->endBody();
$grid->startFooter(/* $footerOptions */);
$grid->footer();
$grid->behaviors->sum->printRow();
$grid->behaviors->average->printRow();
$grid->endFooter();
ActiveGridView::end();
It will require the following events:
begin
, startHead
, endHead
,startBody
, endBody
,startFooter
, head
, body
, footer
, endFooter
, beforeContent
, afterContent
, end
very similar to the layout events. http://www.yiiframework.com/doc-2.0/guide-structure-views.html#creating-layouts
Faryshta, interesting idea аs my example its https://github.com/Insolita/gridconcept (draft only)
@Insolita it looks very interesting, but i don't understand what any of those behaviors do :)
we agreee that the columns and behaviors should added with names so that they can be individually accesible later.
I'am interested too in gridview extending. But i think there is a simple way with $layout placeholders. To enable custom placeholders in $layout little fix in ::renderSection can be made.
class GridViewExt extends GridView
{
public function renderSection($name)
{
$html = parent::renderSection($name);
if (!$html) {
$renderMethod = 'render' . trim($name, '{}');
if ($this->hasMethod($renderMethod)) {
$html = $this->{$renderMethod}($name);
}
}
return $html;
}
}
Custom placeholder usage can be like this:
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => $columns,
'layout' => "{summary}\n{items}\n{pager}\n{actionsBar}",
'as actionsBar' => [ // behavior with method renderActionsBar()
'class' => ActionsBarBehavior::className(),
...
],
]);
Merged into #7435
GridView as component may have behaviors, but it`s mindlessly in practice - It would be nice if we can modify logic in methods such as init, guessColumns, renderFilters etc. by attach behaviors on events from this methods, instead of make different classes extended GridView or super-universal such as kartik\grid project