Link to home
Start Free TrialLog in
Avatar of yltang52
yltang52Flag for Taiwan, Province of China

asked on

Google app engine and Ajax: is it possible to submit data with regular html POST and then update the content div with Ajax?

This problem has bothered me for weeks. I have an html page which contains many forms for users to submit separately. The submitted data contains texts, images, and html files, and each form submits different data. I would like to submit the forms using the regular html POST method because submitting files and various form data via Ajax could be problematic, unless there is a good solution for that.

My questions:
(a) Does Ajax accept html POST? If not, then I have to submit data via Ajax. Further problems: 1) I have to deal with file upload, 2) I have to write an Ajax function for each form (if there are 30 forms, I have to write 30 functions?).
(b) Can an Ajax function get the server response and then update the content where it resides?

To be more specific, in the following, I used hypothetical ideas:
(1) The "content" division actually encloses the whole thing. The purpose is to display the returned data so that users may see what they have entered.
(2) I add class="content" in each <input ...> tag
(3) The following works for <a href= ...>,

$(document).ready(function() {
  $('a.content').click(function() {
    var url = $(this).attr('href');
    $('#content').load(url);
    return false
  });
});

Open in new window


so I tried to modify it to suit the <form ...>

The contents of "form.html" (the response is also this html except that the values of the template variables will be inserted before rendering):

<div id="content">
<form action="/url" method="post" class="..." enctype=multipart/form-data>
  <input type="..." name="..." value={{variable1}} ...>

   ... <!-- various data and data types plus template codes to display the response -->

  <input type="submit" name="submit" class="content">
</form>

<!-- a lot of forms -->

<form action="/url" method="post" class="..." enctype=multipart/form-data>
  <input type="..." name="..." value={{variable2}} ...>
  ...
  <input type="submit" name="submit" class="content">
</form>

<script>
  $(document).ready(function() {
    $('input.content').click(function() {
      var form = $(this).attr('url');
      $('#content').load(url);
      return false;
    });
  });
</script>
</div>

Open in new window

Avatar of yltang52
yltang52
Flag of Taiwan, Province of China image

ASKER

Increase points to 500.
Avatar of David Johnson, CD
you need to break your page into separate areas. possibly with using iframes going into div's. Each form goes into a separate div so when you call a postback only that area gets updated.
With ajax this is done using update panels http://ajax.net-tutorials.com/controls/updatepanel-control/
@veoofa, thanks for your suggestions. As I don't use ASP, the link you provided may not work for me (I mainly use JQuery). To be more specific, I know 2 cases of how to use Ajax to update a certain div:

1) for a link as in the following, when the "someName" link is clicked, the Ajax function listed in my question would then update the "content" div:

<a href="/someUrl" class="content">someName</a>
...
<div id="content"></div>
...
$(document).ready(function() {
  $('a.content').click(function() {
    var url = $(this).attr('href');
    $('#content').load(url);
    return false
  });
});

Open in new window


2) for the following form: it submits data via Ajax, and the "content" div that gets updated is outside of the form.

<form method="" action="">
<input type="text" name="message" size="60" /><br />
<input type="button" value="submit" onclick="return addMsg()" />
</form>
...
<div id="content"></div>
...
function addMsg() {
    var message = $('input[name=message]').val();
    $.ajax({
        type: "POST",
        url: "/chat",
        data: {'message': message},
        cache: false,
        success: function(returndata){
            $("#content").html(returndata);
        }
    });
}

Open in new window


The above two cases has two things in common: the "content" div is empty and it is separated from the button (or whatever) that triggers the Ajax.

But my case is that I have a "content" div in a page and it contains a number of forms. When one of the form is submitted, the response is actually the content itself with the form attribute "value" updated. This is illustrated in my question by {{variable1}} and {{variable2}}. They are substituded with actual values by the Django template system.

All I want to do is to use Ajax to update the "content" div, and the button (or whatever) that triggers the Ajax is also in "content" div. Can this be done? Thanks again for your help.
Hi yltang52,

First let me understand the question -
1) You have one form on form.html which displays the content
2) You have several other forms where user can enter the data
3) Once user enters the data and submits the form you want to display the returned content in content div.
4) You don't want to submit the whole page and want to do it using AJAX.

Now answering few of your questions -
* Yes we can do post using AJAX below are the links to do that
   1. Using XMLHttp object (http://www.javascriptkit.com/dhtmltutors/ajaxgetpost2.shtml)
   2. Using JQuery (http://api.jquery.com/jQuery.post/)
* Yes you can get the AJAX response (shown how to get it in above example) and using javascript you can replace the contents of any div with the response.

I hope this will give you some start. Please validate my understanding and also go through the links and let me know if they are helpful.

Also i would like to know your experience level in using AJAX and JavaScript.

Regards,
Anurag
@anuragal: thanks for pointing out the directions. Your understandings are correct. I am very new to AJAX and JavaScript and I am trying to catch up. I studied the JQuery solution and made a complete but "reduced" case listed in the following. The program didn't work and I noticed that Ajax actually submits a "GET" request, instead of "POST". What was the problem?

app.yaml:
application: test
version: 1
runtime: python27
api_version: 1
threadsafe: true
  
handlers:
- url: /.*
  script: main.app

Open in new window


main.py
# -*- coding: utf-8 -*-
#!/usr/bin/env python2.7

import webapp2
import os
from google.appengine.ext.webapp import template
from google.appengine.ext import db

class MainPage(webapp2.RequestHandler):
    def get(self):
        render(self, 'base.html', {})

class Form(webapp2.RequestHandler):
    def get(self):
        render(self, 'form.html', {})
    def post(self):
        obj = Data()
        obj.name = self.request.get('name')
        obj.file = self.request.get('file')
        try:
            obj.put()
            template_values = {'message': 'Uploaded'}
        except:
            template_values = {}
        render(self, 'form.html', template_values)

def render(handler, infile, template_values):
    path = os.path.join(os.path.dirname(__file__), infile)
    handler.response.out.write(template.render(path, template_values))
#enddef

class Data(db.Model):
    name = db.StringProperty()
    file = db.BlobProperty()

app = webapp2.WSGIApplication([
    ("/form", Form),
    ("/", MainPage)],
    debug=True)

Open in new window


base.html:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>jQuery Test</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link type="text/css" rel="stylesheet" href="/static/css/base.css" />
<script type="text/javascript" src="/static/js/jquery-1.8.2.min.js"></script>
</head>
<body>

<!-- A lot of other stuff -->

<div id="content">
<a href="/form" class="content">Click me</a>
</div>

<!-- A lot of other stuff -->

<script>
  $(document).ready(function() {
      $('a.content').click(function() {
          var url = $(this).attr('href');
          $('#content').load(url);
          return false;
      });
  });
</script>

</body>
</html>

Open in new window


form.html:
<div id="formContent">
<form  id="submitForm" action="/form" enctype="multipart/form-data">
  Name: <input type="text" name="name" /><br /><br />
  File: <input type="file" name="file" />{{ message }}<br />
        <input type="submit" value="Submit" />
</form>

<script>
 $("#submitForm").submit(function(event) {
    /* stop form from submitting normally */
    event.preventDefault();      
    /* get some values from elements on the page: */
    var $form = $(this),
        term = $form.find('input[name="name"]').val(),
        url = $form.attr('action');
    /* Send the data using post and put the results in a div */
    $.post(url, {name: term},
      function(data) {
          var content = $(data).find('#content');
          $("#formContent").empty().append(content);
      }
    );
  });
</script>

</div>

Open in new window

The above program is too complex to understand.

What I will suggest you to make a sample application with a simple form with 2-3 text boxes. And try to submit (POST) this form using AJAX. Once this is done then apply same logic in your current application.

This sample application will help you in understanding the basic concepts of AJAX using Jquery.

Regards,
Anurag
ASKER CERTIFIED SOLUTION
Avatar of Anurag Agarwal
Anurag Agarwal
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks Anurag. I changed the script in "form.html" as follows, but I found that the request was still "GET", not "POST".

<script>
 $("#submitForm").submit(function(event) {
    /* stop form from submitting normally */
    event.preventDefault();      
    /* get some values from elements on the page: */
    var $form = $(this),
        term = $form.find('input[name="name"]').val(),
        url = $form.attr('action');
    /* Send the data using post and put the results in a div */
    $.post(url, $("#submitForm").serialize(),
      function(data) {
          var content = $(data).find('#content');
          $("#formContent").empty().append(content);
      }
    );
  });
</script>

Open in new window

This is not pure POST, but you can add the variable you want to add in this post request.

Anurag