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

Продолжаем знакомиться с виджетами в 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 с такой структурой:



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. Подробное описание доступно на официальном сайте.

Пример: yiiblog.zip
Теги:
array, created, model, delete, status, table, value, striped, update, filter, CGridView, images, widgets, createUrl, index, будет, jQuery, datepicker, записи , удаления, здесь, редактирования, должен, imageUrl, dataProvider, class, новости, widget, нужно, changeMonth, template, function, changeYear, buttons, showAnim
Добавлено: 27 Февраля 2015 08:52:22 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...