Don't use a form for the list items, just for the list header.

The following is meant to serve as an example, not as working code.

It represents the way I solved the problem.  No doubt there are better
ways but this does work.

The script is Jquery.  Strongly recommend you do lots of reading on
that site.
Also see The Book on javascript and ajax recipes.

You can probably accomplish the same thing using a component and the
LOAD command; The Book recommends this approach though I have not used
it.

Validate request.vars in the javascript callbacks!!

model:

db.define_table('stuff', Field('name'))
db.define_table('related', Field('myfield'), Field('stuff_id',
db.stuff))
# other details left out

controller:

def edit():
  ## so you can edit stuff
  form = SQLFORM(db.stuff, request.args[-1])
  #
  if form.process().success:
    redirect(URFL('edit')) # so you come back here
  ## outside the form
  new_related = INPUT(_type='text', _class='new_related_item',
_name='this', _id='that')
  show_related_rows = make_related_rows(request.args[-1]

  return dict(form=form,
    new_related=new_related,
    show_related_rows=show_related_rows)

def make_related_rows(id)

  related_rows = db(db.related.stuff_id==request.args[-1])select()
  if len(related_rows) == 0:
    return 'Nothing related to stuff'
  tbl = TABLE(TR(TH('Related')))
  for row in related_rows:
      tbl.append(TR(
        INPUT(_type='text', _class='related_input',
              _id =  str(row.id)
              _name = str(row.id)
        )
  return tbl


def new_related():
  # here will be your code to parse request.vars.name,
  # and request.vars.field_id
  # and insert stuff in the database
  # hint: use validate_and_insert
  # make sure field_id is an integer
  # rebuild the show_related_rows variable
  # return it

  return '$('#related_rows').html(show_related_rows)

def edit_related():
  # parse request.vars and update the affected record
  # use validate_and_update

view
{{=form}}
{{=new_related}}
<div id="related_rows">
{{=show_related_rows}}
</div>
<input type="hidden", name="updated_related_text",
id="updated_related_text">
<input type="hidden", name="field_id", id="field_id">

<script>
$('.new_related_item').live('change', function(e){

  ajax(URL('new_related', ['this'], ':eval'),); //check out ajax
recipes in The Book
});
$('.related_input').live('change', function(e){
  $('updated_related_text').val(this.val)
  $('field_id').val(this.id)
  ajax(URL('edit_related'), [this.name, 'field_id' ], ':eval');
});
</script>



On Dec 5, 10:56 pm, Aaron Levin <[email protected]> wrote:
> Hi,
>
> I'm really enjoying the simplicity of Web2py. However, for the life of
> me, I cannot figure out a way to accomplish this without re-writing
> FORM/SQLFORM. So, I know I'm not understanding something :)
>
> I'm writing a small app to make lists. Each list has many "items". I'd
> like a user to be able to create a List, and the list may have as many
> items as needed. When the user creates a list, there is a form field
> for one item. When they "focus" or "blur" or interact with that item
> field, another one appears below, via ajax. They continue to add items
> until they're finished.
>
> What I cannot figure out is how to pass back the additional form field
> via ajax, or how to select (via ajax) the form itself.
>
> Here is my model:
>
> db.define_table('listy',
>         Field('title'),
>         Field('description','text'),
>         Field('created_on','datetime',default=request.now),
>         Field('created_by',db.auth_user, default=auth.user_id),
>         format='%(title)s')
>
> db.define_table('entry',
>         Field('listy_id',db.listy),
>         Field('item','string', length=144))
>
> And my basic controller stuff to create a list:
>
> @auth.requires_login()
> def create():
>     """create a new empty list"""
>     # form = crud.create(db.listy, next=URL('index'))
>     form = SQLFORM.factory(db.listy, db.entry,formstyle='divs')
>     if form.process().accepted:
>         id = db.listy.insert(**db.listy._filter_fields(form.vars))
>         form.vars.listy=id
>         id = db.entry.insert(**db.entry._filter_fields(form.vars))
>         response.flash = 'Success! Thanks!'
>     return dict(form=form)
>
> Any help is appreciated. Thanks so much!

Reply via email to