Hi,
Quite a few people have previously asked on the forum about having dropdown lists for day, month and year when entering dates.
I have come up with a rough solution which works for me. I want to improve my code so please give me your thoughts.
Extend the CHtml helper - I have saved this in /protected/components is this the best place?
class Html extends CHtml
{
public static function activeDateField($model,$attribute,$htmlOptions=array())
{
// SET UP ARRAYS OF OPTIONS FOR DAY, MONTH, YEAR
$x = 1;
$dayOptions = array('0'=>' - ');
while ($x < 31)
{
$dayOptions[$x] = $x;
$x++;
}
$monthOptions = array(
'0' => ' - ',
'1'=>'January',
'2'=>'February',
'3'=>'March',
'4'=>'April',
'5'=>'May',
'6'=>'June',
'7'=>'July',
'8'=>'August',
'9'=>'September',
'10'=>'October',
'11'=>'November',
'12'=>'December',
);
$yearOptions = array('0'=>' - ');
$x = 1901;
while ($x < 2030)
{
$yearOptions[$x] = $x;
$x++;
}
parent::resolveNameID($model,$attribute,$htmlOptions);
if ($model->$attribute != '0000-00-00' && isset($model->$attribute))
{
// intval removes leading zero
$day = intval(date('j',strtotime($model->$attribute)));
$month = intval(date('m',strtotime($model->$attribute)));
$year = intval(date('Y',strtotime($model->$attribute)));
} else
{
// DEFAULT TO 0 IF THERE IS NO DATE SET
$day = 0;
$month = 0;
$year = 0;
}
$return = parent::dropDownList($htmlOptions['name'].'[day]', $day,$dayOptions);
$return .= parent::dropDownList($htmlOptions['name'].'[month]', $month,$monthOptions);
$return .= parent::dropDownList($htmlOptions['name'].'[year]', $year,$yearOptions);
return $return;
}
I don’t like the code at the start of this function to get options for day, month and year.
This also lacks some functionality for active input fields - it doesn’t add an ‘error’ class etc.
Extend the CActiveRecord class - The SetAttributes function looks for all date fields (given in an array in the model) and merges the three separate input fields into a single MySQL date string.
class ActiveRecord extends CActiveRecord
{
/**
* Extends setAttributes to handle active date fields
*
* @param $values
* @param $scenario
*/
public function setAttributes ($values,$scenario='')
{
foreach ($this->dateAttributes() as $dateAttribute)
{
if (is_array($values[$dateAttribute]))
{
$day = $values[$dateAttribute]['day'];
$month = $values[$dateAttribute]['month'];
$year = $values[$dateAttribute]['year'];
$values[$dateAttribute] = date('Y-m-d',mktime(0,0,0,$month,$day,$year));
}
}
parent::setAttributes($values,$scenario);
}
}
Usage:
In your model add the following function to specify which fields are dates:
class Passport extends ActiveRecord
{
....
public function dateAttributes()
{
return array('expiryDate');
}
....
}
And finally, in your view use Html::activeDateField($model,‘attributeName’) to get date dropdowns.
<div class="simple">
<? echo CHtml::activeLabelEx($model, 'expiryDate'); ?>
<? echo Html::activeDateField($model, 'expiryDate'); ?>
</div>