If you benefit from web2py hope you feel encouraged to pay it forward by contributing back to society in whatever form you choose!

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)

alt text

That all folks....

Related slices

Comments (8)

  • Login to post



  • 0
    reyelts 14 years ago
    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.

  • 0
    mrfreeze 14 years ago
    @reyelts - good catch. fixed now.

  • 0
    reyelts 14 years ago
    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.

  • 0
    mrfreeze 14 years ago
    @reyelts - Thanks. I added your changes and also fixed support for SQLFORM(keepvalues=True)

  • 0
    johannspies 15 years ago
    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?

  • 0
    mrfreeze 15 years ago
    @johann - The widget should work with any field of type date. You would just set the widget as usual: db.auth_user.birthdate.widget = select_datewidget

  • 0
    sophie 15 years ago
    Hi is there a way to change the language of the months?

  • 0
    mrfreeze 15 years ago
    You would just need to make a list of months and change this line: month = SELECT([OPTION(datetime.date(2008,i,1).strftime('%B'),_value=i) for i in range(1,13)],value=m,_id=dt['_id']+'_month') to this mymonths = [...] month = SELECT([OPTION(mymonths[i],_value=i) for i in range(1,13)],value=m,_id=dt['_id']+'_month')

Hosting graciously provided by:
Python Anywhere