If you benefit from web2py hope you feel encouraged to pay it forward by contributing back to society in whatever form you choose!

Uploading Files With Ajax

Download the jQuery plugin from jquery.form.js into static folder

put this above at the very beginning, first line, of your .html file or in the header of layout.html

   {{response.files.append(URL(r=request,c='static',f='jquery.form.v2.43.js'))}}

Create forms as usual (see: web2py book) and just add the following somewhere:

   <script type='text/javascript'>
  //<!--
        jQuery('document').ready(function() {
        jQuery('form').ajaxForm({dataType: 'script', // <-- like the ':eval' target in ajax() function
                     url: "{{=URL('user_picture_form')}}" // <-- put form controller action here
                     });
    });
                         //-->
</script>

Read documentation: jQuery.form home page

Example Application

This application allows users (without authentication) associate images to registered users. And updates the list by ajax without reloading the entire page after each submission.

The model:

db.define_table('user_pictures',
                Field('user', db.auth_user, unique=True, represent=lambda id: '%s %s ' %( db.auth_user(id).first_name, db.auth_user(id).last_name)),
                Field('picture', 'upload', requires=IS_IMAGE()))
db.user_pictures.user.requires=IS_IN_DB(db,'auth_user.id', '%(first_name)s %(last_name)s', zero=T('choose one'))

Add 2 action to default.py controller:

def user_picture_list():
    rows = db(db.user_pictures.id>0).select()
    return dict(rows=rows)

def user_picture_form():
    form = SQLFORM(db.user_pictures)
    if form.accepts(request.vars):
       response.flash='Thanks for filling the form'
       return XML('ajax("%s",[],"pic_list");' % URL('user_picture_list.load'))
    elif form.errors:
        response.flash='Fill the form correctly'
    else:
        response.flash='Please, fill the form'

    return dict(form=form)

The full index.html:

{{response.files.append(URL(r=request,c='static',f='jquery.form.v2.43.js'))}}
{{extend 'layout.html'}}

<h1>{{=T("Change the user's image!")}}</h1>

<div class='ez-wr'>
  <p>
    This is the list: it will be updated when you submit a new image.
    </p>
  <div class='ez-box' id='pic_list'>
    {{=LOAD('default', 'user_picture_list.load', ajax=False)}}
  </div>
</div>
<div class='ez-wr'>
  <p>
    Upload a new image below!
  </p>
  <div class='ez-box'>
    {{=LOAD('default','user_picture_form.load', ajax=False)}}
  </div>
</div>

user_picture_list.load:

    <div class='ez-wr'>
     {{for r in rows:}}
     <div class="ez-wr">
       <div class="ez-fl ez-negmr ez-50">
     {{user = db.auth_user(r.user)}}
     {{="%s %s" % (user.first_name,user.last_name)}}
       </div>
       <div class="ez-last ez-oh">
     {{=IMG(_src=URL(f='download',args=[r.picture]))}}
       </div>
     </div>
     {{pass}}
   </div>

user_picture_form.load:

{{=form}}
<script type='text/javascript'>
  //<!--
    jQuery('document').ready(function() {
        jQuery('form').ajaxForm({dataType: 'script',
                 url: "{{=URL('user_picture_form')}}"
                 });
});
                     //-->
</script>

Related slices

Comments (7)

  • Login to post



  • 0
    michelecomitini 12 years ago
    @dalf I need more info to help. Check if you don't have some javascript conflicting packages. The order of javascript loading is important. Start to test with only the minimal requirements then try to add the remaining.

  • 0
    aleksdj 12 years ago
    doesn't work for me

  • 0
    ranjeevhs 13 years ago
    First of all this is a nice slice. Got it to work but the response.flash or even session.flash doesn.t work upon upload.

  • 0
    richard 13 years ago
    Very tasty slice, Michele. Thanks. However, two issues came up. First, after submitting the form, the component isn't getting updated so I still see the input. This leads to multiple submission problems. The other issue is more of a question -- why did you use return XML('ajax...') instead of providing a success function to the ajaxForm function?

  • 0
    richard 13 years ago
    I'm also curious about the jQuery('form').ajaxForm(...) statement. Shouldn't it be jQuery('#form').ajaxForm(...)?

  • 0
    richard 13 years ago
    OK, I think I got it: the jQuery('form').ajaxForm(...) should probably look like this:
    
    jQuery('#form').ajaxForm({
          dataType: 'script'
        , url: "{{=URL('user_picture_form')}}"
        , target: "#ez-box"
    })
    
    The target will update the input form after submission.

  • 0
    ariel 13 years ago
    Good example....

Hosting graciously provided by:
Python Anywhere