Tips for Yii. Сhapter 6.
-
datePicker в CGridView.
What have we got?
A table in the database with one of the fields 'date_created' with date/datetime type and displaying of the data in CGridView.
What is our task?
It is to create a filter in CGridView for this field with the help of datePicker.
What is a solution?
It is Yii CJuiDatePicker that will help us. (for example our Open Real Estate CMS 1.3.3)
Add it to 'date_created' in the viewing:
- 'filter'=>$this->widget('zii.widgets.jui.CJuiDatePicker', array(
- 'model'=>$model,
- 'attribute'=>'date_created',
- 'language'=>'en',
- 'options'=>array(
- 'showAnim'=>'fold',
- 'dateFormat'=>'yy-mm-dd',
- 'changeMonth' => 'true',
- 'changeYear'=>'true',
- 'showButtonPanel' => 'true',
- ),
- ),true),
And to make datePicker available after an ajax update of the table, write its initialization in afterAjaxUpdate (we add datePicker to id of the element; in our case, it is 'News_date_created').
An ajax update of the table can happen by deleting of the record, by searching in the table.
- 'afterAjaxUpdate' => 'function(){jQuery("#News_date_created").datepicker(jQuery.extend(jQuery.datepicker.regional["en"],{"showAnim":"fold","dateFormat":"yy-mm-dd","changeMonth":"true","showButtonPanel":"true","changeYear":"true"})); $("a[rel=\'tooltip\']").tooltip(); $("div.tooltip-arrow").remove(); $("div.tooltip-inner").remove();}',
Having made all additions to the code, we will get the following:
- <?php $this->widget('CustomGridView', array(
- 'id'=>'news-grid',
- 'dataProvider'=>$model->search(),
- 'filter'=>$model,
- 'afterAjaxUpdate' => 'function(){jQuery("#News_date_created").datepicker(jQuery.extend(jQuery.datepicker.regional["en"],{"showAnim":"fold","dateFormat":"yy-mm-dd","changeMonth":"true","showButtonPanel":"true","changeYear":"true"})); $("a[rel=\'tooltip\']").tooltip(); $("div.tooltip-arrow").remove(); $("div.tooltip-inner").remove();}',
- 'columns'=>array(
- array(
- 'class'=>'CCheckBoxColumn',
- 'id'=>'itemsSelected',
- 'selectableRows' => '2',
- 'htmlOptions' => array(
- 'class'=>'center',
- ),
- ),
- array(
- 'header' => tc('Title'),
- 'name'=>'title_'.Yii::app()->language,
- 'type'=>'raw',
- 'value'=>'CHtml::link(CHtml::encode($data->getStrByLang("title")), $data->url)'
- ),
- array(
- 'name'=>'dateCreated',
- 'type'=>'raw',
- 'filter'=>$this->widget('zii.widgets.jui.CJuiDatePicker', array(
- 'model'=>$model,
- 'attribute'=>'date_created',
- 'language'=>'en',
- 'options'=>array(
- 'showAnim'=>'fold',
- 'dateFormat'=>'yy-mm-dd',
- 'changeMonth' => 'true',
- 'changeYear'=>'true',
- 'showButtonPanel' => 'true',
- ),
- ),true),
- 'htmlOptions' => array('style' => 'width:130px;'),
- ),
- array(
-
- 'class'=>'bootstrap.widgets.BootButtonColumn',
- 'deleteConfirmation' => tt('Are you sure you want to delete this news?', 'news'),
- 'viewButtonUrl' => '$data->url',
- ),
- ),
- ));
To make the filter work for this field, we shall open the model and add to the ‘search’ method the following:
- if ($this->date_created)
- $criteria->compare('date_created', $this->date_created, true);
So we will get:
- public function search() {
- $criteria = new CDbCriteria;
- ...
- if ($this->date_created)
- $criteria->compare('date_created', $this->date_created, true);
- ...
- }
and:
- public function rules() {
- return array(
- ...
- array($this->getI18nFieldSafe().', date_created', 'safe'),
- ...
- );
- }
Here is the screenshot of what we have, as a result.We click the "Creation date" field:
-
Actions before validation and after it.
Sometimes it is necessary to do actions before validation.
For example, to set a scenario name for validation depending on the value of a variable.
- public function onBeforeValidate($event) {
- $scenarioArray = array(
- 1 => 'scanario1',
- 2 => 'scanario2',
- 3 => 'scanario3',
- 4 => 'scanario4',
- 5 => 'scanario5',
- );
- $this->scenario = $scenarioArray[$this->fieldFromDB1];
-
- if (!$this->field2 || !$this->field3)
- $this->addError('field2', 'Fill in field2 and field3');
- else
- $this->fieldFromDB2 = $this->field2.$this->field3;
- }
, here field2 and field3 are, the fields which the database does not have, but they are announced in the model.
And after validation we can code:
- public function onAfterValidate($event) {
-
- }
The model has also beforeValidate().
But we have examined onBeforeValidate() that considers an event as an argument.
-
How to add a progress indicator for ajax requests.
While performing an ajax request, it is useful to show to the user "that something is happening" and his/her click on the link/button has not been ineffective.
We add div onto the page:
- <div id="loading" style="display:none;">Loading...</div>
Styles:
- #loading{
- position: fixed;
- top: 40px;
- leftleft: 0;
- z-index: 5000;
- background-color: #3C69AC;
- font-size: 100%;
- color: #FFFFFF;
- padding: 5px;
- }
Showing and hiding of the div:
- Yii::app()->clientScript->registerScript('loading', '
- $("#loading").bind("ajaxSend", function(){
- $(this).show();
- }).bind("ajaxComplete", function(){
- $(this).hide();
- });
- ', CClientScript::POS_READY);
-
Paths to folders..
I guess that many developers have to work with downloaded photos and to specify an absolute path to a folder that will contain all the downloaded files.
Dirname(__FILE__);/dirname(__FILE__) . '/../'; etc. can help us.
But Yii has a getPathOfAlias method, using of it is a right and beautiful solution.
For example, for loading in the upload folder:
we use:
- Yii::getPathOfAlias('webroot.uploads');
For loading in the uploads/qrcodes folder:
we use:
- Yii::getPathOfAlias('webroot.uploads.qrcodes');
For loading in the protected/modules/cropimage folder we use:
- Yii::getPathOfAlias('application.modules.cropimage');
It is not possible to use
- Yii::getPathOfAlias('webroot.protected.modules.cropimage');
, because a ‘protected’ folder is closed for access via htaccess.