我可以开发向导应用程序(按顺序提交表单)吗?

时间:2013-07-15 11:31:35

标签: google-apps-script

根据我的理解,只有一个doGet()可以在Google Apps脚本应用程序中触发唯一的doPost()。

我想执行 软件发布商系统 ,用户上传文件或填写表单中的修订信息,然后将提交推送到下一步。最后一页将显示输入信息,向人发送电子邮件并完成所有操作。

但是如何在推送提交按钮后输入下一个表单?

我尝试过在 doPost() 中创建第2步和第3步表单的方法,并使用 try ... catch 以不同的步骤形式触发当前步骤,如下面的代码。 (因为任何步骤都不能通过非前一步骤抛出回调项,所以它会产生异常)

它运作良好,但我认为它不会让人感到愚蠢。有更好的解决方案吗?谢谢,拜托。

//---------------------------------------------------------------------------
function doGet(e)
{
  var app = UiApp.createApplication().setTitle("AP Publisher");    

  createFileUploadForm(app);

  return app;
}
//---------------------------------------------------------------------------
function doPost(e) 
{  
  var app = UiApp.getActiveApplication();                 

  try {
    // 2nd step form
    var fileBlob = e.parameter.thefile;         

    createRevisionForm();
  }
  catch(error) {
    try {
      // 3rd step form
      createConfirmForm(e);
    }
    catch(error2) {
      //Complete       
      sendMail(e);            
      modifySitePageContent(e);            
      saveHistoryFile(e);   

      showConfirmedInfo(e);
    }
  }

  return app;    
}

3 个答案:

答案 0 :(得分:0)

我认为在您的doGet功能中使用3个(或更多)不同的面板与您需要的所有项目并使用它们的可见性会更简单。

首先只有第一个面板可见,并且根据用户输入(使用客户端处理程序来处理)显示下一个面板(并最终隐藏第一个面板)。

最后,提交按钮将调用doPost并从doGet获取所有数据。

答案 1 :(得分:0)

此答案完全从create a new page in a form dynamically, based on data of the prev. page复制。

使用UiApp服务,您有一个doGet()和一个doPost()功能......但是这里有一种扩展它们以支持动态多部分表单的方法。 (示例代码来自this answer。)

您的doGet()只是构建表单的第1部分。但是,在表单中,您需要通过名称标识表单,如下所示:

  var form = app.createFormPanel().setId("emailCopyForm");

然后,doPost()将根据提交的表单将后期操作的处理转移到不同的功能。见下文。 (还包括:reportFormParameters (),一个默认处理程序,它将显示表单部分收集的所有数据。)

/**
 * doPost function with multi-form handling. Individual form handlers must
 * return UiApp instances.
 */
function doPost(eventInfo) {
  var app;
  Logger.log("Form ID = %s", eventInfo.parameter.formId);
  // Call appropriate handler for the posted form
  switch (eventInfo.parameter.formId) {
    case 'emailCopyForm':
      app = postEmailCopyForm(eventInfo);
      break;
    default:
      app = reportFormParameters (eventInfo);
      break;
  }
  return app;
}

/**
 * Debug function - returns a UiInstance containing all parameters from the
 * provided form Event.
 *
 * Example of use:
 * <pre>
 *     function doPost(eventInfo) {
 *       return reportFormParameters(eventInfo);
 *     }
 * </pre>
 *
 * @param {Event} eventInfo Event from UiApp Form submission
 *
 * @return {UiInstance}
 */
function reportFormParameters (eventInfo) {
  var app = UiApp.getActiveApplication();
  var panel = app.createVerticalPanel();
  panel.add(app.createLabel("Form submitted"));
  for (var param in eventInfo.parameter) {
    switch (param) {
      // Skip the noise; these keys are used internally by UiApp
      case 'lib':
      case 'appId':
      case 'formId':
      case 'token':
      case 'csid':
      case 'mid':
        break;

      // Report parameters named in form
      default:
        panel.add(app.createLabel(" - " + param + " = " + eventInfo.parameter[param]));
        break;
    }
  }
  app.add(panel);
  return app;
}

要生成每个表单部分,后续表单处理程序可以使用前面部分中检索的数据动态地将新的Form对象添加到ui。

答案 2 :(得分:0)

首先是我对莫格斯达的帽子。他的帖子在黑暗记录的路径中引导我,这引导我来到这里。 Here is some working code 它演示了一个多页面形式,即它执行初始doGet(),然后让您来回前进多个doPost()。所有这些都是在标准getForm()doGet()函数调用的单个doPost()函数中完成的。

// 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;
  switch(n){
    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 Validate = ui.createSubmitButton("Validate").setEnabled(n>0).setVisible(true);
  var Buttons = ui.createHorizontalPanel().add(Back).add(Validate).add(Next);
  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 onClickValidateHandler = ui.createClientHandler().forTargets(state).setText(''+(parseInt(n)));
  var onClickBackHandler = ui.createClientHandler().forTargets(state).setText(''+(parseInt(n)-1));
  Validate.addClickHandler(onClickValidateHandler);
  Back.addClickHandler(onClickBackHandler);

  // 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
  .forTargets(Body).setStyleAttribute("backgroundColor","#EEE");    
  Form.addSubmitHandler(onFormSubmit);

  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;
}

代码使用单个“隐藏”状态(此处在TextBox中可视化)和多个SubmitButton以允许用户在表单序列中前后前进,以及验证表单的内容。两个额外的SubmitButton使用ClientHandler进行“重新布线”,只需在表单提交之前修改隐藏状态。

备注

  • 请注意在客户端处理程序中使用.setText(value)方法。使用Chrome浏览器,如果我切换到TextBox的{​​{1}}或.setValue(value)方法,我会收到奇怪的运行时错误。

  • 我尝试(不成功)使用.setValue(value, fireEvents)而不是隐藏的TextBox来实现此逻辑。这需要使用服务器处理程序,而不是客户端处理程序。行为不稳定,向我建议异步服务器端事件发生在表单提交事件之后。