How to access the checked property?

54 views
Skip to first unread message

Jose

unread,
Aug 27, 2009, 4:44:15 PM8/27/09
to web2py-users
Hi,

The follows is a simplification.

If my controller is:

def buscar():
form = FORM(TABLE(
TR(INPUT(_name='mytxt', _id='mytxt', _value='a text...')),
TR(INPUT(_type='checkbox', _name='mychk', _id='mychk',
_value='')),
TR("", INPUT(_type="submit",_value="Buscar"))
))

if form.accepts(request.vars, session, keepvalues=True):
if request.vars.mychk:
...
...
rows = db(query1 & query2).select()

return dict(form=form, rows=rows)


When I send the form, I know the state of the checkbox on the line [if
request.vars.mychk]. This works well!


In the example below I can not get the same result, The condition is
always true. This is because I is returning the value, which is always
'on', even though I put something else.

def search2():
form = FORM(TABLE(
TR(INPUT(_name='mytxt', _id='mytxt', _value='a text...')),
TR(INPUT(_type='checkbox', _name='mychk', _id='mychk',
_value='')),
TR("", INPUT(_type="button", _value="Buscar",
_onclick="ajax('bg_find2',['mytxt', 'mychk'],
'target');"))
))

return dict(form=form, target=DIV(_id='target'))

def bg_find2():
if request.vars.mychk:
...

return dict(txt=request.vars.mytxt, chk=request.vars.mychk)


How can I access the checkbox checked property?
Or more simply, how can I know the state of the checkbox in bg_find2

Regards
Jose

mr.freeze

unread,
Aug 27, 2009, 7:27:11 PM8/27/09
to web2py-users
I'm not sure why it's always on but you can store the state of the
checkbox in a hidden field and pass it back with the ajax request like
so:

def search2():
form = FORM(
TABLE(
TR(INPUT(_name='mytxt', _id='mytxt', _value='a
text...')),
TR(INPUT(_type='checkbox', _name='mychk',
_id='mychk',_checked="true",_onclick="jQuery('#chkval').val
(this.checked)")),
TR(INPUT
(_type='hidden',_name='chkval',_id='chkval')),
TR(INPUT(_type="button", _value="Buscar",
_onclick="ajax('%s',['mytxt',
'mychk','chkval'],'target');" % URL(r=request,f='bg_find2')))
)
)

return dict(form=form, target=DIV(_id='target'))

def bg_find2():
return request.var.chkval

Jose

unread,
Aug 27, 2009, 8:20:12 PM8/27/09
to web2py-users


On 27 ago, 23:27, "mr.freeze" <nat...@freezable.com> wrote:
> I'm not sure why it's always on but you can store the state of the
> checkbox in a hidden field and pass it back with the ajax request like
> so:
>
> def search2():
>     form = FORM(
>                 TABLE(
>                     TR(INPUT(_name='mytxt', _id='mytxt', _value='a
> text...')),
>                     TR(INPUT(_type='checkbox', _name='mychk',
> _id='mychk',_checked="true",_onclick="jQuery('#chkval').val
> (this.checked)")),
>                     TR(INPUT
> (_type='hidden',_name='chkval',_id='chkval')),
>                     TR(INPUT(_type="button", _value="Buscar",
>                              _onclick="ajax('%s',['mytxt',
> 'mychk','chkval'],'target');" % URL(r=request,f='bg_find2')))
>                      )
>                 )
>
>     return dict(form=form, target=DIV(_id='target'))
>
> def bg_find2():
>      return request.var.chkval
>

mr.freeze

It is a good alternative, but hoped there would be something simple
and straightforward.

Thank you very much

Jose

mr.freeze

unread,
Aug 27, 2009, 8:26:10 PM8/27/09
to web2py-users
I think I see what's going on. web2py's ajax function is explicitly
getting the 'value' of each element id that is passed. The value of a
checkbox doesn't change, it's just not sent during a submit unless it
is checked. The ajax function would need to be changed to account for
this.

mr.freeze

unread,
Aug 27, 2009, 9:39:52 PM8/27/09
to web2py-users
You could also alter the ajax function in web2py_ajax.html:

function ajax(u,s,t) {
var query="";
for(i=0; i<s.length; i++) {
if(i>0) query=query+"&";
var elem = jQuery("#" + s[i]);
if (elem.attr("type")=="checkbox" && elem.attr('checked') ==
false) continue;
query=query+encodeURIComponent(s[i])+"="+encodeURIComponent
(elem.val());
}
jQuery.ajax({type: "POST", url: u, data: query, success: function
(msg) { if(t==':eval') eval(msg); else document.getElementById
(t).innerHTML=msg; } });
}

That should mimic a normal submit with a checkbox.

Jose

unread,
Aug 27, 2009, 9:40:12 PM8/27/09
to web2py-users


On 28 ago, 00:26, "mr.freeze" <nat...@freezable.com> wrote:
> I think I see what's going on.  web2py's ajax function is explicitly
> getting the 'value' of each element id that is passed.  The value of a
> checkbox doesn't change, ...


It is true, so look for ways to access the checked property.

Jose

mr.freeze

unread,
Aug 27, 2009, 9:44:55 PM8/27/09
to web2py-users
Did you try my altered ajax function? It should only send back the
checkbox if it is check. Hope that helps.

mr.freeze

unread,
Aug 27, 2009, 10:34:29 PM8/27/09
to web2py-users
Even better: let jQuery serialize the entire form since it knows how
to handle all of the form elements properly:

function ajaxSubmit(u,t){
query = jQuery("form").serialize();
jQuery.ajax({type: "POST", url: u, data: query, success: function
(msg) { if(t==':eval') eval(msg); else jQuery("#"+ t).html
(msg); } });

Jose

unread,
Aug 27, 2009, 10:47:37 PM8/27/09
to web2py-users


On 28 ago, 01:44, "mr.freeze" <nat...@freezable.com> wrote:
> Did you try my altered ajax function?

I tried not entered because apparently when I was sending my message.
Now I try it.

Thanks

Jose

unread,
Aug 27, 2009, 10:59:33 PM8/27/09
to web2py-users


On 28 ago, 01:44, "mr.freeze" <nat...@freezable.com> wrote:
> Did you try my altered ajax function?

Works well!. You can add it to the trunk?

Jose

mr.freeze

unread,
Aug 27, 2009, 11:01:54 PM8/27/09
to web2py-users
I'll submit a patch.

mr.freeze

unread,
Aug 28, 2009, 1:28:37 AM8/28/09
to web2py-users
I sent a patch to Massimo but for posterity, here is the fixed ajax
function and added an ajaxForm(url,formIndex,targetResponseID)
function that grabs the entire form (by index i so use 0 for single
form pages):

function ajax(u,s,t) {
query = [];
for(i=0; i<s.length; i++) {
q = jQuery("#"+s[i]).serialize();
if(q){query.push(q);}
}
jQuery.ajax({type: "POST", url: u, data: query.join("&"), success:
function(msg) { if(t==':eval') eval(msg); else jQuery("#" + t).html
(msg); } });
}

function ajaxForm(u,i,t){
frm = jQuery("form:eq(" + i + ")");
query = 'undefined=' + i;
if (frm.length==1){query = frm.serialize();}
jQuery.ajax({type: "POST", url: u, data: query, success: function
(msg) { if(t==':eval') eval(msg); else jQuery("#"+t).html
(msg); } });
}


mdipierro

unread,
Aug 28, 2009, 3:46:49 AM8/28/09
to web2py-users
I suggest you don't send the entire form but just the state of the
button you clicked. It will have much faster response.

Massimo

mr.freeze

unread,
Aug 28, 2009, 10:41:33 AM8/28/09
to web2py-users
How about this: Forget ajaxForm and in the ajax function, if s is a
string, it acts as a jQuery selector, otherwise it acts normally.
That would make it more flexible:

function ajax(u,s,t) {
query = '';
if (typeof s == "string"){
d = jQuery(s).serialize();
if(d){query = d;}
}else{
pcs = [];
for(i=0; i<s.length; i++) {
q = jQuery("#"+s[i]).serialize();
if(q){pcs.push(q);}
}
if (pcs.length>0){query = pcs.join("&");}
}
jQuery.ajax({type: "POST", url: u, data: query, success: function
(msg) { if(t==':eval') eval(msg); else jQuery("#" + t).html
(msg); } });
}

> > > > Jose- Hide quoted text -
>
> - Show quoted text -

mdipierro

unread,
Aug 28, 2009, 11:15:19 AM8/28/09
to web2py-users
I would do something like this instead:

1) make sure all checkboxes have an ID

2) insert this in view
<script>
jQuery(document).ready(function() {
jQuery(':checkbox').change(function() {
var status;
if(jQuery(this).is(':checked') status='1'; else status='0';
ajax('{{=URL(r=request,f='yourcallback')}}/'+jQuery(this).attr
('id')+'/'+status,[],null);
});
});
</script>

then in controller

def yourcallback():
checkbox_id=request.args(0)
status=request.args(1)
... store the status of checkbox_id....
return None

mr.freeze

unread,
Aug 28, 2009, 7:37:57 PM8/28/09
to web2py-users
Seems like a lot of work to get the status of a checkbox but I guess
changing the web2py_ajax.html ajax function to use jQuery.serialize
wouldn't be truly backwards compatible since people have already
implemented workarounds such as this. Oh well. I think the best
option is to avoid the web2py_ajax.html ajax function use jQuery.ajax
instead as it can serialize form elements properly.

mdipierro

unread,
Aug 29, 2009, 4:23:10 AM8/29/09
to web2py-users
I disagree:

if(jQuery(this).is(':checked')

mr.freeze

unread,
Aug 29, 2009, 10:42:09 AM8/29/09
to web2py-users
My point is that the web2py_ajax.html ajax function behaves
differently than a normal submit, which is confusing.

mdipierro

unread,
Aug 29, 2009, 11:30:05 AM8/29/09
to web2py-users
I did not get your point then. Let me look into this more. I am
travelling this week end but I will look at this asap.

Massimo

mr.freeze

unread,
Sep 5, 2009, 2:31:09 PM9/5/09
to web2py-users
Did you get a chance to look at this? Summary:
The web2py_ajax.html ajax function behaves differently than a normal
submit (only noticeable on controls that have conditional postback
like checkbox). This fixes it and adds the ability to use jQuery
selectors ( if s is a string instead of a list of element IDs):
> > > > Seems like a lot of work to get the status of acheckboxbut I guess

mdipierro

unread,
Sep 5, 2009, 4:53:55 PM9/5/09
to web2py-users
Sorry I forgot. Will do it over the week end.
Reply all
Reply to author
Forward
0 new messages