odd save behavior with check box

28 views
Skip to first unread message

Wes James

unread,
Nov 21, 2008, 1:20:28 AM11/21/08
to web2py Web Framework
I have an app that on one page I have a set of fields (first 20 fields
of say 50) I have manually placed. All saves well and when I go to
another page and come back all is well.

On a separate page, I edit the rest of these fields. Part of these
are check box fields and some others including textarea fields.

When I save the data on this page - all is well.

I then go back to the first page and make a change and save the data -
fine, but if I go back to the page with the check boxes, they are all
cleared out - I look in the DB in admin area and yes, they are all set
to False. But the textarea fields do not do this on this page - they
keep their data just fine.

So I created a test page and made a controller like I already have:

form=t2.create(db.student)
return dict(form=form)

and then in a test.html do {{=form}

I then save the page with a check box selected - fine - that works.

I then go back to my first page and make a change and save. Go back
to the test page and the check box is cleared.

Why is it doing this?

thx,

-wj

billf

unread,
Nov 21, 2008, 3:13:06 AM11/21/08
to web2py Web Framework
If the following explanation is correct it is a big coincidence
because I have just been looking at this behaviour.

When a form is submitted, if there is no parameter for a field then
one of 2 things happen (simplified):

If it is NOT a checkable form control (checkable=check box or radio
button) then the original form value is used. In the case of an
existing record, this will be the value in the existing record. In the
case of a new record then any defailt will be used.

If it IS a checkable form control then it is impossible to distinguish
between a missing parameter and an unchecked control because CGI
doesn't send "mycheckbox=off" - it just doesn't send anything. So to
be able to set a boolean field to false, web2py must say
missing==unchecked.

In your case, you set checkboxes on page2 and everything is fine.
When you amend page 1 and submit, no checkboxes are present so web2py
sets the associated fields to False. You go back to page 2 and, lo and
behold, all the checkboxes are unchecked.

The only solution, given the current setup, is that any fields
represented as checkable controls but not displayed in the current
form must be set up in the form as "hidden" so that checked fields are
returned even if they are not displayed.

I think it should be possible to create the "hidden" fields
automatically in SQLFORM/FORM, although supporting "custom
forms" (where a developer may not include a field that the standard
SQLFORM would include) could be a complication.

billf

unread,
Nov 21, 2008, 7:32:00 AM11/21/08
to web2py Web Framework
I am investigating a possible solution to the above problem that would
return fieldname=OFF if a displayed checkbox is unchecked.

This would enable web2py to retain existing values for a boolean field
if a request.var was not present.

However, I recognise that some people may consider returning
fieldname=OFF a contravention of protocol - does anyone feel like
that?

FYI the solution is to add a hidden "off" checkbox (value='off') for
each displayed checkbox (both with the same name) and when the normal
checkbox is clicked setting the "off checkbox appropriately so that
whatever the status of the normal checkbox either name=on or name=off
will be returned.

Any thoughts gratefully received.

mdipierro

unread,
Nov 21, 2008, 9:10:35 AM11/21/08
to web2py Web Framework
Do you have default=False in the database?

SQLFORM and and FORM take a parameter hidden=dict(key='value')

Massimo

billf

unread,
Nov 21, 2008, 9:49:53 AM11/21/08
to web2py Web Framework
Massimo

In what way are you suggesting "SQLFORM and and FORM take a parameter
hidden=dict(key='value')" would be used?

Bill

mdipierro

unread,
Nov 21, 2008, 10:28:05 AM11/21/08
to web2py Web Framework
It was mentioned in one of the previous emails. I am not sure it helps
with the current problem. I am not sure I understand the current
problem.

checkboxes are always unchecked unless:
1) update form and it was unchecked in the original record
2) create form and corresponding field has default=True

Are you saying this is not the case or that I am missing something?
I think this is the correct behavior

Massimo

Wes James

unread,
Nov 21, 2008, 10:42:02 AM11/21/08
to web...@googlegroups.com
This is how I have my fields set:

SQLField("fieldname","boolean")

I'll need to do what billf said, loop through my checkbox fields and
set them as hidden.

something like this:

{{for cbi in range(26,27):}}
{{=form[0][cbi][1][0]['_checked']}}
<input name="{{=form[0][cbi][1][0]['_name']}}" type=hidden
value="{{=form[0][cbi][1][0]['_checked']}}"><br>
{{pass}

Wes James

unread,
Nov 21, 2008, 10:43:57 AM11/21/08
to web...@googlegroups.com
like this since the one line was an output line to let me see what was
happending:

{{for cbi in range(26,27):}}

mdipierro

unread,
Nov 21, 2008, 10:50:16 AM11/21/08
to web2py Web Framework
You should not be doing that. You are clearly doing something wrong in
the controller. Can you post the relevent parts of your controller and
custom views?

Massimo

billf

unread,
Nov 21, 2008, 10:52:23 AM11/21/08
to web2py Web Framework
Massimo

I think there is a typo in your point 1) and it should read "update
form and it was *checked* in the original record". The behaviour of
the setting the checkbox value is not in question.

I believe the problem Wes originally raised is that a boolean field on
the database gets set to False erroneously if a form does not contain
a control for that field (either hidden or a checkbox). This is
because web2py (any server-side code) cannot distinguish between an
unchecked checkbox and an absence of a checkbox. So the missing
control is interpreted as unchecked/false and stored as such. This
differs from other field types where a missing control can and is
interpreted as "no change".

Wes James

unread,
Nov 21, 2008, 11:12:49 AM11/21/08
to web...@googlegroups.com
well, this does not work either, I tried using the default value
'checked' then tried 'true', but when I save the form the value is not
retained:

{{for cbi in range(26,76):}}


<input name="{{=form[0][cbi][1][0]['_name']}}" type=hidden

value="{{='true' if str(form[0][cbi][1][0]['_checked']) in 'checked'
else ''}}">
{{pass}}


It seems that there is no such think as a hidden checkbox, because:

<input name='this' type="hidden" value="checked">

when submitted does not keep its value, it gets set to unchecked when
saved. hmmm...

mdipierro

unread,
Nov 21, 2008, 11:15:11 AM11/21/08
to web2py Web Framework
SQLFORM(...,fields=[...])

should be used to determine which fields are expected and which should
be ignored.

For T2 use

db.table.exposes=[....] # list of field names

Massimo

Yarko Tymciurak

unread,
Nov 21, 2008, 11:39:17 AM11/21/08
to web...@googlegroups.com
Wes -

I think we need a complete - if minimized example which others can use to reproduce.  Can you provide?

Thanks,
Yarko

Wes James

unread,
Nov 21, 2008, 11:52:56 AM11/21/08
to web...@googlegroups.com
if i put:

db.student.exposes=['checkbox1','checkbox2','checkbox3','checkbox4']

in db.py

then i get this error:

Traceback (most recent call last):
File "gluon/restricted.pyc", line 62, in restricted
File "/Users/Shared/web2py.app/Contents/Resources/applications/cnrsa/views/default/profile.html",
line 155, in <module>
File "gluon/html.pyc", line 113, in __getitem__
IndexError: list index out of range

If i take the exposes out, then the error goes away.

Yarko Tymciurak

unread,
Nov 21, 2008, 11:59:03 AM11/21/08
to web...@googlegroups.com
Wes -


...

So your student table has boolean fields called "checkbox1", "checkbox2" and "checkbox3"?

Those names sound off ... not like things that describe a student data record.

  I think we need more context.

Something we can reproduce - complete example would really be useful at this point.


Regards,
Yarko

Wes James

unread,
Nov 21, 2008, 12:00:10 PM11/21/08
to web...@googlegroups.com
Yarko,

so far, i can get it to work if the checkbox fields are not hidden on
the form. My problem now is trying to make 'hidden' checkbox form
elements. I don't see any way to hide checkbox elements.

Yarko Tymciurak

unread,
Nov 21, 2008, 12:02:42 PM11/21/08
to web...@googlegroups.com
Understood - but Bill thinks there's a bug, and is proposing patches;  Massimo is thinking perhaps you're doing something wrong and no patch should be needed - having an example - even if you want to send privately to Massimo - would help close this disconnect.

Thanks.

Wes James

unread,
Nov 21, 2008, 12:02:57 PM11/21/08
to web...@googlegroups.com
oh, i forgot, i can hide with css....

i'm going to try that.

Wes James

unread,
Nov 21, 2008, 12:04:37 PM11/21/08
to web...@googlegroups.com
i'll build a simple app with a text input and a couple of check boxs
and see how that works.

-wes

Yarko Tymciurak

unread,
Nov 21, 2008, 12:07:13 PM11/21/08
to web...@googlegroups.com
Wes -

If you're doing things a "hard" way when there's a direct way, it would be nice for Massimo to point that out (and maybe that will help document something better);

If there's a bug that we don't understand, then I'd like the loop to be closed so that can be addressed - either a patch from bill, or something else.

Thanks for your help with this.

Yarko.

Yarko Tymciurak

unread,
Nov 21, 2008, 12:03:55 PM11/21/08
to web...@googlegroups.com
*sigh*

mdipierro

unread,
Nov 21, 2008, 12:26:55 PM11/21/08
to web2py Web Framework
I am sure there is no bug here. Wes, I suspect you are trying to
reinvent something that exist but I cannot figure out what.
If you just want to hide fields you can do:

<script>
$(document).ready(function() {
$('#tablename_fieldname__row').hide();
// list other fields...
});
</script>

On Nov 21, 11:03 am, "Yarko Tymciurak" <yark...@gmail.com> wrote:
> *sigh*
>
> On Fri, Nov 21, 2008 at 11:02 AM, Wes James <compte...@gmail.com> wrote:
>
> > oh, i forgot, i can hide with css....
>
> > i'm going to try that.
>
> > On Fri, Nov 21, 2008 at 10:00 AM, Wes James <compte...@gmail.com> wrote:
> > > Yarko,
>
> > > so far, i can get it to work if the checkbox fields are not hidden on
> > > the form. My problem now is trying to make 'hidden' checkbox form
> > > elements. I don't see any way to hide checkbox elements.
>
> > > On Fri, Nov 21, 2008 at 9:39 AM, Yarko Tymciurak <yark...@gmail.com>
> > wrote:
> > >> Wes -
>
> > >> I think we need a complete - if minimized example which others can use
> > to
> > >> reproduce. Can you provide?
>
> > >> Thanks,
> > >> Yarko
>
> > >> On Fri, Nov 21, 2008 at 10:15 AM, mdipierro <mdipie...@cs.depaul.edu>

Wes James

unread,
Nov 21, 2008, 12:39:10 PM11/21/08
to web...@googlegroups.com
Sorry for all this hassle.

I will do some more testing, but for now this is what I have working.
On my first page I have:

<div id='hidethis'>
{{for cbi in range(26,76):}}
<input name="{{=form[0][cbi][1][0]['_name']}}" type=checkbox
{{='checked="checked"' if str(form[0][cbi][1][0]['_checked']) ==
'checked' else ''}}>
{{pass}}
</div>

I have hidden actual checkbox elements using css on the div
(#hidethis{display:none;}

The values are being kept now in all cases. For some reason, the only
way the checkboxes will keep their values between submits is if they
actually exist on a page.

I will make a simple example and post what i find.

thx for everyones input

-wes

Reply all
Reply to author
Forward
0 new messages