Создание и сопровождение сайтов

Блог. Yii. Подсказки по yii. Глава девятая.

Поиск

Подсказки по Yii. Глава восьмая.

  1. datePicker в CGridView.

    Дано: Таблица в БД c одним из полем 'date_created' с типом date/datetime и отображение данных в CGridView.

    Задача: в CGridView сделать фильтр по такому полю при помощи datePicker.

    Решение:

    На помощь придёт yii CJuiDatePicker.

    "Прицепим" его к 'date_created' в представлении:

    1. 'filter'=>$this->widget('zii.widgets.jui.CJuiDatePicker'array(  
    2.         'model'=>$model,   
    3.         'attribute'=>'date_created',  
    4.         'language'=>'ru',  
    5.         'options'=>array(  
    6.                 'showAnim'=>'fold',  
    7.                 'dateFormat'=>'yy-mm-dd',  
    8.                 'changeMonth' => 'true',  
    9.                 'changeYear'=>'true',  
    10.                 'showButtonPanel' => 'true',  
    11.         ),  
    12. ),true),  

    И чтобы после ajax обновления таблицы datePicker был доступен пропишем его инициализацию в afterAjaxUpdate. (привязываем datePicker к id элемента, в моём случае это 'News_date_created')

    Ajax обновление таблицы может быть при удалении записи, поиске в таблице.

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

    После всех вставок код должно получиться что-то около:

    1. <?php $this->widget('zii.widgets.grid.CGridView'array(  
    2.     'dataProvider'=>$model->search(),  
    3.     'filter'=>$model,  
    4.     'afterAjaxUpdate'=>"function() { 
    5.         jQuery('#News_date_created').datepicker(jQuery.extend(jQuery.datepicker.regional['ru'],{'showAnim':'fold','dateFormat':'yy-mm-dd','changeMonth':'true','showButtonPanel':'true','changeYear':'true'})); 
    6.     }",  
    7.     'columns'=>array(  
    8.         array(  
    9.             'name'=>'title',  
    10.             'type'=>'raw',  
    11.             'value'=>'CHtml::link(CHtml::encode($data->title), $data->url)'  
    12.         ),  
    13.         array(  
    14.             'name'=>'dateCreated',  
    15.             'type'=>'raw',  
    16.             'filter'=>false,  
    17.             'filter'=>$this->widget('zii.widgets.jui.CJuiDatePicker'array(  
    18.                                 'model'=>$model,   
    19.                                 'attribute'=>'date_created',  
    20.                                 'language'=>'ru',  
    21.                                 'options'=>array(  
    22.                                         'showAnim'=>'fold',  
    23.                                         'dateFormat'=>'yy-mm-dd',  
    24.                                         'changeMonth' => 'true',  
    25.                                         'changeYear'=>'true',  
    26.                                         'showButtonPanel' => 'true',  
    27.                                 ),  
    28.             ),true),  
    29.             'htmlOptions' => array('style' => 'width:130px;'),  
    30.         ),  
    31.         array(  
    32.             'class'=>'CButtonColumn',  
    33.             'deleteConfirmation' =>'Are you sure you want to delete this news?',  
    34.             'viewButtonUrl' => '$data->url',  
    35.         ),  
    36.     ),  
    37. )); ?>  

    Для того, чтобы работал фильтр по этому полю, открываем модель и в метод search добавим:

    1. if ($this->date_created)  
    2.     $criteria->compare('date_created'$this->date_created, true);  

    Получится как-то так:

    1. public function search() {  
    2.     $criteria = new CDbCriteria;  
    3.     ...  
    4.     if ($this->date_created)  
    5.         $criteria->compare('date_created'$this->date_created, true);  
    6.     ...  
    7. }  

    Изображения того, что получится в итоге:

    Кликнули по полю "Дата создания".

    CJuiDatePicker в CGridView 

    Выбрали дату. Результат после фильтрации.

    CJuiDatePicker в CGridView 

    CJuiDatePicker в CGridView 

     

  2. Вывод двух CGridView для разных таблиц.

    Иногда бывает необходимо отобразить на одной странице в двух CGridView данные из двух моделей.

    В контроллере напишем следующее:

    1. public function actionAdmin() {  
    2.     Yii::import('application.modules.apartmentCity.models.ApartmentCity');  
    3.     $modelA = new $this->modelName('search');   
    4.     $modelB = new ApartmentCity('search');  
    5.       
    6.     $this->render('admin'array('modelA' => $modelA'modelB' => $modelB));  
    7. }  

    Yii::import('application.modules.apartmentCity.models.ApartmentCity'); можно не писать, если у вас уже нужная модель импортируется в файле config/main.php

    Представление 'admin' принимает следующий вид:

    1. <?php $this->widget('zii.widgets.grid.CGridView'array(  
    2.     'dataProvider'=>$modelA->search(),  
    3.     'columns'=>array(  
    4.         array(  
    5.             'name'=>'title',  
    6.             'type'=>'raw',  
    7.             'value'=>'CHtml::link(CHtml::encode($data->title), $data->url)'  
    8.         ),  
    9.         array(  
    10.             'name'=>'dateCreated',  
    11.             'type'=>'raw',  
    12.             'filter'=>false,  
    13.             'htmlOptions' => array('style' => 'width:130px;'),  
    14.         ),  
    15.         array(  
    16.             'class'=>'CButtonColumn',  
    17.             'deleteConfirmation' => 'Are you sure you want to delete this news?',  
    18.             'viewButtonUrl' => '$data->url',  
    19.         ),  
    20.     ),  
    21. )); ?>  
    22.   
    23. <?php $this->widget('zii.widgets.grid.CGridView'array(  
    24.     'dataProvider'=>$modelB->search(),  
    25.     'columns'=>array(  
    26.         array(  
    27.             'name' => 'name',  
    28.             'header' => 'Название',  
    29.         ),  
    30.         array(  
    31.             'class'=>'CButtonColumn',  
    32.             'template'=>'{update} {delete}',  
    33.             'buttons'=>array(  
    34.                 'delete'=>array(  
    35.                     'label'=>'Delete',  
    36.                     'url'=>'Yii::app()->createUrl("apartmentCity/delete", array("id"=>$data->id))',  
    37.                 ),  
    38.                 'update'=>array(  
    39.                     'label'=>'Update',  
    40.                     'url'=>'Yii::app()->createUrl("apartmentCity/update", array("id"=>$data->id))',  
    41.                 ),  
    42.             ),  
    43.         ),  
    44.     ),  
    45. )); ?>  

    По-умолчанию, ссылки на редактирование/удаление будут вести на тот контроллер, из которого вы вызываете метод actionAdmin, код которого приведён был выше.

    Поэтому для второй таблицы мы прописываем ссылки на редактирование и удаление в другой контроллер.

    new News('search') и new ApartmentCity('search') означают, что мы вызываем метод search из соответствующих моделей для получения данных.

    Пример метода search модели News:

     

    1. public function search() {  
    2.     return new CActiveDataProvider($thisarray(  
    3.         'sort' => array(  
    4.             'defaultOrder' => 'date_created DESC',  
    5.         ),  
    6.         'pagination' => array(  
    7.             'pageSize' => param('adminPaginationPageSize', 20),  
    8.         ),  
    9.     ));  
    10. }  

     

    Что получится:

    CGridView 

     

  3. Действие после удаления записи в CGridView.

    Дано: таблица, вывод записей которой, в привычном нам CGridView.

    Задача: не давать пользователю удалять последнюю запись и выводить соответствующие сообщение.

    Решение:

    В нашу "таблицу" добавим:

     

    1. 'afterDelete'=>'function(link, success, data){ if (data == 0) {alert("Удалить последний тип нельзя по причине необходимости данного поля в каждом объявлении."); } }',  

     

    Получится так:

     

    1. ....  
    2. array(  
    3.     'class'=>'CButtonColumn',  
    4.     'deleteConfirmation' => 'Вы точно хотите удалить выбранный элемент?',  
    5.     'afterDelete'=>'function(link, success, data){ if (data == 0) {alert("Удалить последний элемент нельзя!"); } }'  
    6. )  
    7. ...  

     

    В метод beforeDelete модели:

    1. public function beforeDelete(){  
    2.     if($this->model()->count() <= 1){  
    3.         echo 0;  
    4.         return false;  
    5.     }  
    6.     ....  
    7. }  

    Теперь когда пользователь захочет удалить последнюю запись у него ничего не получится и он увидит сообщение "Удалить последний элемент нельзя!"

     

Обсудить статью на форуме