0

我正在尝试在 google app 上编写代码,但遇到了一个问题。例如,让我们考虑一下谷歌网站上的这个示例代码(链接在这里https://developers.google.com/apps-script/class_formpanel

 function doGet() {
 var app = UiApp.createApplication();
 var form = app.createFormPanel();
 var flow = app.createFlowPanel();
 flow.add(app.createTextBox().setName("textBox"));
 flow.add(app.createListBox().setName("listBox").addItem("option 1").addItem("option 2"));
 flow.add(app.createSubmitButton("Submit"));
 form.add(flow);
 app.add(form);
 return app;
 }

 function doPost(eventInfo) {
 var app = UiApp.getActiveApplication();
 app.add(app.createLabel("Form submitted. The text box's value was '" +
   eventInfo.parameter.textBox +
   "' and the list box's value was '" +
   eventInfo.parameter.listBox + "'"));
 return app;
  }

我的问题是我想在列表框中选择多个值。然后我更改第 6 行

 flow.add(app.createListBox(true).setName("listBox").addItem("option 1").addItem("option 2"));

允许多选。但结果是只取最后一个选择的值,防止多选。显然,这是由于提交按钮。我需要保留 formPanel,因为在进一步的代码中,我想结合上传文件和 listBox 多项选择。我该如何解决?十分感谢

4

2 回答 2

1

作为对 Mogsdad 答案的补充,请注意,此错误/问题仅与 doPost 结构化处理程序有关……如果您不需要文件上传功能,则可以使用带有 callbackElement 的简单 doGet + 处理程序,在这种情况下为多选列表可用并按预期工作。

测试功能:

function doGet() {
  var app = UiApp.createApplication().setTitle('test listBox');
  var panel = app.createHorizontalPanel().setStyleAttribute('padding','40px');
  var sHdlr = app.createServerHandler('validateList').addCallbackElement(panel);
  var items = ['category 1','category 2','category 3'];
  var list1 = app.createListBox(true).setName('list1');
  for(var i =0;i<items.length;++i){list1.addItem(items[i],i)}
  panel.add(list1).add(app.createButton('validate',sHdlr));
  app.add(panel);
  return app;
}

function validateList(e){
  var app = UiApp.getActiveApplication();
  app.add(app.createLabel("Value(s) in list : "+e.parameter.list1).setStyleAttribute('margin-left','40'));
  return app;
} 

以下是问题跟踪器中描述的解决方法的工作示例。我使用文本框来显示该过程,将其设置为可见(假)或在“真实”应用程序中使用隐藏的小部件。(可在此处进行测试

function doGet() {
  var app = UiApp.createApplication().setTitle('test listBox');
  var panel = app.createHorizontalPanel().setStyleAttribute('padding','40px');
  var listHandler = app.createServerHandler('updlistVal').addCallbackElement(panel);
  var items = ['category 1','category 2','category 3'];
  var list1 = app.createListBox(true).setName('list1').addChangeHandler(listHandler);
  for(var i =0;i<items.length;++i){list1.addItem(items[i])}
  panel.add(list1).add(app.createTextBox().setText(items[0]).setId('listboxVal').setName('listboxVal').setWidth('200'));// set a default value in case the user is happy with that and doesn't touch the listBox
  var submitBtn = app.createSubmitButton('test').setStyleAttribute('margin-left','40');
  app.add(app.createFormPanel().add(panel.add(submitBtn)));
  return app;
}

function doPost(e){
  var app = UiApp.getActiveApplication();
  app.add(app.createLabel().setStyleAttribute('padding','40').setText("Submitted value(s) from list : "+e.parameter.listboxVal));
  return app;
}

function updlistVal(e){
  var app = UiApp.getActiveApplication();
  app.getElementById('listboxVal').setValue(e.parameter.list1);
  return app;
}

编辑 2: 正如在这篇文章的评论中提到的,我们必须找到一种方法来防止在隐藏/文本小部件的值更新为有效值之前完成提交。我上面使用的“默认值”是一种可能的解决方案,另一种是仅当 listValue(或其在隐藏小部件中的值)正确时才使用客户端处理程序来验证提交按钮。这是执行此操作的代码(仅复制了 doGet,所有其他功能都相同。

function doGet() {
  var app = UiApp.createApplication().setTitle('test listBox');
  var panel = app.createHorizontalPanel().setStyleAttribute('padding','40px');
  var submitBtn = app.createSubmitButton('test').setStyleAttribute('margin-left','40').setEnabled(false);
  var listHandler = app.createServerHandler('updlistVal').addCallbackElement(panel);
  var items = ['category 1','category 2','category 3'];
  var listVal = app.createTextBox().setText('not defined yet').setId('listboxVal').setName('listboxVal').setWidth('200');
  var list1 = app.createListBox(true).setName('list1').addChangeHandler(listHandler).addItem('choose one or more item(s)');
  for(var i =0;i<items.length;++i){list1.addItem(items[i])}
  var clientH = app.createClientHandler().forTargets(submitBtn).setEnabled(true).validateMatches(list1, 'category');
  list1.addClickHandler(clientH);
  panel.add(list1).add(listVal);// set a default value in case the user is happy with that and doesn't touch the listBox
  app.add(app.createFormPanel().add(panel.add(submitBtn)));
  return app;
}

使用隐藏的小部件作为验证源会导致一个小问题,因为我们需要在 listBox 上单击两次才能使其工作......如果表单上有其他问题,这将通过触发客户端处理程序与所有其他小部件来解决,所以双击将不再是必要的,但恐怕这变得有点“脱离主题”了。


编辑 3:

只是为了好玩,最后一个版本显然没有问题......

在这里测试

function doGet() {
  var app = UiApp.createApplication().setTitle('test listBox');
  var panel = app.createHorizontalPanel().setStyleAttribute('padding','40px');
  var submitBtn = app.createSubmitButton('test').setStyleAttribute('margin-left','40').setEnabled(false).setId('sbmt');
  var wait = app.createImage('https://dl.dropboxusercontent.com/u/211279/loading3T.gif').setId('wait').setVisible(false);
  var listHandler = app.createServerHandler('updlistVal').addCallbackElement(panel);
  var items = ['category 1','category 2','category 3'];
  var listVal = app.createTextBox().setText('not defined yet').setId('listboxVal').setName('listboxVal').setWidth('200');
  var list1 = app.createListBox(true).setName('list1').addChangeHandler(listHandler).addItem('choose one or more item(s)');
  for(var i =0;i<items.length;++i){list1.addItem(items[i])}
  var clientH = app.createClientHandler().forTargets(wait).setVisible(true).forTargets(submitBtn).setEnabled(false);
  list1.addChangeHandler(clientH);
  panel.add(list1).add(listVal);// set a default value in case the user is happy with that and doesn't touch the listBox
  app.add(app.createFormPanel().add(panel.add(submitBtn).add(wait)));
  return app;
}

function doPost(e){
  var app = UiApp.getActiveApplication();
  app.add(app.createLabel().setStyleAttribute('padding','40').setText("Submitted value(s) from list : "+e.parameter.listboxVal));
  return app;
}

function updlistVal(e){
  var app = UiApp.getActiveApplication();
  app.getElementById('listboxVal').setValue(e.parameter.list1);
  app.getElementById('sbmt').setEnabled(true);
  app.getElementById('wait').setVisible(false);
  return app;
}
于 2013-07-19T14:38:14.063 回答
0

这是问题跟踪器Issue 959中的一个已知错误。访问并为其加注星标以获取更新。

如果您相信支持团队添加的注释,那么它自 2011 年 12 月以来就已为人所知并“开始工作”。其他用户提供了一种解决方法,它的修改版本显示在下面。

想法是将处理函数附加到 ListBox,它将接收来自 ListBox 的所有选定项。然后,处理程序会将这些值写入表单中的隐藏元素。提交表单后,选择列表将doPost()通过隐藏元素提供给 。

  ...
  var listbox = app.createListBox(true).setName("listBox").addItem("option 1").addItem("option 2");
  flow.add(listbox);

  // Issue 959 ListBox Workaround: http://code.google.com/p/google-apps-script-issues/issues/detail?id=959
  var listboxHidden= app.createHidden("listboxHidden", "").setId("listboxHidden");
  flow.add(listboxHidden);
  var fixListBoxHandler = app.createServerHandler('fixListBoxHandler');
  fixListBoxHandler.addCallbackElement(listbox);
  listbox.addChangeHandler(fixListBoxHandler);

  ...
}

function fixListBoxHandler(e) {

  var app = UiApp.getActiveApplication();
  app.getElementById('listboxHidden').setValue(e.parameter.listbox);
  return app;

}

注意:不幸的是,这种解决方法是时间敏感的;处理程序可能需要几秒钟来更新隐藏值。如果在处理程序完成其工作之前点击提交按钮,则 post() 会在调用处理程序之前接收隐藏元素中的内容。

于 2013-07-19T13:43:16.687 回答