- Basics
- Localization
- Theming
- Options
- Adjusting the appearance
- Holidays
- Inside an AJAX updated area
- Links
We all love the convenient gadget, namely jQuery UI Datepicker as an input element for date. Yii supports it as CJuiDatePicker. Let's see how to use it.
Basics ¶
Imagine we have a text field for date in our form.
<div class="row">
<?php echo $form->labelEx($model,'date_from'); ?>
<?php
echo $form->textField($model, 'date_from', array(
'size' => 10,
'maxlength' => 10,
));
?>
<?php echo $form->error($model,'date_from'); ?>
</div>
As you see, we are using a CActiveForm here. And now replace the text field with a CJuiDatePicker.
<div class="row">
<?php echo $form->labelEx($model,'date_from'); ?>
<?php
$this->widget('zii.widgets.jui.CJuiDatePicker', array(
'model' => $model,
'attribute' => 'date_from',
'htmlOptions' => array(
'size' => '10', // textField size
'maxlength' => '10', // textField maxlength
),
));
?>
<?php echo $form->error($model,'date_from'); ?>
</div>
Basically this is all that you have to do.
- You don't need to load the javescript files (i.e. jQuery and jQuery UI) and CSS files by yourself.
- You don't need to write a text field by yourself.
- You don't need to write a script to convert the text field into Datepicker by yourself.
CJuiDatePicker will do all the tasks for you. (Well, things could be a little complicated in some situations. We will discuss it later.)
In the example above, we are using CJuiDatePicker like a CActiveForm::textField, setting $model
to model and 'date_from' attribute of $model
to attribute. By this settings, CJuiDatePicker will use the same logic as CActiveForm::textField to name the input field and connect the value to the attribute of the model.
If you don't use CActiveForm, you may use name and value to specify the name of the input field and the value of it. It correspond to the usage of CHtml::textField.
$this->widget('zii.widgets.jui.CJuiDatePicker', array(
'name' => 'date_from',
'value' => $fromDateValue,
'htmlOptions' => array(
'size' => '10', // textField size
'maxlength' => '10', // textField maxlength
),
));
Note: You have to use either model-attribute pair or name-value pair. They are mutually exclusive. Do not mix them up.
Localization ¶
Now, let's localize the Datepicker.
$this->widget('zii.widgets.jui.CJuiDatePicker', array(
'model' => $model,
'attribute' => 'date_from',
'language' => 'ja',
// 'i18nScriptFile' => 'jquery.ui.datepicker-ja.js',
'htmlOptions' => array(
'size' => '10',
'maxlength' => '10',
),
));
We have to specify 'language'. Generally you don't to need to specify 'i18nScriptFile' if you are using the latest version of jQuery UI.
Theming ¶
And we are applying a jQuery UI theme.
$this->widget('zii.widgets.jui.CJuiDatePicker', array(
'model' => $model,
'attribute' => 'date_from',
'language' => 'ja',
'themeUrl' => Yii::app()->baseUrl . '/css/jui',
'theme' => 'softark',
'cssFile' => 'jquery-ui-1.9.2.custom.css',
'htmlOptions' => array(
'size' => '10',
'maxlength' => '10',
),
));
We are in the assumption that '/css/jui' holds a theme named 'softark'. You have to create a jQuery UI theme using ThemeRoller. It's not quite easy to create a good looking theme, though.
Options ¶
We can set various options.
$this->widget('zii.widgets.jui.CJuiDatePicker', array(
'model' => $model,
'attribute' => 'date_from',
'language' => 'ja',
'themeUrl' => Yii::app()->baseUrl . '/css/jui',
'theme' => 'softark',
'cssFile' => 'jquery-ui-1.9.2.custom.css',
'options' => array(
'showOn' => 'both', // also opens with a button
'dateFormat' => 'yy-mm-dd', // format of "2012-12-25"
'showOtherMonths' => true, // show dates in other months
'selectOtherMonths' => true, // can seelect dates in other months
'changeYear' => true, // can change year
'changeMonth' => true, // can change month
'yearRange' => '2000:2099', // range of year
'minDate' => '2000-01-01', // minimum date
'maxDate' => '2099-12-31', // maximum date
'showButtonPanel' => true, // show button panel
),
'htmlOptions' => array(
'size' => '10',
'maxlength' => '10',
),
));
The options are all up to your choice. Please see DatePicker DEMO and API for detailed information.
Note: My experience tells that the Datepicker works more stable without 'showAnim' option. Especially when you want to use 2 or more instances on the same screen, you would be better not set this option.
Adjusting the appearance ¶
But, we don't like the appearance of it at all. The header is divided into 2 rows because the dropdowns of year and month are a little too large. And we would like the font to be a little smaller.
Hmm, we have to tweak the CSS that ThemeRoller has created.
[css]
/* Component containers
----------------------------------*/
/* --- delete : use the default font of my site css ---
.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; }
*/
...
/* --- add : font should be a little smaller --- */
#ui-datepicker-div { font-size: 80%;}
button.ui-datepicker-trigger { font-size: 80%; line-height: 1.4em; }
...
/* --- layout of year and month ... have to modify a bit ---
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year { width: 49%;}
*/
.ui-datepicker select.ui-datepicker-month { with: 35%; }
.ui-datepicker select.ui-datepicker-year { width: 40%; }
/* --- for fxxking stupid browsers --- */
* html .ui-datepicker .ui-datepicker-title select.ui-datepicker-month { width: 30%; }
* html .ui-datepicker .ui-datepicker-title select.ui-datepicker-year { width: 35%;}
/* --- highliting --- */
.ui-datepicker .ui-state-active, .ui-datepicker .ui-state-active.ui-state-highlight { border-color: #0b5110;}
.ui-datepicker .ui-state-highlight { border-color: #448844;}
So, the boring part of the task has been done. Of course you have to do your own job here. There's no standard way of doing it.
Holidays ¶
I'm going to use GCalHolidays.js. It will enable you to color Sundays, Saturdays and Japanese Holidays with different colors.
Yes, I'm sorry, this part is Japanese specific. But you may find your locale specific counterpart somewhere on the web.
Yii::app()->cientScript->registerScriptFile(
Yii::app()->baseUrl . '/js/GCalHolidays.js',
CClientScript::POS_END
);
Inside an AJAX updated area ¶
In today's web applications, it's a common practice to update/replace the content of a specific area using AJAX. And if you want to use Datepicker inside such an area (e.g. in a form that will be ajax updated), you will need some extra work.
jQuery UI Datepicker modifies the existing HTML code to transform the ordinary text field into a Datepicker. So when the HTML code has been updated by an AJAX, the Datepicker will return to an plain text field.
You may encounter an issue like this: the Datepicker works just fine when the page has been loaded for the first time, but after you have done something in the page the Datepicker won't work anymore. Most probably the cause of the issue is that the HTML code has been updated by AJAX and the Datepicker has been reset to the plain text field.
To solve this kind of issue, we have to convert the plain text field to a Datepicker again after every ajax updating.
There are 2 ways to do that:
- Include a script to re-create the Datepicker in the AJAX response.
- Manually re-create the Datepicker after AJAX updating.
I don't have much to say about the 1st approach, because I've never used it. Probably you have to set the 4th parameter of Controller::renderPartial() to true
to include the script in AJAX response. But, at the same time, you have to tweak CClientScript::scriptMap to avoid the duplication of jQuery and jQuery UI. ... I'm not sure. Personally I feel this approach is tricky, hacky and unstable. I don't like it.
I prefer the 2nd approach. I will not include any javascript in the response from the server. It goes like this:
[javascript]
$('#submit-button').click(function() {
// post the form content by ajax
$.ajax({
'type' : 'POST',
'url' : 'foo-update',
'dataType' : 'json',
'data' : $('#foo-form').serialize(),
'success' : function(data){
// update the form
$('#foo-form').html(data.contents);
// re-create Datepicker
$('#foo-form .d-picker').datepicker();
}
});
});
It's just a rough skech, but the point is that we call datepicker() function of jQuery UI after the AJAX updating to re-create the Datepicker.
Yes, I'm doing a pure jQuery programming here. Although usually the jQuery support of Yii is quite convenient and useful, the things will be much easier with plain jQuery programming when the things got a little complicated.
But I will continue to use CJuiDatePicker for the initial loading of the Datepicker, because it's much more easy. And the following is a sample code to create a Datepicker when it has to be updated by AJAX.
$this->widget('zii.widgets.jui.CJuiDatePicker', array(
...
'defaultOptions' => array(
'showOn' => 'both',
...
... more options here ...
...
),
'htmlOptions' => array(
...
'class' => 'd-picker',
),
));
We set 'class' in 'htmlOptions' because we want to select this element using jQuery. Of course you may use 'id' instead.
And we use 'defaultOptions' instead of 'options'. By doing this, we will be able to call datepicker() function of jQuery UI without explicitly specifying the options.
Links ¶
- Using CJuiDatePicker for CGridView filter
- Japanese Translation: Yii で jQuery UI Datepicker を使う
- Persian Translation: Persian version
multiple date select
is it possible to select multiple date select ?
re: multiple date select
I'm not sure what you want exactly, but you can use multiple datepickers for multiple date fields on a single page, while you can not select multiple dates at once in a single datepicker.
hi
Hi, this is what i am expecting.. http://multidatespickr.sourceforge.net/
to choose multiple at once...
re: multiple date select
I see.
CJuiDatePicker is a wrapper over jQuery UI Datepicker. I think it doesn't support the MultiDatesPicker plug-in.
hi
it would be a nice enhancement if you can modify it to support multi select. tnx
CGridView cell?
So, if I have a CGridView with a CHtml::textField that I'm using to capture a date, how do I turn CDataColumn into a datepicker?
@Lynette
type=raw and value=html
and then either:
disable ajax (ajaxUpdate=>'false') in your CGridView
or
write a custom datepicker reinitialisation script to turn your field into datepicker after each ajax update.
Excellent
Excellent work, Softark.
Thank you
Nice work. So clear with examples.
Holidays calendar
How to implement the calendar with holidays?
Holidays calendar
How to implement the calendar with holidays?
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.