Дорабатываем CGridView под свои задачи



Спонсор поста: EximusCommerce — платформа для создания интернет-магазинов на Yii framework.

Продолжаем знакомиться с виджетами в Yii framework. Сегодня рассмотрим CGridView. CGridView — это стандартный виджет, располагается в /framework/zii/widgets/grid/CGridView.php. Виджет служит, для отображения данных в табличной форме. Поддерживается сортировка по атрибутам, постраничная навигация и поиск. Сортировка и постраничная навигация могут осуществляться, как с помощью AJAX’а, так и без него. Если, у пользователя отключен javascript, то сортировка и переключение страниц будет происходить обычным образом, без AJAX.

Минимальный код необходимы для вызова виджета:

$dataProvider=new CActiveDataProvider('Model');

$this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider'=>$dataProvider,
));

Под катом, мы рассмотрим следующие пункты:

1. Добавление календаря в фильтры (jquery datepicker).
2. Выпадающие списки в фильтрах.
3. Изменение дизайна.

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

Создадим таблицу tbl_news с такой структурой:
Структура таблицы tbl_news

name — название новости.
content — содержимое новости.
status — статус новости. Новости с 0 статусом не показываются.
created_at — дата создания новости.

SQL:

CREATE TABLE `tbl_news` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `content` text NOT NULL,
  `status` tinyint(1) NOT NULL DEFAULT '1',
  `created_at` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;

--
-- Дамп данных таблицы `tbl_news`
--

INSERT INTO `tbl_news` (`id`, `name`, `content`, `status`, `created_at`) VALUES
(1, 'name1', 'content1', 1, '2013-03-23'),
(2, 'name2', 'content2', 1, '2013-04-01'),
(3, 'name3', 'content3', 0, '2013-04-03'),
(4, 'name4', 'content4', 1, '2013-04-01'),
(5, 'name5', 'content5', 0, '2013-04-05');

После того, как создали таблицу tbl_news в базе данных, генерируем модель News, с помощью gii. Если все прошло правильно, то новая модель доступна в models/News.php. Изменим немного метод search. Меняем:

return new CActiveDataProvider($this, array(
			'criteria'=>$criteria,
		));

На следующий код:

return new CActiveDataProvider($this, array(
             'criteria'=>$criteria,
                 'pagination'=>array(
                     'pageSize'=>10,
                  ),
                  sort'=>array(
                      'defaultOrder'=>array(
                       'created_at'=>"DESC"
                  ))
        ));

В приведенном выше коде, задается, что на странице будет выводится 10 записей и сортировка будет по полю created_at.

Создадим контроллер NewsController.php в protected/controllers (CRUD-методы специально не включены в контроллер).

Содержимое NewsController:

<?php
class NewsController extends Controller
{
    /**
     * Главная страница новостей
     */
    public function actionIndex()
    {
        $model = new News('search');

        $model->unsetAttributes();

        if(isset($_GET['News'])) {
            $model->attributes = $_GET['News'];
        }

        $this->render('index', array('model'=>$model));
    }
}
?>

Создаем директорию news в protected/views и представление index.php в views/news. В файле index.php будут выводится все новости в виджете CGRidView.

Содержимое index.php:

<?php
$this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider' => $model->search(),
    'filter' => $model,
    'columns' => array(
        array(
            'name' => 'name',
            'type' => 'raw',
            'value' => '$data->name',
        ),
        array(
            'name' => 'status',
            'type' => 'raw',
            'value' => '$data->status',
        ),
        array(
            'name' => 'created_at',
            'type' => 'raw',
            'value' => '$data->created_at',
        ),
        array(
            'class' => 'CButtonColumn',
            'template' => '{update}&nbsp;{delete}',
            'buttons' => array(
                'update' => array(
                    //здесь должен быть url для редактирования записи
                    'url' => 'Yii::app()->createUrl("/edit/$data->id")',
                ),
                'delete' => array(
                    //здесь должен быть url для удаления записи
                    'url' => 'Yii::app()->createUrl("/delete/$data->id")',
                ),
            ),
        ),
    ),
));

Открыв страницу с новостями, вы увидите 5-ть записей в таблице, со стандартным оформлением. Можно производить сортировку по атрибутам, искать значения в фильтрах, но для того, чтобы найти записи за определенную дату нужно вводить значение вручную. Это не слишком удобно. Исправим это, добавив календарь для поля created_at.

Добавление календаря в CGridView

Заменяем:

array(
      'name' => 'created_at',
      'type' => 'raw',
      'value' => '$data->created_at',
     ),

На следующий код:

array(
      'name' => 'created_at',
      'type' => 'raw',
      'value' => '$data->created_at',
      'filter'=>$this->widget('zii.widgets.jui.CJuiDatePicker', array(
           'model'=>$model,
           'attribute'=>'created_at',
           'language'=>'ru',
           'options'=>array(
           'showAnim'=>'fold',
           'dateFormat'=>'yy-mm-dd',
           'changeMonth' => 'true',
           'changeYear'=>'true',
                ),
       ),true),
    ),

Теперь, при клике в поле фильтра для created_at, будет появляться календарь с возможностью выбора даты. Чтобы, datepicker работал и после выполнения ajax-запросов, нужно добавить следующий код после columns:

'afterAjaxUpdate'=>"function() {
        jQuery('#News_created_at').datepicker(jQuery.extend(jQuery.datepicker.regional['ru'],{
                                            'showAnim':'fold',
                                            'dateFormat':'yy-mm-dd',
                                            'changeMonth':'true',
                                            'changeYear':'true'}));
    }",

Добавление выпадающего списка в CGridView

Изменим код колонки status’а на следующий:

array(
      'name' => 'status',
      'type' => 'raw',
      'value' => '$data->getStatus($data->status)',
      'filter' => array(''=>'Все', 1 => 'Показывается', 0=> 'Не показывается'), ),

Кроме измененного фильтра, был добавлен метод getStatus() для возвращения значения статуса. Данный метод нужно добавить в модель News.

public function getStatus($status)
{
    $data = array(0=>"Не показывается", 1=>"Показывается");
    return $data[$status];
}

Добавление своих стилей в CGridView

Если посмотреть на страницу новостей после изменений, то можно увидеть, что текстовое поле под колонкой «Статус» заменено на выпадающий список. Вместо 1 и 0, выводятся текстовые значения статуса. Осталось изменить кнопки для редактирования, удаления записей и стили. Добавьте следующие стили в файл main.css (входит в комплект с демо блогом):

.table-striped td {
    border-top: 1px solid #DDDDDD;
    line-height: 20px;
    padding: 8px;
    text-align: left;
    vertical-align: top;
}
.grid-view table.table-striped th {
    padding-bottom: 8px;
}
.table-striped {
    width: 100%;
}
.table-striped th {
    background: #ffffff;
    text-align: center;
}
.grid-view table.table-striped tr.selected {
    background-color: #BCE774 !important;
}
.grid-view table.table-striped {
    border-collapse: collapse;
}

В views/news/index.php после ‘filter’ => $model добавляем ‘itemsCssClass’=>’table-striped’. Этим мы указали значение для атрибута class, для нашей таблицы. Изменим кнопки, для удаления и редактирования.

Для редактирования будет такая картинка:

Для удаления, вот такая:

Обе картинки находятся в директории images. Предварительно ее нужно создать, если ее нет.

В ‘update’, перед url, добавляем: ‘imageUrl’=>’/images/edit.png’, а в ‘delete’ ‘imageUrl’=>’/images/delete.png’,

Должно получиться вот так:

array(
            'class' => 'CButtonColumn',
            'template' => '{update}&nbsp;{delete}',
            'buttons' => array(
                'update' => array(
                    //url до картинки
                    'imageUrl'=>'/images/edit.png',
                    //здесь должен быть url для редактирования записи
                    'url' => 'Yii::app()->createUrl("/edit/$data->id")',
                ),
                'delete' => array(
                    //url до картинки
                    'imageUrl'=>'/images/delete.png',
                    //здесь должен быть url для удаления записи
                    'url' => 'Yii::app()->createUrl("/delete/$data->id")',
                ),
            ),
        ),

Для того, чтобы все изменения вступили в силу, нужно очистить директорию assets. Кнопки задаются по шаблону, определенному в ‘template’ => ‘{update} {delete}’. В скобках можно задать шаблон для своей кнопки, а потом добавить ее в массив  buttons.

Полный листинг файла news/index.php:

<?php
$this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider' => $model->search(),
    'filter' => $model,
    'itemsCssClass'=>'table-striped',
    'columns' => array(
        array(
            'name' => 'name',
            'type' => 'raw',
            'value' => '$data->name',
        ),
        array(
            'name' => 'status',
            'type' => 'raw',
            'value' => '$data->getStatus($data->status)',
            'filter' => array(''=>'Все', 1 => 'Да', 0=> 'Нет'),
        ),
        array(
            'name' => 'created_at',
            'type' => 'raw',
            'value' => '$data->created_at',
            'filter'=>$this->widget('zii.widgets.jui.CJuiDatePicker', array(
                'model'=>$model,
                'attribute'=>'created_at',
                'language'=>'ru',
                'options'=>array(
                    'showAnim'=>'fold',
                    'dateFormat'=>'yy-mm-dd',
                    'changeMonth' => 'true',
                    'changeYear'=>'true',

                ),
            ),true),
        ),
        array(
            'class' => 'CButtonColumn',
            'template' => '{update}&nbsp;{delete}',
            'buttons' => array(
                'update' => array(
                    //url до картинки
                    'imageUrl'=>'/images/edit.png',
                    //здесь должен быть url для редактирования записи
                    'url' => 'Yii::app()->createUrl("/edit/$data->id")',
                ),
                'delete' => array(
                    //url до картинки
                    'imageUrl'=>'/images/delete.png',
                    //здесь должен быть url для удаления записи
                    'url' => 'Yii::app()->createUrl("/delete/$data->id")',
                ),
            ),
        ),
    ),
    'afterAjaxUpdate'=>"function() {
        jQuery('#News_created_at').datepicker(jQuery.extend(jQuery.datepicker.regional['ru'],{
                                            'showAnim':'fold',
                                            'dateFormat':'yy-mm-dd',
                                            'changeMonth':'true',
                                            'changeYear':'true'}));
    }",
));

В статье показаны лишь немногие методы доступные для CGridView. Подробное описание доступно на официальном сайте.

Архив с примером. Новости из примера, запускаются по адресу: http://yiiblog/news.



Теги:

Комментарии

  1. Подход с непосредственным вписыванием раз за разом десятков одних и тех же параметров в каждый грид не очень удобен. Можно вынести стили грида http://www.elisdn.ru/blog/36/yii-widgets-styling-approaches и кнопок
    http://www.elisdn.ru/blog/37/custom-cgridview-columns-in-yii в сторонние файлы и вернуться почти к тому же минимальному коду.

    Reply

  2. Вы проводите обучение по Yii?

    Reply

    Max Reply:


    Нет.

    Reply

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