Настройки GridView в Yii2

22 сентября, 2015
Метки: , ,

Тема вроде как изжеванна вдоль и поперек, но так как просили больше статьей для новичков, расскажу об интересных особенностях виджета GridView, т.к без него у меня еще не обходился ни один проект. В дальнейшем буду пополнять данный FAQ.

Поменять фон строки в зависимости от данных

Есть таблица с данными, допустим список пользователей, нужно некоторые из строк выделить другим цветом (например заблоченных юзеров выводить на сером фоне), т.к это куда нагляднее, чем просто надпись «вкл/выкл» в отдельном столбце. И реализуется проще простого: нужно добавить анонимную функцию в атрибут rowOptions

echo GridView::widget([
    'dataProvider' => $data,
    'rowOptions' => function ($model, $key, $index, $grid)
    {
      if($model->is_active == false) {
          return ['style' => 'background-color:#778899;'];
      }
    },
...
])

Т.к в функцию передается $index — текущий номер строки, можно четные строки раскрасить в один цвет, не четные в другой. Точно также можно передать любые параметры, которые попадут в нутрь тега tr. Если же вычислять ничего не нужно, то можно сразу указать массив параметров без анонимной функции

echo GridView::widget([
    'dataProvider' => $data,
    'rowOptions' => ['style' => 'background-color:#778899;'],
...
])

Добавить подстроки в зависимости от данных

Есть таблица с данными и к примеру нам нужно выводить дату записей с группировкой по месяцам. Январь — дальше строки таблицы за январь. Февраль и тп.Для этого существуют атрибуты beforeRow и afterRow.
Атрибуты beforeRow и afterRow работают по тому же принципу, что и rowOptions за тем исключением, что результат, полученный для этих функций будет выведен до и после тега tr.

$currentDate = date('m');
echo GridView::widget([
    'dataProvider' => $data,
    'beforeRow' =>function ($model, $key, $index, $grid) use ($currentDate)
    {
      if($model->month != $currentDate) {
          return '<tr><td colspan=10>'.$model->month.'</td></tr>';
      }
    }
...
])

Просуммировать данные по столбцу с учетом фильтров

Если вы используете ActiveDataProvider, то для решения достаточно понимать, что в query у вас экземпляр класса Query. Это такой не выполненный запрос. ActiveDataProvider добавит к нему limit и offset для постраничного вывода. Но вы может использовать этот запрос и сами, так как вам нужно. Например так:

 $query = MyModel::find()->where(...);
 $data =  new ActiveDataProvider([
            'query' => $query,
        ]);
 $totalSum = $query->sum('amount');

Поменять url для ссылок в ActionColumn

Если у вас используется один контроллер для множества гридов и вам нужно изменить только адрес ссылок для GridView, то сделать это можно передав анонимную функцию в качестве параметра urlCreator. Функция должна возвращать правильно сформированную ссылку:

  ['class' => 'yii\grid\ActionColumn',
   'template' => '{update}&nbsp;&nbsp;&nbsp;{delete}',
   'urlCreator'=>function($action, $model, $key, $index){
       return \yii\helpers\Url::to(['dashboard/user-'.$action,'id'=>$model->id]);
   }
  ]

Как видно из примера — простой способ изменить порядок кнопок или удалить каку-нибудь из стандартных ({update} {delete} {view}) — это передать параметр template.


Метки: , ,

Оставить комментарий

10 комментариев »

    Мурманск

    Спасибо большое, подстроки как раз мне нужны были). Ещё интересует на уровне новичков тема хранения например pdf файлов с возможностью для пользователей их скачки по временному рандомному пути, который они получат в сообщении.

      Developer

      Самое простое решение:
      1) генерим ссылку с параметром, по которому можно понять о каком файле речь и даем ее пользователю как ссылка на скачку
      2) по ссылке отдаем заголовки с рандомным именем файла и содержимое оригинального файла

      header("Content-type:application/pdf");
      header("Content-Disposition:attachment;filename='downloaded.pdf'");
      readfile("path/to/original.pdf");
      

      Минусы: отсутствие докачки, нагрузка на сервер. Для отдачи статических файлов лучше всего поднять отдельный сервер nginx.


    Мурманск

    Ещё вспомнил. Как то меня попросили сделать данные в гриде покомпактнее, уменьшить высоту строк и сделать поменьше шрифт. Подскажите, пожалуйста, как лучше это сделать в стандартном гриде в yii2?

      Developer

      Нужно прописать свои CSS-классы или стили. Заставить grid использовать их можно через такие атрибуты как tableOptions, options, captionOptions и тп (см класс yii\grid\GridView)
      Т.е будет примерно так:

      echo GridView::widget([
          'dataProvider' => $data,
          'tableOptions' => ['class' => 'my-table-class'];
      

    Роман

    Добрый день. А возможно ли в GridView сделать так, чтобы колонки были по одним данным, а фильтр по другим. Например табличка с данными по отзывам(отзыв, дата,положительный или отрицательный), а фильтр по пользователям этих отзывов(пол, возраст,…) ?
    Или разместить 2 связанных GridView, но в одном убрать фильтр, а в другом как-то скрыть строки, через rowOptions?

      Developer

      Можно. Если фильтровать более чем по 1 полю, то лучше делать форму поиска и результаты выводить в виде GridView (как форму search генерит gii). Если фильтровать столбец по одному параметру, то делаем так

       [
                      'class' => DataColumn::className(),
                      'attribute' => 'date',
                      'filter' => Users::getYears()
                  ],
                 
      

      Т.е что происходит:
      — метод Users::getYears() возвращает массив возрастов, он будет выпадающим списков сверху в фильтре.
      — в search методе нужно обработать это значение. Оно придет как значение аттрибута date
      Если массив значений для фильтра не нужен, то параметр filter не добавляем вообще, а просто в search методе обрабатываем значение как нам надо:

      // было
       $query->andFilterWhere(['like', 'date', $this->date])
      
      //станет что-то типа того
      $query->joinWith('user');
      $query->andWhere(['user.age' => $this->date]);
      

      Надеюсь смогла объяснить.


    Мурманск

    Подскажите, пожалуйста, как сделать две таблички.Чтобы при нажатии на любую строчку из первой таблички, например, справа во второй табличке раскрывались подробные характеристики строчки из первой таблицы.

      Developer

      В первой таблице ссылка должна отправлять ajax запрос и отображать результат в том месте где 2-я таблица.

      Pjax::begin();
      Html::a('Ссылка в качестве значения колонки в первой таблице', 
      $url, [ 'data-pjax' => '#table2']);
      Pjax::end();
      
      Pjax::begin(['id' => 'table2']);
      // Начальный текст второй таблицы
      Pjax::end();
      

      В контроллере нужно не забывать делать renderAjax вместо render. Надеюсь стало понятнее в какую сторону смотреть.


    Мурманск

    По предыдущему вопросу по двум зависимым табличкам.
    А можно решить эту проблему с помощью partial view? Без ajax. Подскажите, пожалуйста

      Developer

      Смотрите как это работает: юзер кликнул на ссылку. Вместо того, чтобы перезагружать страницу, отправляем запрос на сервер (ajax) и в ответ получаем кусочек view (renderPartial или renderAjax) только той части, которая нужна для второй таблицы и с помощью JavaScript выводим полученные данные в нужном месте страницы (нужный яваскрипт уже есть в компоненте yii Pjax). Т.е без ajax запроса на сервер не получится.
      Но можно сделать и по другому: загружать на страницу сразу всю информацию и скрывать лишнюю в скрытых css дивах. По клику на ссылку с помощью JavaScript нужный див показывается, а все остальные остаются скрытыми.


Оставить комментарий:









Копирование материалов разрешено при наличии активной ссылки на источник