Update ...

I found one problem: when I was dynamically adding form fields as html 
elements, I wasn't adding them as field objects to the form object on the 
postback so w2p didn't know about the fields for validation.

But I still must be confused how components work.  I load the form but the 
submit action reloads the entire page and therefore does not process the 
form.  What am I missing? ...

Action:

def send_msg():
    return dict()


View:

{{extend 'layout.html'}}
<div id="send_msg_form">
    {{=LOAD('sendmsg','get_msg_vars',ajax=True)}}
</div>


Component:

def get_msg_vars():
    fields = []
    fields.append(db.msg.msg_typ)
    if request.vars['msg_typ']:
        db.msg.msg_typ.default = request.vars['msg_typ']
        msg_typ = db.msg_typ(request.vars['msg_typ'])
        for var in msg_typ.msg_typ_vars:
            msg_typ_var_lbl = ' '.join(x.capitalize() for x in 
var.split('_'))
            fields.append(Field(var, label=msg_typ_var_lbl, 
requires=IS_NOT_EMPTY()))
    form=SQLFORM.factory(*fields)
    mt = form.element(_name='msg_typ')
    mt['_onchange'] = XML("ajax('get_msg_vars', ['msg_typ'], 
'send_msg_form');")
    if form.accepts(request,session):
        response.flash="form accepted"
    elif form.errors:
        response.flash="form is invalid"
    else:
        response.flash="please fill the form"
    return form


On Sunday, August 11, 2013 8:37:15 AM UTC-4, Michael Beller wrote:
>
> Thanks Derek,
>
> I've tried a few approaches and can't get a good scenario to work.
>
> If I add an onchange event using:
>     form=SQLFORM(db.msg, fields=['msg_typ'])
>     mt = form.element(_name='msg_typ')
>     mt['_onchange'] = XML("ajax('get_msg_vars', ['msg_typ'], 
> 'send_msg_form');")
>
> I then added the div to the form using:
>     dv = DIV('', _id='send_msg_form')
>     mtvars = form.element(_id='msg_msg_typ__row')
>     mtvars.append(dv)
>
> and then have the function get_msg_vars retrieve the list:string and add 
> the input fields to the div, I can't get the form to validate the fields.  
>
> I tried also tried using a LOAD component for the entire form but then the 
> onchange event doesn't work.  This was my alternate approach and it almost 
> works - you have to hit submit for the form to update:
>
> def send_msg():
>     return dict(form=LOAD(url=URL(r=request,f='get_msg_vars.load'),
>         ajax=True, target='send_msg_form'))
>
> def get_msg_vars():
>     fields = []
>     fields.append(db.msg.msg_typ)
>     if request.vars['msg_typ']:
>         db.msg.msg_typ.default = request.vars['msg_typ']
>         msg_typ = db.msg_typ(request.vars['msg_typ'])
>         for var in msg_typ.msg_typ_vars:
>             msg_typ_var_lbl = ' '.join(x.capitalize() for x in 
> var.split('_'))
>             fields.append(Field(var, label=msg_typ_var_lbl, 
> requires=IS_NOT_EMPTY()))
>     form=SQLFORM.factory(*fields)
>     mt = form.element(_name='msg_typ')
>     mt['_onchange'] = XML("ajax('get_msg_vars', ['msg_typ'], 
> 'send_msg_form');")
>     if form.accepts(request.vars):
>         response.flash = 'ok' 
>         return dict(message="Hello %s" % form.vars)
>     return dict(form=form)
>
> I read some other posts that indicate there may be problems with the 
> hidden form fields that are generated if I try to replace the entire form 
> using ajax and the load as above.
>
> My only other option that I can think of is to not use ajax or a component 
> and recreate the form each postback but this would require setting the 
> msg_type to read only and having a reset button.  I'm going to try that 
> next unless anybody has a better idea.
>
> Is there something I'm missing about using ajax/load to dynamically add 
> fields to the form?
>
> Thanks.
>
> On Monday, August 5, 2013 7:00:17 PM UTC-4, Derek wrote:
>>
>> Rig up the onchange of the message type dropdown to the load function... 
>>
>> On Monday, August 5, 2013 1:00:45 PM UTC-7, Michael Beller wrote:
>>>
>>> I have a requirement to create a message based on the user selecting a 
>>> message type.  Each message type has a fixed text component and a set of 
>>> zero, one, or more variable components.
>>>
>>> Ideally, I'd like the user to select the message type from a list and 
>>> have the form dynamically display zero, one, or more fields for entering 
>>> each variable component without posting back the entire page.  I've 
>>> researched LOAD and Ajax options in the book, along with using a field type 
>>> of list:string, but I haven't defined a good approach.  I've also read 
>>> about the conditional fields but not how to have a dynamic set of 
>>> conditional fields.
>>>
>>> Worst case, I could just postback the form and display a page with the 
>>> new form for that message type (and make the message type read only).
>>>
>>> Any ideas?  Thanks.
>>>
>>> Here is the base model ...
>>>
>>> db.define_table('msg_typ',
>>>     Field('msg_typ_id'),
>>>     Field('msg_typ_name'),
>>>     Field('msg_typ_body'),
>>>     Field('msg_typ_vars', type='list:string'),
>>>     format='%(msg_typ_name)s',
>>>     migrate=True)
>>>     
>>> db.define_table('msg',
>>>     Field('msg_typ', type='reference msg_typ'),
>>>     Field('msg_vars', type='list:string'),  # ideally, this would be a 
>>> dictionary with the vars from the msg_typ table along with their values
>>>     migrate=True)
>>>
>>>
>>>

-- 

--- 
You received this message because you are subscribed to the Google Groups 
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to