Advanced Datepicker helper for CakePHP

This is a really old post. I’ve wrote a new one which you can find it here

I am using this part of code from long time ago, but it wasn’t in a separate helper. It was part from one not very good written Auth component/helper mash up which I already not using. I fact the default Date input of CakePHP Framework is ugly and not user friendly at all. The drop-downs are good because the format is clear and users cannot mess it, but if you thinking for the user convenience, then you should know that it’s 3 times easier just to type the date in a field or to pick it from a Calendar pop up than selecting from 3 drop-downs.

In that helper I am using JSCalendar. The benefits of it are:

  • Flexible Date and Time formats
  • Full Theme support
  • Translated in many languages
  • Fast and very easy to setup

For additional information: Full Demo and Calendar Documentation Pages.

What you should do in order to run it in you CakePHP project.

Update 04 Oct 2007 – From now on the Helper includes 2 options

  • Regular Po-pup Calendar – simple text field with link which will pop-up the calendar helper
  • Flat Calendar – It’s using hidden field to store date more convenient if you don’t want to allow your users to mess up with data input in that field

Update 11 Oct 2007 – The code is tested and working with CakePHP v1.2! Previous versions of the Framework throws an error.

1. Download a copy of the calendar and unzip it in your {cakeproject}/app/webroot/js directory. It’s possible to strip down the unnecessary files like examples, docs etc.
2. Create a file with name common.js with the following content:

var oldLink = null;
function setActiveStyleSheet(link, title) {
  var i, a, main;
  for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
    if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) {
      a.disabled = true;
      if(a.getAttribute("title") == title) a.disabled = false;
  if (oldLink) = 'normal';
  oldLink = link; = 'bold';
  return false;
// This function gets called when the end-user clicks on some date.
function selected(cal, date) {
  cal.sel.value = date; // just update the date in the input field.
  if (cal.dateClicked && ( == "sel1" || == "sel3"))
    // if we add this call we close the calendar on single-click.
    // just to exemplify both cases, we are using this only for the 1st
    // and the 3rd field, while 2nd and 4th will still require double-click.

// And this gets called when the end-user clicks on the _selected_ date,
// or clicks on the "Close" button.  It just hides the calendar without
// destroying it.
function closeHandler(cal) {
  cal.hide();                        // hide the calendar
//  cal.destroy();
  _dynarch_popupCalendar = null;

// This function shows the calendar under the element having the given id.
// It takes care of catching "mousedown" signals on document and hiding the
// calendar if the click was outside.
function showCalendar(id, format, showsTime, showsOtherMonths) {
  var el = document.getElementById(id);
  if (_dynarch_popupCalendar != null) {
    // we already have some calendar created
    _dynarch_popupCalendar.hide();                 // so we hide it first.
  } else {
    // first-time call, create the calendar.
    var cal = new Calendar(1, null, selected, closeHandler);
    // uncomment the following line to hide the week numbers
    // cal.weekNumbers = false;
    if (typeof showsTime == "string") {
      cal.showsTime = true;
      cal.time24 = (showsTime == "24");
    if (showsOtherMonths) {
      cal.showsOtherMonths = true;
    _dynarch_popupCalendar = cal;                  // remember it in the global var
    cal.setRange(1900, 2070);        // min/max year allowed.
  _dynarch_popupCalendar.setDateFormat(format);    // set the specified date format
  _dynarch_popupCalendar.parseDate(el.value);      // try to parse the text in field
  _dynarch_popupCalendar.sel = el;                 // inform it what input field we use

  // the reference element that we pass to showAtElement is the button that
  // triggers the calendar.  In this example we align the calendar bottom-right
  // to the button.
  _dynarch_popupCalendar.showAtElement(el.nextSibling, "Br");        // show the calendar

  return false;

var MINUTE = 60 * 1000;
var HOUR = 60 * MINUTE;
var DAY = 24 * HOUR;
var WEEK = 7 * DAY;

// If this handler returns true then the "date" given as
// parameter will be disabled.  In this example we enable
// only days within a range of 10 days from the current
// date.
// You can use the functions date.getFullYear() -- returns the year
// as 4 digit number, date.getMonth() -- returns the month as 0..11,
// and date.getDate() -- returns the date of the month as 1..31, to
// make heavy calculations here.  However, beware that this function
// should be very fast, as it is called for each day in a month when
// the calendar is (re)constructed.
function isDisabled(date) {
  var today = new Date();
  return (Math.abs(date.getTime() - today.getTime()) / DAY) > 10;

function showFlatCalendar(id, holder, format, selectedHandler) {
  var prnt = document.getElementById(holder);
  var element = document.getElementById(id);
  // construct a calendar giving only the "selected" handler.
  var cal = new Calendar(0, null, selectedHandler);
  // hide week numbers
  cal.weekNumbers = false;

Put this file in {cakeproject}/app/webroot/js/. Basicaly this is a code snipet which I found in Calendar documentation.

3. Get this Helper and put it into date_picker.php file under your Helpers directory – {cakeproject}/app/view/helpers/:

* Autocomplete Helper
* @author  Nik Chankov
* @website
* @version 1.0.0

class DatePickerHelper extends FormHelper {
    var $format = '%Y-%m-%d';
     *Setup the format if exist in Configure class

    function _setup(){
        $format = Configure::read('DatePicker.format');
        if($format != null){
            $this->format = $format;
    * The Main Function - picker
    * @param string $field Name of the database field. Possible usage with Model.
    * @param array $options Optional Array. Options are the same as in the usual text input field.
    function picker($fieldName, $options = array()) {
        $htmlAttributes = $this->domId($options);        
        $divOptions['class'] = 'date';
        $options['type'] = 'text';
        $options['div']['class'] = 'date';
        $options['after'] = $this->Html->link($this->Html->image('../js/jscalendar/img.gif'), '#', array('onClick'=>"return showCalendar('".$htmlAttributes['id']."', '".$this->format."'); return false;"), null, false);
        $output = $this->input($fieldName, $options);
        return $output;
    function flat($fieldName, $options = array()){
        $htmlAttributes = $this->domId($options);        
        $divOptions['class'] = 'date';
        $options['type'] = 'hidden';
        $options['div']['class'] = 'date';
        $hoder = '<div id="'.$htmlAttributes['id'].'_cal'.'"></div><script type="text/javascript">showFlatCalendar("'.$htmlAttributes['id'].'", "'.$htmlAttributes['id'].'_cal'.'", "'.$this->format.'", function(cal, date){document.getElementById(\''.$htmlAttributes['id'].''.'\').value = date});</script>';
        $output = $this->input($fieldName, $options).$hoder;
        return $output;

In fact as you can see it’s usinf a textbox from form helper with added at the end calendar image for date picker.

4. Add the folowing code in your layout file between head tags:

    <!-- Javascript includes-->
    <?php echo $javascript->link('jscalendar/calendar.js'); ?>
    <?php echo $javascript->link('jscalendar/lang/calendar-en.js'); ?>
    <?php echo $javascript->link('common.js'); ?>
    <!-- CSS Theme-->
    <?php echo $html->css('../js/jscalendar/skins/aqua/theme');?>

or in every view which using that helper. Depends on your taste.

5. Add this helper in $helpers variable under the controller:

class TestController extends AppController {
    var $helpers = array(..., 'DatePicker');

6. Use the Helper in the view files with:
for Popup

    <?php echo $datePicker->picker('datefield');?>

or Flat

    <?php echo $datePicker->flat('datefield');?>

*** Update *** Abdullah Zainul Abidin extended this helper so now it’s not required to touch layout by adding the scripts and css required. Now they are called automatically in the header. Check it out

Happy Baking!

66 thoughts on “Advanced Datepicker helper for CakePHP

  1. Pierre


    There is a small bug in 3. wrt picker(): if there is no $options specified, domId(null) generates a string whereas an associative array is expected.

    A quick fix: replace the default value
    function picker($fieldName, $options = null) {
    function picker($fieldName, $options = array()) {

  2. Carina


    I’m trying out the jscalendar with cakephp. Your manual is very good, and I have the datepicker up and running. But I would really like to have the calendar “flat” underneath text field.(instead of a popup). Any idea how to do this.
    Thanks in advance!!


  3. Nik Chankov Post author

    @Carina – Thanks for your comments!

    About the Flat Calendar option – I just made some amendments which will allow you to make Flat Calendar field. The field which hold the data is hidden, so users wont mess it up. They can only pick from the Calendar and that’s it. Calendar feed the date value from this hidden field so every time it will be selected properly.

    Hope that helps!

  4. DGC

    I did everything you said here, but it doesn`t work.

    Fatal error: Call to undefined method DatePickerHelper::setFormTag() in cakePHP/app/views/helpers/date_picker.php on line 25


  5. Nik Chankov Post author

    @DGC Thanks for visiting my page.

    This code is tested and developed on CakePHP verison 1.2, I just check the 1.1 Api and I didnt see such function setFormTag(). Probably this is the problem.

    I would like to hear if this is the case, and thanks, I will add a note in the article that this is applied for v.1.2


  6. Pingback: links for 2007-10-13 « Richard@Home

  7. Nik Chankov Post author

    Thanks silid,
    I am considering to write an article there. BUT I wrote an article based on my Helper for Autocomplete, and so far it’s not publiched and it’s quite a while since then 🙁
    I will try to publish it anyway.

    About the parameters – you could modify the webroot/js/common.js mentioned in my article. There is the Calendar “setup”. As you can see there are some options already used there. Unfortunately, once they are set there will be available for all callendar instances. So far there is no solution to make this for each instance of the calendar.

    Have a good day!

  8. Alberto D'Este

    Hi, I’ve just modified date_picker.php to works with CakePHP version 1.1.x.
    In case you are interested of:
    function picker($fieldName, $options = array()) {
    $htmlAttributes = array(‘class’=>’date’,’type’=>’text’,’size’ => ’10’, ‘id’=>(isset($options[‘id’])?$options[‘id’]:$fieldName)); if(isset($options[‘value’])){ $htmlAttributes[‘value’] = $options[‘value’];
    $output = $this->Html->input($fieldName, $htmlAttributes);
    $output .= $this->Html->link($this->Html->image(‘../js/jscalendar/img.gif’), ‘#’, array(‘class’=>’calendar’, ‘onClick’=>”return showCalendar(‘”.$htmlAttributes[‘id’].”‘, ‘”.((isset($options[‘format’])?$options[‘format’]:$this->format)).”‘); return false;”), null, false);
    return $output;


  9. Sul

    Hi Nik,
    I have a question, I probe the code on Firefox and works fine, but when it open the calendar on IE 7, appears in another position respect than the calendar icon, why?

  10. Nik Chankov Post author

    @Alberto D’Este – Thanks, this code would help somebody.

    @Sul – I am using such helper in a project and I checked it with IE as well and there is no problem like you mention. I think that this is a problem of CSS rather than Calendar problem. But this is just a guess.

    @Dawn – Calendar JS is not my code 🙂 I wish to be but it is not. so you can download the calendar from it’s official web site
    The download link is in the right column of the page. Hope that helps.

  11. Joe

    How do you change the default position of the calendar from below the field to the right of the field? I’ve tried to change it in common.js, from “Br” to “R”, which should align it to the right of the field according to the jscalendar reference manual, but nothing happens. Thanks for your taking the time to do this. It is a great help and works great otherwise!

  12. Nik Chankov Post author

    @Joe – I am glad that helper helps somebody 🙂
    About the positioning I made a test it’s working you should remember that there are 2 letters defining the position:
    first one is the vertical positioning and the possible variants are: T=Top,C=Center,B=Bottom
    The second one is the horizontal pozition and the possible variants are: L=Left,C=Center,R=Right
    so if you want to align the calendar popup to center right you should replace BR with CR and this will do the job.

    Hope this make sense!

  13. Buzz

    Thanks for the code.
    When I use it from an Add View, the calendar displays as expected. However on an Edit View where a date value exists (and is displayed in the input box) The calendar displays without any of the graphics, just the numbers ‘floating’ transparently where the finished calender should be.
    Any thoughts?

  14. Nik Chankov Post author

    Hi Abdullah,
    I am glad that you found this helpful. 🙂
    Adding the lines for JavaScript includes doesn’t need to be included in every action which you had.

    The idea behind is that you can add the JS code in your layout, so once you do this the only code which you need to add in your helpers is the $datePicker->picker() function.

    I think your addition is good but only if you have one date field per screen, otherwise you will load the JavaScript as many times as you have Date Field, which should work, but is not the best practice 😉

  15. Nik Chankov Post author

    It is my fault, I didn’t understood your idea. 🙂 I didn’t saw that you using beforeRender(). I thought you just print the script part just right before printing the input tag.

    About printing the code above the doctype – I also think it’s not the best way.

    Anyway, important is that this helper do what it supposed to do 🙂

  16. jarrett

    Really a brilliant piece of code integration, thanx alot..You made my lunch time longer….lol…:-D
    one small Q, Im trying to add the date and time, i pass the helper the params $datePicker->picker(‘Sitepage/publish_date’, array(‘format’=>’%Y-%m-%d [%W] %H:%M’)…but it doesnt show the calendar with the time picker:(

  17. jarrett

    Answer to my own Q, here we go for cakephp1.1:

    function picker($fieldName, $options = null, $showsTime = null) {
    $htmlAttributes = array(‘class’=>’date’,’type’=>’text’,’size’ => ’10’, ‘id’=>(isset($options[‘id’])?$options[‘id’]:$fieldName));
    $htmlAttributes[‘value’] = $options[‘value’];
    $output = $this->Html->input($fieldName, $htmlAttributes);
    $output .= $this->Html->link($this->Html->image(‘../js/jscalendar-1.0/img.gif’), ‘#’, array(‘class’=>’calendar’, ‘onClick’=>”return showCalendar(‘”.$htmlAttributes[‘id’].”‘, ‘”.((isset($options[‘format’])?$options[‘format’]:$this->format)).”‘, ‘”.$showsTime.”‘); return false;”), null, false);
    return $output;
    Then U simple call it with:
    echo $datePicker->picker(‘Sitepage/publish_date’, array(‘format’=>’%Y-%m-%d %H:%M’), ‘yes’);

  18. SteveH

    Hi Nik,

    Got you very nice code working in my CakePHP 1.1 test app, using jarret’s fix. The only problem I’m having is that the popup calendar is being drawn for the full width of the web page! Do you have any ideas what the problem might be?

    Thanks very much,

  19. Nik Chankov Post author

    Hi SteveH,

    Just to clarify the issue with Alberto’s approach:
    the “problem” is that he miss to add the function _setup(); which actually extract the format from the Configure class. I take a look and in CakePHP1.1.x.x there is Configure class and I think the following code should work as a dream:

    function picker($fieldName, $options = array()) {
       $htmlAttributes =   array(class=>date,'type’=>’text’,’size’ => ‘10?, ‘id’=>(isset($options[’id’])?$options[’id’]:$fieldName)); if(isset($options[’value’])){ $htmlAttributes[’value’] = $options[’value’];
       $output = $this->Html->input($fieldName, $htmlAttributes);
    $output .= $this->Html->link($this->Html->image(’../js/jscalendar/img.gif’), ‘#’, array(’class’=>’calendar’, ‘onClick’=>”return showCalendar(’”.$htmlAttributes[’id’].”‘, ‘”.((isset($options[’format’])?$options[’format’]:$this->format)).”‘); return false;”), null, false);
    return $output;

    About calendar being drawn full width of the page: it’s a css issue. CakePHP define table to be with width:100% which automatically make table of the popup 100%. The solution is to add following css in your css files:

    .calendar table {width:auto;}

    this will fix the issue. 😉

  20. JenR

    Thanks for contributing this code to the community Nik! I love calendar date pickers!

    I’m a cake noobie and need some help. I used the code you provided for CakePHP1.1.x.x, but I get an error:
    Notice: Undefined offset: 1 in /cake/libs/view/helpers/html.php on line 947

    Aside from that error showing up, the calendar picker appears to be working. Should I still be using this code in my edit page:

    Any ideas? Your help is greatly appreciated! Thanks!

  21. Nik Chankov Post author

    @JenR – can you send me some code, because as far I can see the function which causing that Notice is setFormTag() and there only the model and field was set.

    I think the problem comes, because you using field which is not exist in database.

  22. JenR

    Oh duh! I didn’t put my own model name and db field in, it works now.


    Thanks for pointing me in the right direction!!

  23. hashem

    im getting an error saying that calender is not defined in my error console.
    after creating everything as described here, i get the input field, but at the end of it theres just a little blue square and when i click it, nothing happens.

  24. Nik Chankov Post author

    hashem, I think you didn’t put the code for calendar js in the right place, or you didn’t get the origilan calendar script from the js code shown here is just an extension how to connect field and js, but the core js is different. About blue square – probably the icon is missing in your wwwroot/js/jscalendar/ folder.

    Hope this helps

  25. hashem

    well i did get my code from that site and i put it in the webroot/js folder as mentioned above, but it still didnt work.
    and what do you mean by “probably the icon is missing in your wwwroot/js/jscalendar/ folder.”

    just so you know, im just a co-op student working on the portal for the company that hired me, as part of my co-op, so im no programming genious or anything.

  26. Nik Chankov Post author

    Hashem, if you be able to show me the site where you experienced this problem probably I could give you a hint. Other than that – I cannot help much.

  27. hashem

    well i would but i cant, sorry. thanks anyway, ill let you know if i can figure out something specific

  28. Niko

    Hi Nik !
    It’s really a great work,
    but I need your help
    th epicker works great saving in my databese correctly, but cause a problem to the debugger so that it couldn’t do a redirect
    it says:
    Warning: implode() [function.implode]: Bad arguments. in /var/cake/libs/debugger.php on line 497
    where can it be the problem?

  29. Marc


    Great work ! Works fine under 1.2. A bit hard to adapt to 1.1 for a noobie like me.
    Just a question : does somebody notice that the icon beside the date field is on a new line ? I looked at the html source page, and I think it must come from a CSS attribute. But, which one ? I use the cake.generic.css default file.

  30. Giorgio

    i want to thanks who posted the cakephp 1.1.x version, without i would spend a lot of time trying to change then 1.2 version. Thanks a lot to everybody and a special thanks to Nick for his tip

  31. Simon

    Before everything, great job ! It works fine and it’s more user-friendly than cakephp’s original date field…
    By the way, I spotted a little problem when using the datepicker with the GET method in forms. Let me explain…

    When you create a POST method form, the form helper names the inputs with names like “data[Person][first_name]” for example. And with a GET method form, the names are only like “first_name”, in order to be able to pass them in the URl’s without problem.
    So, if you take a look at the line 207 of /cake/libs/view/helpers/form.php, you will see that the form helper defines a variable called $this->requestType, which default value is “post”. And, the point is that this variable is not defined in the datepicker helper, because it is a subclass of the form helper. And so with the datepicker fields, the form helper always assumes that it is a POST method form, and names the fields with names like data[Person][date_of_birth]… Which does not works well in URl’s ! I hope I explained the problem clearly !

    So, for now I changed a bit the file date_picker.php as follows :

    function picker($fieldName, $requestType = null, $options = array()) {
          // That's new !
            if($requestType == null) {
                $this->requestType = 'post';
            } else {
                $this->requestType = strtolower($requestType);

            $htmlAttributes = $this->domId($options);
            $divOptions['class'] = 'date';
            $options['type'] = 'text';
            $options['div']['class'] = 'date';
            $options['after'] = $this->Html->link($this->Html->image('../js/jscalendar/img.gif'), '#', array('onClick'=>"return showCalendar('".$htmlAttributes['id']."', '".$this->format."'); return false;"), null, false);
            $output = $this->input($fieldName, $options);

            return $output;

    Now you have to specify the method when you create a datepicker field… I know it is not very convenient and nice, but I am not very familiar to Object Oriented PHP, and I can’t get the datepicker class fetching the value of this variable ! If anyone sees a better way to get it work… *-)

  32. Nik Chankov Post author

    @Simon, thanks for your comment and especially for pointing out this sort of bug. To tell you the truth, I really rarely using GET methods for posing data, so probably that’s why I didn’t notice this behavior of the helper.

    The method which you proposed I don’t think it’s very good. Rather than this I would suggest 2 ways to get this working:
    1. Because datePicker class inherits everything from the Form class, instead of using $form->create() and $form->input() /especially in that case with _GET method you could use $datePicker->create() and $datepicker->input() and then easily you could set method in the create() function as normal. But I think this is more messy.
    2. The second method, which I would use is to set the requestType variable just before calling the picker function or with small example you could set the field with following code:

    $datePicker->requestType = "get";
    //or even better:
    $datePicker->requestType = $form->requestType;

    3. Here it’s possible to use your way but instead of settling a extra field in the function definition, I would use an option in the $options variable like:

    function picker($fieldName, $options = array()) {
          // That's new !
            if(isset($options['method'])) {
                $this->requestType = strtolower($options['requestType']);
            } else {
                $this->requestType = 'post';
            $htmlAttributes = $this->domId($options);
            $divOptions['class'] = 'date';
            $options['type'] = 'text';
            $options['div']['class'] = 'date';
            $options['after'] = $this->Html->link($this->Html->image('../js/jscalendar/img.gif'), '#', array('onClick'=>"return showCalendar('".$htmlAttributes['id']."', '".$this->format."'); return false;"), null, false);
            $output = $this->input($fieldName, $options);

            return $output;

    Hope this make sense

  33. Johnny Hughes

    This line in [b]date_picker.php[/b]:


    Needs to be changed to:


    setFormTag is now depreciated, at least in the 1.2 RC2 release of cake.

  34. Nik Chankov Post author


    Thanks for the interest. I will change the code that you’ve suggested.

    About the integration with the security component – I don’t have idea why it’s not working. I’ve also experiencing problems with the Security component with other type of fields, so for now cannot help much.

  35. Terri Ann

    I’m just starting to learn Cake PHP and this is a great tutorial though it took me a little bit to figure out what the final file structure. Would it make more sense to save the javascript file as jscalendar.js in the same directory as the /jscalendar/ directory containing the calendar scripts?

    This is the first javascript helper I’ve added so I’m not sure if that isn’t one of the standards but it seems more organized to me that way!


  36. Nik Chankov Post author

    Terri Ann,

    I am glad that this helps.

    About file structure – it’s up to you. Basically, I assume that jscalendar folder is a vendor – like core files in the CakePHP which I prefer to leave unchanged. This is the only reason, but if you prefer to put this file in jscalendar folder – I don’t this it’s wrong.

  37. Terri Ann

    Thanks for the the response Nik but I don’t think you followed me completely on that one. I meant:

    |- jscalendar/
    |- jscalendar.js

    common.js didn’t seem descriptive enough for me.

  38. Nik Chankov Post author

    Oh, sorry my fault.

    About the naming convention. It was inherited from my previous projects where in common.js I’ve put all js related to a project, but I agree with you, that jscalendar.js is more sensible. 🙂

  39. jarrett

    For anyone who needs to get the date and time.
    Add the following to changes to date_picker.php
    line 31
    function picker($fieldName, $options = array(), $showsTime = null) {
    line 38
    $options[‘after’] = $this->Html->link($this->Html->image(‘{Your/Image/Location}’), ‘#’, array(‘onClick’=>”return showCalendar(‘”.$htmlAttributes[‘id’].”‘, ‘”.$this->format.”‘, ‘”.$showsTime.”‘); return false;”), null, false);
    Then in your view that needs time as well
    echo $datePicker->picker(‘start_date’, array(‘format’=>’%Y-%m-%d %H:%M’), ‘yes’);

Leave a Reply

Your email address will not be published. Required fields are marked *