GridView комбинирование ячеек (rowspan)

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
fly2k
Сообщения: 155
Зарегистрирован: 2013.03.19, 05:31

GridView комбинирование ячеек (rowspan)

Сообщение fly2k »

Ку!

Давно хочу разобраться как по уму делать сабж. Самый распространённый пример, когда нужно сделать, чтобы в одной ячейке отображалось 2 или более атрибутов. Само отображение - без проблем, что хочешь можно написать в анонимной функции сваойства value от DataColumn. Но вот как сделать чтобы в заголовке табицы указывалось labels от 2х атрибутов, да еще и с href'ами, для сортировки. Что нибудь типа "Attr1 / Attr2"...

Можно указать свойство header в DataColumn, но это уже статика, линки на сортировку тогда как то вручную тут же нада задавать. Но я не въехал пока как. Немного поизучал сырцы, глянул на yii/data/Sort, но пока не догнал как это все засунуть в header от DataColumn,

Подскажите плз. Примерно понятно как это сделать переопределением классов DataColumn и/или GridView, но хочелось бы меньшей кровью.

Спасибо!
// Yii2Rulez!
fly2k
Сообщения: 155
Зарегистрирован: 2013.03.19, 05:31

Re: GridView комбинирование ячеек (rowspan)

Сообщение fly2k »

чтобы было понятно приведу код:

Код: Выделить всё

...
$columns = [
    ...
    [
        //'header' => 'title', // тут нада как то сказать что отображаем в хедере title & name и позволить сортировку по ним
        'attribute' => 'name', // так показывает label и сортировку только по name, если не указать, то хедер пустой
        'format' => 'raw',
        'value' => function($model) {
                $return = '<span class="lead">' . $model->name . '</span><br>';
                $return .= '<small>' . $model->title . '</small>';
                return $return;
            },
    ],
    ...
];
echo GridView::widget([
    'dataProvider' => $dataProvider,
    //'filterModel' => $searchModel,
    'columns' => $columns,
]);
...
// Yii2Rulez!
astronin
Сообщения: 606
Зарегистрирован: 2012.01.30, 17:46

Re: GridView комбинирование ячеек (rowspan)

Сообщение astronin »

на сколько я знаю ни как
мне пришлось переопределить три файла и несколько методов чтоб сделать такую штуку...
fly2k
Сообщения: 155
Зарегистрирован: 2013.03.19, 05:31

Re: GridView комбинирование ячеек (rowspan)

Сообщение fly2k »

а можно подробнее? чтоб велосипед не изобретать, можно без кода, хотя бы какие методы каких классов посмотреть на предмет переопределения...
// Yii2Rulez!
aquy
Сообщения: 48
Зарегистрирован: 2014.08.21, 09:35

Re: GridView комбинирование ячеек (rowspan)

Сообщение aquy »

нужно в сеарч модели прописывать новое свойство, которое будет объединять ваши оба свойства и в модели же прописывать сортировку для получившегося нового свойства, а в виджет уже подсовывать новое поле модели, которое уже будет сортироваться и показывать то что вам нужно

PS делается это примерно так же, как фильтрация и сортировка по связанным таблицам
astronin
Сообщения: 606
Зарегистрирован: 2012.01.30, 17:46

Re: GridView комбинирование ячеек (rowspan)

Сообщение astronin »

fly2k писал(а):а можно подробнее? чтоб велосипед не изобретать, можно без кода, хотя бы какие методы каких классов посмотреть на предмет переопределения...
Выложил на github, но еще не оформил. Внимание, это пока только для YII2 Beta, стабильный пока еще не вышел, так что код скорей всего придется менять/мержить потом.
https://github.com/AstRonin/yii2_improv ... components

вам нужен будет DataColumn::renderHeaderCells(), GridView::renderTableHeader()
при формировании виджета указываем

Код: Выделить всё

'dataColumnClass' => 'common\components\grid\DataColumn',
потом внутри columns

Код: Выделить всё

'attributes' => ['attribute1', 'attribute'],
к примеру, ['first_name', 'second_name']
можно еще добавить

Код: Выделить всё

'labels' => [Yii::t('frontend.user', 'Label1'), Yii::t('frontend.user', 'Label2')],
Кажется все, если не заработает, пишите в личку, разберемся
fly2k
Сообщения: 155
Зарегистрирован: 2013.03.19, 05:31

Re: GridView комбинирование ячеек (rowspan)

Сообщение fly2k »

Спасибо огромное! Ваш опыт очень пригодился! Но я всё таки написал свой костыль :)
Буду признателен за рассмотрение и любые комментарии:

Код: Выделить всё

<?php

namespace flyiing\uni\grid;

use yii\helpers\Html;
use yii\grid\DataColumn;

/**
 * Class DataCombineColumn
 * @package flyiing\uni\grid
 *
 * Renders several attributes combined in one grid column
 */

class DataCombineColumn extends DataColumn
{

    /**
     * @var array
     * List of attributes to combine
     * Simple format: [ 'attr1_name', 'attr2_name', ... ]
     * Extended format:
     * [
     *     'attr1_name' => [ // attribute name as item key
     *          'label' => 'attr1_label',
     *          'format' => 'attr1_format',
     *          ... // any property of the base DataColumn class possible here...
     *     ],
     *     [
     *          'attribute' => 'attr2_name', // attribute name as item property
     *          ...
     *     ],
     * ]
     */
    public $attributes = null;

    /**
     * @var string
     * Template for data cell in format: '...{attr1_name}...{attr2_name}...{attrN_name}...'
     */
    public $template = null;
    /**
     * @var string
     * Template for header cell in same format ^^^
     * If null, $template will be used
     */
    public $headerTemplate = null;

    /**
     * @var array
     * backup variable to store base/default properties
     */
    private $_staticData = null;

    public function init()
    {
        parent::init();

        // setting up default templates if empty
        if($this->template === null) {
            $this->template = '';
            foreach($this->attributes as $key => $value) {
                if(is_array($value)) {
                    if(is_string($key))
                        $attr = $key;
                    if(isset($value['attribute']))
                        $attr = $value['attribute'];
                } elseif(is_string($value))
                    $attr = $value;
                $this->template .= '{' . $attr . '}<br>';
            }
        }
        if($this->headerTemplate === null)
            $this->headerTemplate = $this->template;

        $this->_staticData = \yii\helpers\ArrayHelper::toArray($this, [], false);
    }

    public function renderHeaderCell()
    {
        if($this->attributes === null)
            return parent::renderHeaderCell();

        $items = [];
        foreach($this->attributes as $key => $value) {

            if(is_array($value)) {
                if(is_string($key))
                    $this->attribute = $key;
                \Yii::configure($this, $value);
            } elseif(is_string($value))
                $this->attribute = $value;

            $items['{' . $this->attribute . '}'] = $this->renderHeaderCellContent();
            \Yii::configure($this, $this->_staticData);

        }

        return Html::tag('th', strtr($this->headerTemplate, $items), $this->headerOptions);
    }

    public function renderDataCell($model, $key, $index)
    {
        if($this->attributes === null)
            return parent::renderDataCell($model, $key, $index);

        // copy-past from yii2\grid\Column
        if ($this->contentOptions instanceof Closure) {
            $options = call_user_func($this->contentOptions, $model, $key, $index, $this);
        } else {
            $options = $this->contentOptions;
        }

        $items = [];
        foreach($this->attributes as $key => $value) {

            if(is_array($value)) {
                if(is_string($key))
                    $this->attribute = $key;
                \Yii::configure($this, $value);
            } elseif(is_string($value))
                $this->attribute = $value;

            $items['{' . $this->attribute . '}'] = $this->renderDataCellContent($model, $key, $index);
            \Yii::configure($this, $this->_staticData);

        }

        return Html::tag('td', strtr($this->template, $items), $options);
    }

}
в принципе, то что мне нужно работает... вот пример использования в моем коде про юзеров, это один элемент массива columns от GridView:

Код: Выделить всё

    [
        'class' => \flyiing\uni\grid\DataCombineColumn::className(),
        'template' => '<span class="lead">{username}</span><br>{email}',
        'headerTemplate' => '{username}<br><small>{email}</small>',
        'attributes' => [
            'username',
            'email' => ['format' => 'email'],
        ],
    ],
объясните, зачем трогать сёрчмодели, сорты итд? даже GridView оказалось можно не трогать... чем плох мой подход? какие тут могут быть подводные камни?
пока что заметил только отсутсвие филтра в столбце, но я на эту тему ничего и не делал, ибо мне не нада.

Спасибо!
// Yii2Rulez!
fly2k
Сообщения: 155
Зарегистрирован: 2013.03.19, 05:31

Re: GridView комбинирование ячеек (rowspan)

Сообщение fly2k »

еще примеры :) :

Код: Выделить всё

    [
        'class' => \flyiing\uni\grid\DataCombineColumn::className(),
        'attributes' => [
            'status' => [
                'value' => function($model) {
                        return $model->statusLabel;
                    },
            ],
            'logged_at' => ['format' => 'datetime'],
        ],
    ],
    [
        'class' => \flyiing\uni\grid\DataCombineColumn::className(),
        'format' => 'datetime',
        'attributes' => ['created_at', 'updated_at'],
    ],
ну красяво же? :)
// Yii2Rulez!
Ответить