Подсказки по Yii. Глава восьмая.
-
datePicker в CGridView.
Дано: Таблица в БД c одним из полем 'date_created' с типом date/datetime и отображение данных в CGridView.
Задача: в CGridView сделать фильтр по такому полю при помощи datePicker.
Решение:
На помощь придёт yii CJuiDatePicker.
"Прицепим" его к 'date_created' в представлении:
- 'filter'=>$this->widget('zii.widgets.jui.CJuiDatePicker', array(
- 'model'=>$model,
- 'attribute'=>'date_created',
- 'language'=>'ru',
- 'options'=>array(
- 'showAnim'=>'fold',
- 'dateFormat'=>'yy-mm-dd',
- 'changeMonth' => 'true',
- 'changeYear'=>'true',
- 'showButtonPanel' => 'true',
- ),
- ),true),
И чтобы после ajax обновления таблицы datePicker был доступен пропишем его инициализацию в afterAjaxUpdate. (привязываем datePicker к id элемента, в моём случае это 'News_date_created')
Ajax обновление таблицы может быть при удалении записи, поиске в таблице.
- 'afterAjaxUpdate'=>"function() {
- jQuery('#News_date_created').datepicker(jQuery.extend(jQuery.datepicker.regional['ru'],{'showAnim':'fold','dateFormat':'yy-mm-dd','changeMonth':'true','showButtonPanel':'true','changeYear':'true'}));
- }",
После всех вставок код должно получиться что-то около:
- <?php $this->widget('zii.widgets.grid.CGridView', array(
- 'dataProvider'=>$model->search(),
- 'filter'=>$model,
- 'afterAjaxUpdate'=>"function() {
- jQuery('#News_date_created').datepicker(jQuery.extend(jQuery.datepicker.regional['ru'],{'showAnim':'fold','dateFormat':'yy-mm-dd','changeMonth':'true','showButtonPanel':'true','changeYear':'true'}));
- }",
- 'columns'=>array(
- array(
- 'name'=>'title',
- 'type'=>'raw',
- 'value'=>'CHtml::link(CHtml::encode($data->title), $data->url)'
- ),
- array(
- 'name'=>'dateCreated',
- 'type'=>'raw',
- 'filter'=>false,
- 'filter'=>$this->widget('zii.widgets.jui.CJuiDatePicker', array(
- 'model'=>$model,
- 'attribute'=>'date_created',
- 'language'=>'ru',
- 'options'=>array(
- 'showAnim'=>'fold',
- 'dateFormat'=>'yy-mm-dd',
- 'changeMonth' => 'true',
- 'changeYear'=>'true',
- 'showButtonPanel' => 'true',
- ),
- ),true),
- 'htmlOptions' => array('style' => 'width:130px;'),
- ),
- array(
- 'class'=>'CButtonColumn',
- 'deleteConfirmation' =>'Are you sure you want to delete this news?',
- 'viewButtonUrl' => '$data->url',
- ),
- ),
- )); ?>
Для того, чтобы работал фильтр по этому полю, открываем модель и в метод search добавим:
- if ($this->date_created)
- $criteria->compare('date_created', $this->date_created, true);
Получится как-то так:
- public function search() {
- $criteria = new CDbCriteria;
- ...
- if ($this->date_created)
- $criteria->compare('date_created', $this->date_created, true);
- ...
- }
Изображения того, что получится в итоге:
Кликнули по полю "Дата создания".
Выбрали дату. Результат после фильтрации.
-
Вывод двух CGridView для разных таблиц.
Иногда бывает необходимо отобразить на одной странице в двух CGridView данные из двух моделей.
В контроллере напишем следующее:
- public function actionAdmin() {
- Yii::import('application.modules.apartmentCity.models.ApartmentCity');
- $modelA = new $this->modelName('search');
- $modelB = new ApartmentCity('search');
-
- $this->render('admin', array('modelA' => $modelA, 'modelB' => $modelB));
- }
Yii::import('application.modules.apartmentCity.models.ApartmentCity'); можно не писать, если у вас уже нужная модель импортируется в файле config/main.php
Представление 'admin' принимает следующий вид:
- <?php $this->widget('zii.widgets.grid.CGridView', array(
- 'dataProvider'=>$modelA->search(),
- 'columns'=>array(
- array(
- 'name'=>'title',
- 'type'=>'raw',
- 'value'=>'CHtml::link(CHtml::encode($data->title), $data->url)'
- ),
- array(
- 'name'=>'dateCreated',
- 'type'=>'raw',
- 'filter'=>false,
- 'htmlOptions' => array('style' => 'width:130px;'),
- ),
- array(
- 'class'=>'CButtonColumn',
- 'deleteConfirmation' => 'Are you sure you want to delete this news?',
- 'viewButtonUrl' => '$data->url',
- ),
- ),
- )); ?>
-
- <?php $this->widget('zii.widgets.grid.CGridView', array(
- 'dataProvider'=>$modelB->search(),
- 'columns'=>array(
- array(
- 'name' => 'name',
- 'header' => 'Название',
- ),
- array(
- 'class'=>'CButtonColumn',
- 'template'=>'{update} {delete}',
- 'buttons'=>array(
- 'delete'=>array(
- 'label'=>'Delete',
- 'url'=>'Yii::app()->createUrl("apartmentCity/delete", array("id"=>$data->id))',
- ),
- 'update'=>array(
- 'label'=>'Update',
- 'url'=>'Yii::app()->createUrl("apartmentCity/update", array("id"=>$data->id))',
- ),
- ),
- ),
- ),
- )); ?>
По-умолчанию, ссылки на редактирование/удаление будут вести на тот контроллер, из которого вы вызываете метод actionAdmin, код которого приведён был выше.
Поэтому для второй таблицы мы прописываем ссылки на редактирование и удаление в другой контроллер.
new News('search') и new ApartmentCity('search') означают, что мы вызываем метод search из соответствующих моделей для получения данных.
Пример метода search модели News:
- public function search() {
- return new CActiveDataProvider($this, array(
- 'sort' => array(
- 'defaultOrder' => 'date_created DESC',
- ),
- 'pagination' => array(
- 'pageSize' => param('adminPaginationPageSize', 20),
- ),
- ));
- }
Что получится:
-
Действие после удаления записи в CGridView.
Дано: таблица, вывод записей которой, в привычном нам CGridView.
Задача: не давать пользователю удалять последнюю запись и выводить соответствующие сообщение.
Решение:
В нашу "таблицу" добавим:
- 'afterDelete'=>'function(link, success, data){ if (data == 0) {alert("Удалить последний тип нельзя по причине необходимости данного поля в каждом объявлении."); } }',
Получится так:
- ....
- array(
- 'class'=>'CButtonColumn',
- 'deleteConfirmation' => 'Вы точно хотите удалить выбранный элемент?',
- 'afterDelete'=>'function(link, success, data){ if (data == 0) {alert("Удалить последний элемент нельзя!"); } }'
- )
- ...
В метод beforeDelete модели:
- public function beforeDelete(){
- if($this->model()->count() <= 1){
- echo 0;
- return false;
- }
- ....
- }
Теперь когда пользователь захочет удалить последнюю запись у него ничего не получится и он увидит сообщение "Удалить последний элемент нельзя!"