Sure.

The table I use *department* and *rank* in (and also the one I perform 
insert/update on):

db.define_table('seafarer_experience',
    Field('user_id', db.auth_user, default=auth.user_id, readable=False, 
writable=False),
    Field('department', db.department, label='Department'),
    Field('rank', db.rank, label='Rank'),
    Field('company'),
    Field('vessel', db.vessel, label='Vessel type'),
    Field('date_from', 'date', label='Worked from', requires = 
IS_DATE(format='%d/%m/%Y'),
    Field('until_now', 'boolean', label='until now'),
    Field('date_to', 'date', label='Worked to', requires = 
IS_DATE(format='%d/%m/%Y')
)

db.seafarer_experience.department.requires=IS_IN_DB(db,'department.id','%(name)s',
 
orderby=db.department.id, zero='-- Choose department --')
db.seafarer_experience.rank.requires=IS_IN_DB(db,'rank.id','%(name)s',orderby=db.rank.name,
 
zero='-- Choose rank --')
db.seafarer_experience.vessel.requires=IS_IN_DB(db,'vessel.id','%(name)s',orderby=db.vessel.name,
 
zero='-- Choose vessel --')

Link to insert:

<a href="{{=URL('seafarer', 'create', vars={'c':'exp'})}}">Add experience 
now</a>

Insert form in *seafarer.py* controller:

if request.vars.c in ['edu', 'exp', 'img']:
    if request.vars.c == 'exp':
        response.view = 'seafarer/add_experience.html'
        add_experience = crud.create(db.seafarer_experience, 
next=(URL('seafarer', 'profile')), _class='formstyle')
        return dict(add_experience=add_experience)
    elif: ....
    elif: ....
else:
    redirect(URL('default', 'oh_bummer'))

*oh_bummer *is a test not-authorized view (it only displays an error 
message). *edu* and *img *vars represent other crud actions.


add_experience.html view:

{{=add_experience.custom.begin}}
    {{=add_experience.custom.widget.department}}
    {{=add_experience.custom.widget.rank.label}}

    <div class="w2p_fw">
        {{if request.vars.department:}}
            <select class="generic-widget" id="seafarer_experience_rank" 
name="rank">
                {{=XML(result)}}
            </select>
        {{else:}}
        {{=add_experience.custom.widget.rank}}
        {{pass}}
    </div>
    ....
    ....
{{=add_experience.custom.end}}

Link to update:

<a href="{{=URL('seafarer', 'update', args=exp.id, vars={'u':'exp'})}}">

Udate form in *seafarer.py* conroller:

if request.vars.u in ['edu', 'exp', 'img']:
    if request.vars.u == 'exp':
        response.view = 'seafarer/edit_experience.html'
        edit_experience = crud.update(db.seafarer_experience, 
request.args(0), deletable=False, next=(URL('seafarer', 'profile')))
        return dict(edit_experience=edit_experience)
    elif: ....
    elif: ....
else:
    redirect(URL('default', 'oh_bummer'))

edit_experience.html view:

{{=edit_experience.custom.begin}}
    {{=edit_experience.custom.widget.department}}
    {{=edit_experience.custom.widget.rank.label}}

    <div class="w2p_fw">
        {{if request.vars.department:}}
            <select class="generic-widget" id="seafarer_experience_rank" 
name="rank">
                {{=XML(result)}}
            </select>
        {{else:}}
        {{=edit_experience.custom.widget.rank}}
        {{pass}}
    </div>
    ....
    ....
{{=add_experience.custom.end}}

And that's basically it. There's no explicit form processing. I use 
web2py's CRUD and table definition validators.

When I insert data into *seafarer_experience *table -- I can choose any 
option from the *department* select box and *rank *is auto-populated every 
time.

When go to update form (to update the same table), *department* and *rank*are 
already selected, which is natural. But auto-populating does not work. 
That's what happens in the update form:

1. I select any department
2. The department I chose is not being selected and "zero" value is set 
 ("--Choose department--")
3. The rank select box looks empty, but code inspector shows it's not: 
inside the *rank *select box renders the *oh_bummer *view

So, I guess, the problem is somewhere between this

if request.vars.u in ['edu', 'exp', 'img']:
    ....
    ....
    ....
else:
    redirect(URL('default', 'oh_bummer'))

and passing *department *variable via ajax(). But if it's true, why does 
the insert form works fine and the update not? They're both generated the 
same way in the seafarer.py.

I'm really trying to write it all as simple as I can :)








On Sunday, June 23, 2013 2:30:49 AM UTC+2, Anthony wrote:
>
> I think we also need to see the code that creates and processes the form.
>
> On Saturday, June 22, 2013 4:53:51 PM UTC-4, lesssugar wrote:
>>
>> Anthony, here's more info.
>>
>> In my form, you need to choose a department to generate respective list 
>> of ranks. The tables involved:
>>
>> db.define_table('department',
>> Field('name', length = 30),
>> format=lambda r: r.name
>> )
>>
>> db.define_table('rank',
>> Field('department_id', db.department),
>> Field('name', length = 50),
>> format=lambda r: r.name
>> )
>>
>>
>> I reference the tables in my user profile table (user has i.a. department 
>> and rank).
>>
>> When user wants to insert data, the view generates a custom crud form 
>> (below) -- nothing fancy here. However, I need to modify the piece of code 
>> which deals with *rank *- to auto-populate it based on department chosen:
>>
>> {{=form.custom.begin}}
>>     {{=form.custom.widget.department}}
>>     {{=form.custom.widget.rank.label}}
>>     <div class="w2p_fw">
>>         {{if request.vars.department:}}
>>             <select class="generic-widget" id="seafarer_experience_rank" 
>> name="rank">
>>                 {{=XML(result)}}
>>             </select>
>>         {{else:}}
>>         {{=form.custom.widget.rank}}
>>         {{pass}}
>>     </div>
>>     ....
>> {{=form.custom.end}}
>>
>> So, when user displays the form, the *department *variable is not set 
>> (True) yet. In that case all ranks are being displayed in the select_2 
>> (else: ...). Then, when user chooses an option from select_1 (department), 
>> jQuery change() triggers and ajax() sends department variable to *populate 
>> *function. The variable is used in the query (my first post) to retrieve 
>> ranks connected with the department chosen, and send it back to the view as 
>> <option></option> tags -- {{=XML(result)}}.
>>
>> As I said - it works for inserting data. Does not when I try to update.
>>
>> I use the same HTML + web2py code as in the form code above for both 
>> insert and update forms.
>>
>> If I'm still being not clear enough, let me know. And thanks.
>>
>>
>> On Saturday, June 22, 2013 8:04:39 PM UTC+2, Anthony wrote:
>>>
>>> Sorry, it wasn't clear that it was failing upon change of select_1. It 
>>> might help to show more of the code that creates and displays the form, as 
>>> it is not quite clear how everything is working. In particular, I don't 
>>> quite get what that view code is doing and where it is used.
>>>
>>> Anthony
>>>
>>> On Saturday, June 22, 2013 1:55:18 PM UTC-4, lesssugar wrote:
>>>>
>>>> Yes, of course you're right, I guess I wasn't clear enough. The real 
>>>> problem is this: what if a user needs to change the value of select_1 in 
>>>> order to update their data? Then, depending on what they choose, select_2 
>>>> should still be auto-populated.
>>>>
>>>> I don't get why code which works for insert form fails when it comes to 
>>>> update. Can it be connected to the fact that the update form shows 
>>>> specific 
>>>> value of select_1? Not sure. But jquery change() should anyway spot the 
>>>> select change action and trigger ajax().
>>>>
>>>> On Saturday, June 22, 2013 7:39:05 PM UTC+2, Anthony wrote:
>>>>>
>>>>> $('#select_1').change(function()
>>>>>
>>>>> You're using a "change" event handler, so it will only fire when the 
>>>>> value of select_1 is changed. When the update form is first loaded, the 
>>>>> existing record's value for select_1 is shown, but there is no change 
>>>>> event 
>>>>> to trigger the retrieval of the select_2 values.
>>>>>
>>>>> Note, for an update form, it should be possible to populate select_2 
>>>>> on the server rather than via ajax, since you already have the value of 
>>>>> select_1.
>>>>>
>>>>> Anthony
>>>>>
>>>>> On Saturday, June 22, 2013 1:29:02 PM UTC-4, lesssugar wrote:
>>>>>>
>>>>>> I have 2 select boxes. I managed to auto-populate second select box 
>>>>>> based on value from the first one. All of the code below works just fine 
>>>>>> when I create new record - second select is being populated. However, 
>>>>>> when 
>>>>>> I try to update the same record, select_2 does not get populated, as if 
>>>>>> the 
>>>>>> *department* variable never reached the *populate* function. As a 
>>>>>> result, there's a view rendered within select_2 instead of 
>>>>>> <option></option> elements. This occurs only in the update form.
>>>>>>
>>>>>> The script passing *department *variable from select_1:
>>>>>>
>>>>>> <script>
>>>>>>     $('#select_1').change(function() {
>>>>>>         ajax('populate', ['department'], 'select_2');
>>>>>>     });
>>>>>> </script>
>>>>>>
>>>>>> *populate *function which uses "department" var to get respective 
>>>>>> data:
>>>>>>
>>>>>> def populate():
>>>>>>
>>>>>>     ranks = db(db.rank.department_id == 
>>>>>> request.vars.department).select(db.rank.id, db.rank.name, orderby=
>>>>>> db.rank.name)
>>>>>>
>>>>>>     result = ""
>>>>>>
>>>>>>     for r in ranks:
>>>>>>         result += "<option value='" + str(r.id) + "'>" + r.name + 
>>>>>> "</option>"
>>>>>>
>>>>>>     return XML(result)
>>>>>>
>>>>>> view:
>>>>>>
>>>>>> <div class="w2p_fw">
>>>>>>     {{if request.vars.department:}}
>>>>>>         <select class="generic-widget" id="seafarer_experience_rank" 
>>>>>> name="rank">
>>>>>>             {{=XML(result)}}
>>>>>>         </select>
>>>>>>     {{else:}}
>>>>>>         {{=form.custom.widget.rank}}
>>>>>>     {{pass}}
>>>>>> </div>
>>>>>>
>>>>>>
>>>>>>

-- 

--- 
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