Add the widget to your model:
def select_datewidget(f,v):
import datetime
now = datetime.date.today()
dtval = v if v else now.isoformat()
y,m,d= str(dtval).split("-")
dt = SQLFORM.widgets.string.widget(f,v)
dayid = dt['_id']+'_day'
monthid = dt['_id']+'_month'
yearid = dt['_id']+'_year'
wrapper = DIV(_id=dt['_id']+"_wrapper")
day = SELECT([OPTION(str(i).zfill(2)) for i in range(1,32)],
value=d,_id=dayid)
month = SELECT([OPTION(datetime.date(2008,i,1).strftime('%B')
,_value=str(i).zfill(2)) for i in range(1,13)],
value=m,_id=monthid)
year = SELECT([OPTION(i) for i in range(now.year-50,now.year+50)],
value=y,_id=yearid)
setval = "var curval = jQuery('#%s').val();if(curval){var pcs = curval.split('-');"\
"var dd = pcs[2];var mm = pcs[1];var yy = pcs[0];"\
"jQuery('#%s').val(dd);jQuery('#%s').val(mm);jQuery('#%s').val(yy);}" % \
(dt['_id'],dayid,monthid,yearid)
combined = "jQuery('#%s').val()+'-'+jQuery('#%s').val()+'-'+jQuery('#%s').val()" % \
(yearid,monthid,dayid)
combine = "jQuery('#%s').val(%s);" % (dt['_id'],combined)
onchange = "jQuery('#%s select').change(function(e){%s});" % \
(wrapper['_id'],combine)
jqscr = SCRIPT("jQuery('#%s').hide();%s%s" % (dt['_id'],setval,onchange))
wrapper.components.extend([month,day,year,dt,jqscr])
return wrapper
Create a test form in your controller and set the field to use the widget:
def index():
form = SQLFORM.factory(Field('posted','date',default=request.now,widget=select_datewidget))
if form.accepts(request.vars,session):
response.flash = "New record added"
return dict(form=form)
That all folks....
Comments (8)
- Login to post
order by: newest oldest upvoted downvoted
This works beautifully except for an interesting issue with the month field. It defaults to 'January' regardless of the input date. The day and year seem to work fine.
@reyelts - good catch. fixed now.
Thanks loads! I skimmed through the source before posting and couldn't see the error... you have much better eyes than me.
I'm using it for a birth date field and modified it so the year range is always the current year - 100 instead of the hardcoded 200 year range. In case anyone is interested, here's the mod:
replace:
dtval = v if v else datetime.date.today()
y,m,d=str(dtval).split("-")
with this:
now = datetime.date.today()
dtval = v if v else now.isoformat()
y,m,d=dtval.split("-")
and
replace:
year = SELECT([OPTION(i) for i in range(1900,2100)],value=int(y),_id=dt['_id']+'_year')
with this:
year = SELECT([OPTION(i) for i in range(now.year-99,now.year+1)],value=int(y),_id=dt['_id']+'_year')
Note that I also removed the call to str() for dtval by having the default dtval be isotime() instead of the date object itself. It saves the interpreter from running str() when dtval is set to v.
@reyelts - Thanks. I added your changes and also fixed support for SQLFORM(keepvalues=True)
How would you use it with an auth_user record that has a birthdate field? Do I have to create the form manually or can this slice be combined with a crud-created form?
show more comments0
reyelts 14 years ago
0
mrfreeze 14 years ago
0
reyelts 14 years ago
0
mrfreeze 14 years ago
0
johannspies 15 years ago