О возможностях Yii CGridView на примерах. Часть 1: визуальное представление

2 сентября, 2014
Метки:

CGridView — один из виджетов Yii-framework. Он позволяет выводить данные объектов модели в виде удобной таблицы, с кнопками управления записями.

<?php $this->widget('zii.widgets.grid.CGridView', array(
    'id'=>'country-grid',
    'dataProvider'=>$model->search(),
    'filter'=>$model,
    'columns'=>array(
        'id',
        'name',
        'region',
        array(
            'class'=>'CButtonColumn',
        ),
    ),
)); ?>

Это незаменимый виджет для любой админки. Если лень писать руками, его можно сгенерировать с помощью gii. Но то, что генерируется автоматически не всегда совпадает с потребностями разработчика. В моем примере CGridView используется для вывода и управления списком стран. Давайте рассмотрим возможности CGridView на этом примере.

Как изменить стандартные кнопки в CGridView

Как вы наверное уже догадались, за кнопки управления отвечает кусок кода

array(
  'class'=>'CButtonColumn',
),

Что будет, если разместим его не в конце списка колонок, а в начале? Правильно: кнопки управления будут до колонок с данными 🙂
По умолчанию кнопок бывает 3 (редактирование, просмотр и удаление). Ссылаются они на контроллер, совпадающий с именем модели.

  • Чтобы изменить порядок и вывод стандартных кнопок достаточно добавить атрибут template
    array(
      'class'=>'CButtonColumn',
      'template'=>'{view}<div class="button">{update}</div>{delete}',
    ),
    

    Из примера видно, что сами кнопки обозначаются как {view}, {update} и {delete}. Их можно обернуть в любой html-код. Таким же образом можно избавиться от «лишних» кнопок, просто не перечисляя их в данном блоке.

    array(
      'class'=>'CButtonColumn',
      'template'=>'{delete}',
    ),
    
  • Чтобы изменить ссылку стандартной кнопки нужно переопределить xxxButtonUrl (viewButtonUrl, updateButtonUrl, deleteButtonUrl соответственно)
    array(
    'class'=>'CButtonColumn',
    'template'=>'{update}{delete}',
    'updateButtonUrl'=>'Yii::app()->getUrlManager()->createUrl("/admin/editCountry/", array("id" => $data->id))',
    'deleteButtonUrl'=>'Yii::app()->getUrlManager()->createUrl("/admin/delCountry/", array("id" => $data->id))'
            )
    

    Обратите внимание: метод, возвращающий ссылку записан в одинарные кавычки! Это просто текстовая строка. Он не должен выполняться на этапе компиляции данного php-скрипта. Текущие данные строки таблицы доступны через объект $data.

  • Чтобы добавить свою кнопку нужно задать ей имя в template и определить все параметры кнопки в buttons

    'class'=>'CButtonColumn',
    'template'=>'{moderation}&nbsp;&nbsp;{delete}',
    'buttons'=>array
    (
      'moderation' => array
      (
        'label'=>'Одобрить',   
        'url'=>'Yii::app()->getUrlManager()->createUrl("admin/moderation/", array("id" => $data->id))',
    'imageUrl' => '/img/moderation.png',
       ),
    ),
    'deleteButtonUrl'=>'Yii::app()->getUrlManager()->createUrl("/admin/delCountry/", array("id" => $data->id))'
    )
    

    Если не задан imageUrl, ссылка будет просто текстовая.

  • Как спрятать кнопку, при определенных условиях. Мне не нужна кнопка «модерирования» для уже промодерированных записей. Добавляем свойство visible
    'buttons'=>array
    (
      'moderation' => array
      (
        'label'=>'Одобрить',   
        'visible' => '$data->moderation == 0'
        'url'=>'Yii::app()->getUrlManager()->createUrl("admin/moderation/", array("id" => $data->id))',
    'imageUrl' => '/img/moderation.png',
       ),
    ),
    

    Теперь кнопка отображается только на тех строках, где выполняется условие visible. В visible можно прописать не только выражение, но и вызов функции, возвращающий true или false. Только учтите, что этот вызов должен быть передан в виде строки.
    Помимо этого, кнопке можно добавить событие по клику, прописав вызов JS-функции в виде свойства ‘click’. Событие так-же должно указываться в виде строки.

Как изменить данные в колонках CGridView

  • Чтобы вывести данные в колонке CGridView в виде html-кода, картинки, ссылки и тп нужно в списке колонок передать массив параметров
    'columns'=>array(
            'name',
             array(
               'name'  => 'flag',
               'value' => '"/images/".$data->flag',
               'type'  => 'image',
               'filter' => false
            ),
            region,
    

    Параметр name влияет на название колонки. Это может быть как просто строка, так и атрибут модели. Во втором случаи названием колонки будет то, что прописано для атрибута в методе attributeLabels модели Country.
    filter — отвечает за фильтрацию данных. О нем поговорим в другой статье.
    Value — это значение колонки. Данные строки все так же доступны через объект $data. Тут может быть как просто строка, так и вызов метода. Единственное о чем нужно помнить — вызов должен быть оформлен в виде строки, которая будет скомпилирована позже.
    type — тип строки. По умолчанию все строки считаются текстовыми. Типы могу быть:

    • text — данные будут выведены с декодированием всех html тегов (html-encode)
    • raw — данные будут выведены «как есть» без изменений
    • ntext — все переносы строки будут заменены на соответствующие html-теги
    • html — данные будут выведены в виде html-кода
    • date, time, datetime — данные будут оформатированны в виде даты/времени соотвественно. Формат по умолчанию для даты ‘Y/m/d’, для времени ‘h:i:s A’, для datetime — ‘Y/m/d h:i:s A’. Если значение value — строка, она автоматически преобразуется в timestamp с помощью метода strtotime. Если значение value — число, то оно считается значением timestamp
    • boolean — данные будут выведены в виде логического значения ‘No’ / ‘Yes’
    • number — значение value преобразуется с помощью функции number_format и имеет смысл только если есть возможность передать значение $numberFormat. О таковой возможности мне пока ничего не известно. По умолчанию число делиться на блоки по 3 символа, разделенные запятой
    • email — значение value оборачивается тегом mailto
    • image — данные оборачиваются тегом img, где value устанавливается как значение src
    • url — данные оборачиваются тегом a, где value устанавливается как значение href
    • size — переданное значение интерпретируется как число в байтах, которое преобразуется в килобайты, мегабайты, гигобайты и теробайты соотвественно. Например получив значение value=10000023 в ячейки таблицы с таким типов будет выведено 9.54 МБ
  • Чтобы вывести связанные данные в CGridView, нужно в качестве значения value в виде строки передать метод, возвращающий связанные данные
    array(
      'name'   => 'region',
      'filter' => Region::getAll(),
      'value'  => 'Region::getNameByID($data->region)',
    ),
    

    Обратите внимание, в фильтре метод вызывается сразу, а в value записан в виде строки и будет вызван только в процессе построения таблицы методами класса CGridView. В моем случаи метод getNameByID класса Region возвращает название региона по первичному ключу.
    Если вы уверены, что объект, переданный в dataProvider будет иметь связанные таблицы (как это сделать смотрите во второй части, посвященной CGridView), то можно использовать такую запись

    array(
      'name'   => 'region',
      'filter' => Region::getAll(),
      'value'  => '$data->region->title',
    ),
    

    В моем примере «region» — это имя связи модели Country, которая используется при построении CActiveDataProvider с помощью with().

Изменяем пейджинацию в CGridView

  • Как вывести пейджинацию CGridView в отдельном диве. Для этого достаточно указать шаблон вывода template
    <?php $this->widget('zii.widgets.grid.CGridView', array(
        'id'=>'country-grid',
        'dataProvider'=>$model->search(),
        'filter'=>$model,
        'template' => '<div>{pager}</div>{summary}{items}<div>{pager}</div>',
        'columns'=>array(
            'id',
            'name',
            'region',
            array(
                'class'=>'CButtonColumn',
            ),
        ),
    )); ?>
    

    В шаблоне можно использовать любой html-код.

  • Как изменить стили пейджинации в CGridView
  • Для этого нужно настроить аттрибут pager

    <?php $this->widget('zii.widgets.grid.CGridView', array(
        'id'=>'country-grid',
        'dataProvider'=>$model->search(),
        'filter'=>$model,
        'pager'=>array(
            'header'         => '',
            'firstPageLabel' => '&lt;&lt;',
            'prevPageLabel'  => '<img src="images/pagination/left.png">',
            'nextPageLabel'  => '<img src="images/pagination/right.png">',
            'lastPageLabel'  => '&gt;&gt;',
        ),
        'columns'=>array(
            'id',
            'name',
            'region',
            array(
                'class'=>'CButtonColumn',
            ),
        ),
    )); ?>
    

Вот такая подробная инструкция у меня получилась. Надеюсь кому-нибудь да пригодиться. Если у вас возникли вопросы — пишите в комментариях, помогу чем смогу.
В следующей статье поговорим об источниках дынных для CGridView. Как добавить условия, настроить и сбросить фильтры.


Метки:

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

3 комментария »

    Жека

    Спасибо! Ващпе Помогло!


    Oleg

    Спасибо, пожалуй одно из лучших описаний этого сложного виджета.


    Gargun

    Большое спасибо, достался легаси код и там как раз этот виджет. Очень помогло


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









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