Date/Time Range Selector Widget for Symfony

I needed to create a date/time widget for use in an sfForm in a symfony project I was working on, and unfortunately there’s not currently a widget that I could find to allow this. In this post I show how I solved this problem, creating a widget for selecting a date range, using the jquery date selector from sfFormExtraPlugin.

The end result looks like this:

DateTime Widget

The reason to create a widget for this is to allow for it to be reused across the site, and of course in other projects too. A similar widget for selecting date ranges already exists (sfWidgetFormDateRange) however it unfortunately doesn’t support having time widgets too. My sfWidgetFormDateTimeRange widget is based off this widget. Here’s the code, with comments removed:


    $this->addOption('template', '
%from_date% %from_time% - %to_date% %to_time%
'); } public function render($name, $value = null, $attributes = array(), $errors = array()) { $values = array_merge(array('from_date' => '', 'to_date' => '', 'from_time' => '', 'to_time' => ''), is_array($value) ? $value : array()); return strtr($this->translate($this->getOption('template')), array( '%from_date%' => $this->getOption('from_date')->render($name.'[from_date]', $value['from_date']), '%from_time%' => $this->getOption('from_time')->render($name.'[from_time]', $value['from_time']), '%to_date%' => $this->getOption('to_date')->render($name.'[to_date]', $value['to_date']), '%to_time%' => $this->getOption('to_time')->render($name.'[to_time]', $value['to_time']), )); } public function getStylesheets() { return array_unique(array_merge( $this->getOption('from_date')->getStylesheets(), $this->getOption('from_time')->getStylesheets(), $this->getOption('to_date')->getStylesheets(), $this->getOption('to_time')->getStylesheets() )); } public function getJavaScripts() { return array_unique(array_merge( $this->getOption('from_date')->getJavaScripts(), $this->getOption('from_time')->getJavaScripts(), $this->getOption('to_date')->getJavaScripts(), $this->getOption('to_time')->getJavaScripts() )); } }

As you can probably see from the code above, the concept is simple – our range widget is essentially a container around 4 other widgets which are provided as options. Allowing the definition of the enclosed widgets allows for extra flexibility, as the exact widgets used for the date and time selections can be defined when the widget is constructed.

Using the widget in a sfForm

The code below shows a simple example of how this widget can be used. I’ve added a little extra ‘fluff’ around it – to limit the minute drop down to 5 minute intervals, and defined a calendar icon for the jQuery pop-up activator.

widgetSchema['span'] = new sfWidgetFormDateTimeRange(array(
      'from_date' => new sfWidgetFormJQueryDate(array('image' => '/images/icons/calendar.gif')),
      'from_time' => new sfWidgetFormTime(array('minutes' => $minutes)),
      'to_date' => new sfWidgetFormJQueryDate(array('image' => '/images/icons/calendar.gif')),
      'to_time' => new sfWidgetFormTime(array('minutes' => $minutes)),

    $this->validatorSchema['span'] = new sfValidatorDateTimeRange(array(
      'from_date' => new sfValidatorDate(),
      'from_time' => new sfValidatorTime(),
      'to_date' => new sfValidatorDate(),
      'to_time' => new sfValidatorTime(),

Using the widget with the admin generator

In your model, it’s likely you’ll have a ‘startdate’ and ‘enddate’ field or similar – and as this single widget is for setting both of these fields, a little bit of extra work is needed in your form class. This code below shows using




to correctly setup the form from an object instance and save the values back to the model.

setDefault('span', array(
      'from_date' => $this->getObject()->getDateTimeObject('startdate')->format('Y-m-d'),
      'from_time' => $this->getObject()->getDateTimeObject('startdate')->format('H:i'),
      'to_date' => $this->getObject()->getDateTimeObject('enddate')->format('Y-m-d'),
      'to_time' => $this->getObject()->getDateTimeObject('enddate')->format('H:i'),

  public function updateObject($values = null)
    if (null === $values)
      $values = $this->values;
    $obj = parent::updateObject($values);
    $obj->setStartdate(sprintf('%s %d:%d',
    $obj->setEnddate(sprintf('%s %d:%d',
    return $obj;


That is all that’s needed! The admin generator will call the methods correctly for you and editing should ‘just work’! The above is Doctrine specific, however modifying it for Propel or anything else should be reasonably simple.


I chose to write this post to demonstrate the flexibility of the sfForm system, and to show an example of a reasonably rich widget. This will be released as part of a plugin at some point.

When writing forms for your project, don’t be afraid to write widget classes that are domain specific. For example, for our internal systems at work, I created a TimicoWidgetFormAccountId widget, which originally was just providing a simple text input, with a specific class attribute for styling. Later, I simply needed to modify this widget to project AJAX style lookups of customers to help people fill in a customers Account ID if they didn’t know it. If I didn’t create this widget to start with, even though to start with it served little purpose, I’d have had to go back though many form classes and make alterations.

11 thoughts on “Date/Time Range Selector Widget for Symfony”

    1. Thanks for your comment.

      Yeah – my screenshot is pretty awful… I really do suck at design when it comes to UI’s, I’ll be the first to admit that, and my boss a close second 😉

      The way the output rendered is easily stylable, and it’s templated too – and it looks more interesting when you use it because you of course get the nice jQuery calender widget pop up.

  1. I need example to configure sfWidgetFormJQueryDate for Filters with date range, somebody help me please? Thank you!

  2. Thank you a lot ! I spent 2 days trying to do this !!
    This is really helpful so it is a good idea if you can submit it to symfony or as a plugin.
    Thanks again.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.