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