Take the 2-minute tour ×

Request Summary:

I know FormPanel works with doPost(e).

But if I have a few formPanels and each of them need to work with different set of doPost(e)?

Since doPost(e) is fixed name, how to have a few different doPost(e) like doPost1(e), doPost(2), etc.

Same issue with createSubmitButton, since it automatically look for function doPost(e), how to guide each formPanel's submit to fire the right doPostX(e)

If above is not possible, does it mean each Project is limited to have only single doPost(e) function?


share|improve this question

2 Answers 2

The may problem of doPost and doGet functions is that you can only have one doGet and one doPost per project at most. This is due to the fact that these functions use shared ressources and this kind of functions is therefore shared among the functions of one project.

There are in fact two workarounds (at least I know and have tested only two of them) to use multiple doPost queries which do different things in one single project.

The simplest way (and the best) is to use different functions in a single doPost function, one for every task needing a doPost function. The trick here is that you need to add a hidden field in your forms that will help you differentiate between the different forms in your project.

Then you can add a "if()else if()else" block to select the right function depending of the value of the hidden field.

For example if you have two functions you can do:

function doGet(e){
  var app=UiApp.createApplication();
  some stuff;
  return app; 

function doPost(e){

  some stuff

 else if(e.parameter.form=="value2"){


 some other stuff

function function1(e,otherParameters){

 var app=UiApp.getActiveApplication();
 var panel=app.createVerticalPanel();
 var formPanel=app.createFormPanel();
 var button=app.createSubmitButton();
 var formHidden=app.createHidden().setName("form");
 other widgets;
 panel.add(other widgets);

 some stuff;

function function2(e,otherParameters){
 var app=UiApp.getActiveApplication();
 var panel=app.createVerticalPanel();
 var formPanel=app.createFormPanel();
 var button=app.createSubmitButton();
 var formHidden=app.createHidden().setName("value2");
 other widgets different from those in function1;
 panel.add(other widgets);

 some stuff different from what you have in function1;

You can also create another project (for example Project2) where you have a doPost function and deploy this project as a web app.

The idea is that you can then send the information from a given form to some urls using the setAction("url") method of the FormPanel. With this method you can send the content of your form to a web page that will handle your query. therefore, if you set the string value of this method to the url of your web app, you will send the content of a google-script form to this app. And this is this app that will use its doPost function to handle the query.

This option is a bit more difficult to develop and present the disadvantage of not currently handling Blobs from FileUpload at all.

Hope it will help you



share|improve this answer

Note: In the subroutines that doPost() transfers control to, be sure to use the UiApp.getActiveApplication() method. In my haste, I spent more time than I care to admit because I was invoking the UiApp.createApplication() method in each of these subroutines.


Here is working code that demonstrates a multiple page form, i.e. it does the initial doGet() and then lets you advance back and forth doing multiple doPost()'s. All this is done in a single getForm() function called by both the standard doGet() and the doPost() functions.

// Muliple page form using Google Apps Script

function doGet(eventInfo)  {return GUI(eventInfo)};
function doPost(eventInfo) {return GUI(eventInfo)};

function GUI (eventInfo) {
  var n = (eventInfo.parameter.state == void(0) ? 0 : parseInt(eventInfo.parameter.state));
  var ui = ((n == 0)? UiApp.createApplication() : UiApp.getActiveApplication());
  var Form;
    case -1: {
      Form = ui.createFormPanel().add(ui.createHTML("<H3>Exited by submission of form "+eventInfo.parameter.formId+"</h3>"));
    } break;
    case 0: {
      Form = getForm(eventInfo,n); // Use identical forms for demo purpose only
    } break;
    case 1: {
      Form = getForm(eventInfo,n); // In reality, each form would differ but...
    } break;
    default: {
      Form = getForm(eventInfo,n) // each form must abide by (implement) the hidden state variable
    } break;
  return ui.add(Form);

function getForm(eventInfo,n) {
  var ui = UiApp.getActiveApplication();

  // Increment the ID stored in a hidden text-box
  var state = ui.createTextBox().setId('state').setName('state').setValue(1+n).setVisible(true).setEnabled(false);
  var H1 = ui.createHTML("<H1>Form "+n+"</H1>");
  var H2 = ui.createHTML(
    "<h2>"+(eventInfo.parameter.formId==void(0)?"":"Created by submission of form "+eventInfo.parameter.formId)+"</h2>");

  // Add three submit buttons to go forward, backward and to validate the form
  var Next = ui.createSubmitButton("Next").setEnabled(true).setVisible(true);
  var Back = ui.createSubmitButton("Back").setEnabled(n>1).setVisible(true);
  var Stay = ui.createSubmitButton("Stay").setEnabled(n>0).setVisible(true);
  var Exit = ui.createSubmitButton("Exit").setEnabled(n>0).setVisible(true);
  var Buttons = ui.createHorizontalPanel().add(Back).add(Stay).add(Next).add(Exit);
  var Body = ui.createVerticalPanel().add(H1).add(H2).add(state).add(Buttons).add(getParameters(eventInfo));
  var Form = ui.createFormPanel().setId((n>0?'doPost[':'doGet[')+n+']').add(Body);

  // Add client handlers using setText() to adjust state prior to form submission
  // NB: Use of the .setValue(val) and .setValue(val,bool) methods give runtime errors!
  var onClickStayHandler = ui.createClientHandler().forTargets(state).setText(''+(parseInt(n)));
  var onClickBackHandler = ui.createClientHandler().forTargets(state).setText(''+(parseInt(n)-1));
  var onClickExitHandler = ui.createClientHandler().forTargets(state).setText('-1');

  // Add a client handler executed prior to form submission
  var onFormSubmit = ui.createClientHandler()
  .forTargets(state).setEnabled(true) // Enable so value gets included in post parameters

  return Form;

function getParameters(eventInfo) {
  var ui = UiApp.getActiveApplication();
  var panel = ui.createVerticalPanel().add(ui.createLabel("Parameters: "));
  for( p in eventInfo.parameter)
    panel.add(ui.createLabel(" - " + p + " = " + eventInfo.parameter[p]));
  return panel;

The code uses a single "hidden" state (here visualized in a TextBox) and multiple SubmitButton's to allow the user to advance forward and backward through the form sequence, as well as to validate the contents of the form. Three extra SubmitButton's are "rewired" using ClientHandler's that simply modify the hidden state prior to form submission.


  • In any given form, you can actually have as many buttons as your application requires; i.e. more or less than the four that are demonstrated here. The Stay button in this example effectively posts the current status and reloads the same form. Note that functionally this is equivalent to doing a server handler. Potential uses for this would be eg. to load default data or to save the existing data from/to a database/worksheet.

  • Note the use of the .setText(value) method in the client handler's. Using the Chrome browser I get weird runtime errors if I switch to either of the TextBox's .setValue(value) or .setValue(value, fireEvents) methods.

  • I tried (unsuccessfully) to implement this logic using a Script Property instead of the hidden TextBox. Instead of client handlers, this requires using server handlers. The behavior is erratic, suggesting to me that the asynchronous server-side events are occurring after the form submission event.

share|improve this answer

Your Answer


