multiple forms components issues

69 views
Skip to first unread message

Richard

unread,
Jun 21, 2016, 10:27:45 AM6/21/16
to web2py-users
Hello,

I have a strange issue... I have 2 forms that get append to a page container as component with LOAD()...

If I use form alone, they worked properly (only loading single component). But if I append both forms (loading both at the same time), one of my forms don't work properly.

What happen is that the form that not work properly need to be submit twice in order  to recieve error message on empty form. Sometime the problem transfert from one form to the other like if it was the first or the last form that load (difficult to determine) which work properly. Is there a way to determine which components as finished to load first?

Also in order to insert a record, the form has to be submit twice because at first submit one of the field (even if filled up) is empty after form submission, and there is no error message displayed... I have to fill it up again and submit than the record get created.

Once I succeed in inserting a record, the form work properly for the other insertion, I mean I don't have to submit twice to get record inserted.

The other form don't get affected by the issue at all, meaning it is not affected by the other form dysfunctionning...

Both components forms are custom form. They have different formname : 

if form.process(formname='phone_number_form').accepted:

The _formkey appear to be different when I look to the page source...

Any pointer where this could coming from?

It would be a lot of code to analyse, that why I didn't pasted here...

Thanks

Richard

Anthony

unread,
Jun 21, 2016, 10:30:15 AM6/21/16
to web2py-users
Code please.

Richard

unread,
Jun 21, 2016, 10:51:07 AM6/21/16
to web2py-users
As you which!!

# Controllers
Form 1
def phone_numbers_form():
    """
    phone_numbers_form() allow to create/update/display phone(s) number(s).

    Args (vars):
        readonlyform: If set to "True" the function only display phones numbers in row, no create form and buttons
                      to modify add phone number is available.
        remove_phone_number_id: If phone number id is passed through url with this vars phone number specify id
                                record is deleted.
        request_modify_phone_id: The passed phone number with this vars will make the phone_numbers_form() to return
                                 an update form for the specified phone number id record.

    """
    user_id = None

    # To display only the phone numbers
    readonlyform = False
    if request.vars.readonlyform:
        if request.vars.readonlyform in ['True']:
            readonlyform = True

    if request.args(0) is not None:
        try:
            user_id = int(request.args(0))
        except:
            user_id = db(db.auth_user.username == request.args(0)).select(db.auth_user.id).first().id
    if user_id is None:
        user_id = auth.user_id
    if request.vars.remove_phone_number_id is not None:
        db(db.phone_number.id == int(request.vars.remove_phone_number_id)).delete()
    record_to_modify = request.vars.request_modify_phone_id
    phone_numbers = db(db.phone_number.user_id == user_id).select()
    db.phone_number.user_id.default = user_id
    db.phone_number.user_id.update = user_id
    if record_to_modify is None:
        buttons = [
            TAG.button(I('', _class='icon-ban-circle icon-large icon-white'), _type='button',
                       _onClick='web2py_component("%s","phone_number_component");' % URL(c='directory',
                                                                                         f='phone_numbers_form',
                                                                                         extension='load',
                                                                                         args=request.args(0)),
                       _class='btn btn-mini btn-inverse'),
            TAG.button((I('', _class='icon-ok icon-large icon-white'), CAT('  '), STRONG(T('Add'))), _type='submit',
                       _class='btn btn-mini btn-primary', _style='white-space: nowrap;')]
    else:
        buttons = [
            TAG.button(I('', _class='icon-ban-circle icon-large icon-white'), _type='button',
                       _onClick='web2py_component("%s","phone_number_component");' % URL(c='directory',
                                                                                         f='phone_numbers_form',
                                                                                         extension='load',
                                                                                         args=request.args(0)),
                       _class='btn btn-mini btn-inverse'),
            TAG.button((I('', _class='icon-ok icon-large icon-white'), CAT('  '), STRONG(T('Ok'))), _type='submit',
                       _class='btn btn-mini btn-primary')]
        # form.element(_type='submit')['_value'] = T('ok')
        # form.element(_type='submit')['_class'] = 'btn btn-mini pull-right'
    form = SQLFORM(db.phone_number, record=None if record_to_modify is None else int(record_to_modify),
                   buttons=buttons if readonlyform is False else None,
                   readonly=True if readonlyform is True else False,
                   _id='phone_number_form_id')
    if form.process(formname='phone_number_form').accepted:
        if record_to_modify is not None:
            response.flash = T('Successfully inserted')
        else:
            response.flash = T('Successfully updated')
        response.js = 'web2py_component("%(URL)s","phone_number_component");' % {'URL': URL(c='directory',
                                                                                            f='phone_numbers_form',
                                                                                            extension='load',
                                                                                            args=request.args(0))}
    elif form.errors:
        response.flash = T('Errors...')

    # -----------------------------------------------------------------------------
    # <script>
    #     $(document).ready(function() {
    #         var add_phone_number_translation = "{{=T('Add a phone number')}}"
    #         $("tr#input_new_phone_number").children().hide();
    #         $("tr#input_new_phone_number").append('<td colspan="3" id="new_phone_number"><button type="button" class="btn btn-small pull-right" onclick="$(\'tr#input_new_phone_number\').children().show(); $(\'td#new_phone_number\').hide();"><strong>' + add_phone_number_translation + '</strong></button></td>');
    #         });
    # </script>
    # What below is a replacement for the jQuery code above
    if readonlyform is False:
        controller_view_js = \
            common_functions.flash_message_from_js(tr_id='new_phone_number',
                                                   colspan='3',
                                                   button_text='Add a phone number',
                                                   flash_text='Please add your phone number...',
                                                   form_id='phone_number_form_id')
    else:
        controller_view_js = ''
    # -----------------------------------------------------------------------------

    return dict(phone_numbers=phone_numbers,
                form=form,
                controller_view_js=controller_view_js,
                readonlyform=readonlyform)


Form 2

def group_membership():
    if not auth.has_membership('admin'):
        redirect(URL(c='permission', f='not_authorized'))
    user_id = None
    if request.args(0) is not None:
        try:
            user_id = int(request.args(0))
        except ValueError:
            user_id = db(db.auth_user.username == request.args(0)).select(db.auth_user.id).first().id
    # if user_id is None:
    #     user_id = auth.user_id  # Extrêmement douteux...
    if request.vars.remove_membership_id is not None:
        db(db.auth_membership.id == int(request.vars.remove_membership_id)).delete()
    record_to_modify = request.vars.request_modify_membership_id
    memberships = db(db.auth_membership.user_id == user_id
                     ).select(db.auth_membership.ALL,
                              db.auth_group.ALL,
                              join=db.auth_group.on(db.auth_group.id == db.auth_membership.group_id),
                              orderby=db.auth_group.role_gui)
    db.auth_membership.user_id.default = user_id
    db.auth_membership.user_id.update = user_id
    # ------------------------------------------------------------------------------------------------------------------
    # We don't need all the user id to be present in the drop down as group selected should apply to only a single user
    # ------------------------------------------------------------------------------------------------------------------
    user_id_set = db(db.auth_user.id == user_id)
    db.auth_membership.user_id.requires = IS_IN_DB(user_id_set, 'auth_user.id', '%(first_name)s %(last_name)s (%(id)s)')
    # ------------------------------------------------------------------------------------------------------------------
    # ------------------------------------------------------------------------------------------------------------------
    # We don't need other user_X groups as the user can't be assign to other user group
    # ------------------------------------------------------------------------------------------------------------------
    groups_set = db(~db.auth_group.role.startswith('user_'))
    db.auth_membership.group_id.requires = IS_IN_DB(groups_set, 'auth_group.id', '%(role)s-%(description)s (%(id)s)')
    # ------------------------------------------------------------------------------------------------------------------
    if record_to_modify is None:
        buttons = [
            TAG.button(I('', _class='icon-ban-circle icon-large icon-white'), _type='button',
                       _onClick='web2py_component("%s","membership_component");' % URL(c='directory',
                                                                                         f='group_membership',
                                                                                         extension='load',
                                                                                         args=request.args(0)),
                       _class='btn btn-mini btn-inverse'),
            TAG.button((I('', _class='icon-ok icon-large icon-white'), CAT('  '), STRONG(T('Add'))), _type='submit',
                       _class='btn btn-mini btn-primary', _style='white-space: nowrap;')]
    else:
        buttons = [
            TAG.button(I('', _class='icon-ban-circle icon-large icon-white'), _type='button',
                       _onClick='web2py_component("%s","membership_component");' % URL(c='directory',
                                                                                         f='group_membership',
                                                                                         extension='load',
                                                                                         args=request.args(0)),
                       _class='btn btn-mini btn-inverse'),
            TAG.button((I('', _class='icon-ok icon-large icon-white'), CAT('  '), STRONG(T('Ok'))), _type='submit',
                       _class='btn btn-mini btn-primary')]
        # form.element(_type='submit')['_value'] = T('ok')
        # form.element(_type='submit')['_class'] = 'btn btn-mini pull-right'
    form = SQLFORM(db.auth_membership, record=None if record_to_modify is None else int(record_to_modify),
                   buttons=buttons, _id='membership_form_id')
    if form.process(formname='membership_form').accepted:
        if record_to_modify is None:
            response.flash = T('Successfully inserted')
        else:
            response.flash = T('Successfully updated')
        response.js = 'web2py_component("%(URL)s","membership_component");' % {'URL': URL(c='directory',
                                                                                          f='group_membership',
                                                                                          extension='load',
                                                                                          args=request.args(0))}
    elif form.errors:
        response.flash = T('Errors...')

    thead = THEAD(TR(TH(T('Role(s)'))))
    trs = []
    for r in memberships:
        if request.vars.request_modify_membership_id is not None and \
                r.auth_membership.id == int(request.vars.request_modify_membership_id):
            trs.append(TR(TD(form.custom.widget.group_id,
                             DIV(A(I('', _class='icon-ban-circle icon-large icon-white'),
                                   _class='btn btn-mini btn-inverse',
                                   _href=URL('group_membership', extension='load',
                                             args=request.args(0)), cid=request.cid),
                                 BUTTON(I('', _class='icon-ok icon-large icon-white'),
                                        _class='btn btn-mini btn-primary',
                                        _type='submit'),
                                 _class='pull-right'))))
        else:
            trs.append(TR(TD(T(r.auth_group.role_gui),
                             DIV(A(I('', _class='icon-edit icon-large'), _class='btn btn-mini',
                                   _href=URL('group_membership', extension='load', args=request.args(0),
                                             vars=dict(request_modify_membership_id=r.auth_membership.id)),
                                   cid=request.cid),
                                 A(I('', _class='icon-remove icon-large icon-white'), _class='btn btn-mini btn-danger',
                                   _href=URL('group_membership', extension='load', args=request.args(0),
                                             vars=dict(remove_membership_id=r.auth_membership.id)), cid=request.cid),
                                 _class='pull-right'))))
    if request.vars.request_modify_membership_id == None:
        trs.append(TR(TD(form.custom.widget.group_id,
                         SPAN(form.custom.widget.user_id, _style='display: none;'),  # There is an issue with this...
                                                                                     # NO form.vars.user_id available
                                                                                     # for update form!!
                         SPAN(form.custom.submit, _class='pull-right')), _id='input_new_membership'))
    memberships_table = TABLE(thead, TBODY(*trs), _class='table table-condensed table-hover')

    # -----------------------------------------------------------------------------
    # $(document).ready(function() {
    #     var add_membership_translation = '{{=T('Add membership')}}'
    #     $("tr#input_new_membership").children().hide();
    #     $("tr#input_new_membership").append('<td colspan="3" id="new_membership"><button type="button" class="btn btn-small pull-right" onclick="$(\'tr#input_new_membership\').children().show(); $(\'td#new_membership\').hide();"><strong>' + add_membership_translation + '</strong></button></td>');
    #     });
    # What below is a replacement for the jQuery code above
    controller_view_js = \
        common_functions.flash_message_from_js(tr_id='new_membership',
                                               colspan='3',
                                               button_text='Add membership',
                                               flash_text='Please select a role...',
                                               form_id='membership_form_id')
    # -----------------------------------------------------------------------------

    return dict(memberships_table=memberships_table, form=form, controller_view_js=controller_view_js)

Container page controller
@auth.requires_login()
def manage_users():
    if not auth.has_membership('manage_users'):
        redirect(URL(c='permission', f='not_authorized'))
    if request.args(0) is not None:
        try:
                user_id = int(request.args(0))
        except ValueError:
            user_id = db(db.auth_user.username == request.args(0)).select(db.auth_user.id).first().id
    else:
        user_id = None
        db.auth_user.address_id.requires = \
            IS_EMPTY_OR(IS_IN_DB(db, db.address.id, '%(address_code)s - %(door_number)s, %(street)s'))
        db.auth_user.initials.requires = \
            IS_EMPTY_OR(IS_NOT_IN_DB(db, 'auth_user.initials', error_message=T('Initials already exist!')))
        db.auth_user.password.requires = IS_EMPTY_OR(CRYPT(min_length=auth.settings.password_min_length,
                                                           error_message=T('too short')))

    for field in db.auth_user.fields:
        db.auth_user[field].readable = False
        db.auth_user[field].writable = False
    fields = (db.auth_user.first_name,
              db.auth_user.last_name,
              db.auth_user.address_id,
              db.auth_user.email,
              db.auth_user.initials,
              db.auth_user.title_fr,
              db.auth_user.title_en,
              db.auth_user.manager_id,
              db.auth_user.gender,
              db.auth_user.registration_key,
              db.auth_user.picture)
    for field in fields:
        field.readable = True
        field.writable = True
    db.auth_user.registration_key.requires = IS_EMPTY_OR(IS_IN_SET(['pending', 'disabled']))
    db.auth_user.registration_key.default = 'pending'
    buttons = [TAG.button((I('', _class='icon-ban-circle icon-large icon-white'), CAT('  '), STRONG(T('Cancel'))),
                          _type='button',
                          _onClick="javascript:void(history.go(-1))",
                          _class='btn btn-small btn-inverse'),
               TAG.button((I('', _class='icon-ok icon-large icon-white'), CAT('  '), STRONG(T('Update'))),
                          _type='submit',
                          _class='btn btn-small btn-primary')]
    form = SQLFORM(db.auth_user, record=user_id, buttons=buttons, formstyle=formstyle, separator=separator)
    if form.process(dbio=False).accepted:
        if user_id is None:
            session.flash = T('User created')
            form.vars.ceo = False
            form.vars.note = ''
            if form.vars.email is not None:
                form.vars.username = form.vars.email.split('@')[0]
            id = db.auth_user.insert(**{str(var): form.vars[var] for var in form.vars})
            user_id_role_exist = db(db.auth_group.role == 'user_%d' % id).count() == 1
            if user_id_role_exist is False:
                db.auth_group.insert(role='user_%d' % id, description='Individual user group user_ + user id',
                                     role_gui=form.vars.username)
            member_of_basic_access_group = \
                db((db.auth_membership.user_id == id) &
                   (db.auth_membership.group_id == db(db.auth_group.role == 'basic_access'
                                                      ).select(db.auth_group.id).first().id)
                   ).count() == 1
            if member_of_basic_access_group is False:
                db.auth_membership.insert(user_id=id,
                                          group_id=db(db.auth_group.role == 'basic_access'
                                                      ).select(db.auth_group.id).first().id)
            # Push new user into Redmine
            redmine_utility.push_active_user_into_redmine(db=db)
        else:
            session.flash = T('User updated')
            db(db.auth_user.id == user_id).update(**{str(var): form.vars[var] for var in form.vars})

        if form.vars.title_fr is not None and form.vars.title_fr != '' \
                and form.vars.title_en is not None and form.vars.title_en != '':
            common_functions.value_translation_update(en_field_name='title_en', fr_field_name='title_fr', form=form)
        if request.args(0) is not None:
            username = request.args(0)
        elif form.vars.username is not None:
            username = form.vars.username
        else:
            username = None
        redirect(URL(c='directory', f='employee', args=username))
    elif form.errors:
        response.flash = T('Form has error')
    else:
        response.flash = T('Please complete or update the form')
    return dict(form=form)





# View ".load"
Form 1
<strong>{{=T('Phone numbers')}}</strong>
{{=form.custom.begin}}
<table class="table table-condensed table-hover">
    <tbody>
        {{for phone_number in phone_numbers:}}
            <tr>
                {{if request.vars.request_modify_phone_id is not None and phone_number.id == int(request.vars.request_modify_phone_id):}}
                    <td>{{=form.custom.widget.phone_number_kind_id}}</td>
                    <td>{{=form.custom.widget.phone_number}}</td>
                    <td>
                        <span style="display: none;">{{=form.custom.widget.user_id}}</span>
                        {{=form.custom.widget.extension}}
                        <div class="pull-right">
                        {{=A(I('', _class='icon-ban-circle icon-white'), _class='btn btn-mini btn-inverse',
                             _href=URL('phone_numbers_form', extension='load', args=request.args(0)), cid=request.cid)}}
                        {{=BUTTON(I('', _class='icon-ok icon-white'), _class='btn btn-mini btn-primary', _type='submit')}}
                        </div>
                    </td>
                {{else:}}
                    <td>{{=db.phone_number_kind[phone_number.phone_number_kind_id].phone_number_kind}}</td>
                    <td>{{=phone_number.phone_number}}</td>
                    <td>
                        {{if phone_number.extension is not None and phone_number.extension != '':}}
                            ({{=phone_number.extension}})
                        {{pass}}
                        {{if readonlyform is False:}}
                            <div class="pull-right">
                            {{=A(I('',_class='icon-edit'), _class='btn btn-mini',
                                 _href=URL('phone_numbers_form', extension='load', args=request.args(0),
                                           vars=dict(request_modify_phone_id=phone_number.id)), cid=request.cid)}}
                            {{=A(I('',_class='icon-remove icon-white'), _class='btn btn-mini btn-danger',
                                 _href=URL('phone_numbers_form', extension='load', args=request.args(0),
                                           vars=dict(remove_phone_number_id=phone_number.id)), cid=request.cid)}}
                            </div>
                        {{pass}}
                    </td>
                {{pass}}
            </tr>
        {{pass}}
        {{if readonlyform is False:}}
            {{if request.vars.request_modify_phone_id == None:}}
                <tr id="input_new_phone_number">
                    <td>{{=form.custom.widget.phone_number_kind_id}}</td>
                    <td>{{=form.custom.widget.phone_number}}</td>
                    <td>{{=form.custom.widget.extension}}
                        <span style="display: none;">{{=form.custom.widget.user_id}}</span>
                        <span class='pull-right'>{{=form.custom.submit}}</span>
                    </td>
                </tr>
            {{pass}}
        {{pass}}
    </tbody>
</table>
{{=form.custom.end}}

<script>
    {{=XML(controller_view_js)}}
</script>



Form 2
<strong>{{=T('User membership')}}</strong>
{{=form.custom.begin}}
    {{=memberships_table}}
{{=form.custom.end}}

<script>
    {{=XML(controller_view_js)}}
</script>


Container page
{{extend 'layout_form.html'}}

    <div class="span4">
        <div class="thumbnail">
            <div>
                {{=form}}
            </div>
        </div>
    </div>
    {{if request.args(0) is not None:}}
        <div class="span6">
            <div class="thumbnail">
                <div>
                    {{=LOAD(c='directory', f='phone_numbers_form', extension='load',
                            args=request.args(0), ajax=True, target='phone_number_component')}}
                </div>
            </div>
        </div>
        {{if auth.has_membership('admin') and request.args(0) is not None:}}
            <div class="span6">
                <div class="thumbnail">
                    <div>
                        {{=LOAD(c='directory', f='group_membership', extension='load',
                                args=request.args(0), ajax=True, target='membership_component')}}
                    </div>
                </div>
            </div>
        {{pass}}
    {{pass}}




# modules JS generation snippet
def flash_message_from_js(tr_id, colspan, button_text, flash_text, form_id=None):
    """
    Set flash message with $.web2py.flash() so the flash message get fire in the right context
    Need this in view :

    <script>
        {{=XML(controller_view_js)}}
    </script>

    NOTE: We now generate this piece of JS from python to solve issue with quoting escape cause by to many single
          and double quotes. The code breaks when whe translate "Please fill out the form..." with
          "S'il vous plaît remplir le formulaire..." the single quote were not escape properly with the Javascript
          implementation.
    NOTE: The issue has multiple facet... Mainly the issue is related to the fact that we want to translate flash
          message and for this reason we need to generate JS at some level from python even if it only the content of
          a string variable. Then since we need to generating also HTML from Javascript it makes multiple level of
          abstraction and a lot of quoting... When you add over all that there is single quote using in the translated
          text and that we deal with byte (python str) and not unicode... That were you end up...

          :param colspan:
          :param tr_id:
          :param flash_text:
          :param button_text:
    """
    elements_to_be_added = \
        TD(TAG.button(STRONG(current.T(button_text).decode('utf8')),
                      _type='button',
                      _class='btn btn-small pull-right',
                      _onclick='$("tr#input_%s").children().show(); '
                               '$("td#%s").hide(); '
                               '$.web2py.flash("%s");' % (tr_id, tr_id, current.T(flash_text).decode('utf8'))),
           _colspan=colspan,
           _id=tr_id)

    controller_view_js = \
        '''$(document).ready(function() {
            if(!$('#%s .error').length) {
                $("tr#input_%s").children().hide();
                $("tr#input_%s").append('%s');
                }
            });''' % (form_id, tr_id, tr_id, elements_to_be_added)
    # -----------------------------------------------------------------------------
    return controller_view_js




You have everything...

Richard Vézina

unread,
Jun 21, 2016, 3:42:03 PM6/21/16
to web2py-users
Any clue?

--
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
---
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 web2py+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Massimo Di Pierro

unread,
Jun 23, 2016, 5:28:02 AM6/23/16
to web2py-users
Can you reproduce the problem with some simpler code? 
Any clue?

To unsubscribe from this group and stop receiving emails from it, send an email to web2py+unsubscribe@googlegroups.com.

Richard Vézina

unread,
Jun 23, 2016, 9:38:29 AM6/23/16
to web2py-users
Can try... But my guess is that it's cause by the "ifs" there must be some annoying thing happening cause of them... But when I look into the page source everything seems fine... I am suspecting something with javascript...

Richard

Any clue?

To unsubscribe from this group and stop receiving emails from it, send an email to web2py+un...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
---
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 web2py+un...@googlegroups.com.

Richard Vézina

unread,
Jun 23, 2016, 11:29:37 AM6/23/16
to web2py-users
Can't reproduce with this : 

def component_container():
    form = SQLFORM(db.auth_user)
    if form.process().accepted:
        response.flash = 'form accepted'
    elif form.errors:
        response.flash = 'form has errors'
    else:
        response.flash = 'please fill out the form'
    return dict(form=form)


def form1():
    form = SQLFORM(db.auth_group)
    if form.process(formname='form1').accepted:
        response.flash = 'form accepted'
    elif form.errors:
        response.flash = 'form has errors'
    else:
        response.flash = 'please fill out the form'
    return dict(form=form)


def form2():
    form = SQLFORM(db.auth_permission)
    if form.process(formname='form2').accepted:
        response.flash = 'form accepted'
    elif form.errors:
        response.flash = 'form has errors'
    else:
        response.flash = 'please fill out the form'
    return dict(form=form)


I will try later with custom form to see issue come from there...

Richard
Reply all
Reply to author
Forward
0 new messages