使用客户端处理程序进行表单验证:为什么输入序列顺序改变结果?

时间:2013-03-11 22:47:04

标签: google-apps-script

我最近建议(在this post中)一个脚本,在允许提交之前检查表单的不同字段是否有答案,我使用带有验证器的客户端处理程序来完成它。

使用该脚本我注意到,在某些情况下,即使未满足所有验证条件,也会启用提交按钮。这取决于填充不同字段的顺序。

要明确:如果你一个接一个地填充每个字段,一切都很好,如果由于某种原因你改变了这个序列(从结束或从中间开始),那么fileupload验证不会发生考虑到并且提交按钮在没有选择文件的情况下启用。

(写这个我意识到它不是那么清楚;-)但是looking at the online test会表明我的意思!!)

以下是我使用的演示代码,如果您发现其中存在错误,可以解释此行为,我将很高兴知道。

var submissionSSKey = '0AnqSFd3iikE3dFZ6M1JDekJIa1I5UEZIZURGN3hhM3c';
var listitems = ['Select a value','value1','value2','value3','value4','value5','value6']
var Panelstyle = {'background':'beige','padding':'40px','borderStyle':'ridge','borderWidth':'15PX','borderColor':'#eecc99'}

function doGet() {
  var app = UiApp.createApplication().setTitle('Form test').setStyleAttribute('padding','50PX');
  var panel = app.createFormPanel().setStyleAttributes(Panelstyle).setPixelSize(400, 250);
  var title = app.createHTML('<B>Form validation test</B>').setStyleAttribute('fontSize','20px').setStyleAttribute('color','brown');
  var grid = app.createGrid(9,2).setId('grid');
  var list1 = app.createListBox().setName('list1');
   for(var i in listitems){list1.addItem(listitems[i])}    
  var list2 = app.createListBox().setName('list2');
   for(var i in listitems){list2.addItem(listitems[i])}    
  var list3 = app.createListBox().setName('list3');
   for(var i in listitems){list3.addItem(listitems[i])}    
  var Textbox1 = app.createTextBox().setWidth('150px').setName('TB1');
  var Textbox2 = app.createTextBox().setWidth('150px').setName('TB2');
  var DateB = app.createDateBox().setWidth('150px').setName('dateB');
  var upLoad = app.createFileUpload().setName('uploadedFile');
  var submitButton = app.createSubmitButton('<B>Submit</B>'); 
  var warning = app.createHTML('Please fill in all fields').setStyleAttribute('background','#FFcc99').setStyleAttribute('fontSize','20px');
  //file upload
  var cliHandler2 = app.createClientHandler()
  .validateLength(Textbox1, 1, 40).validateLength(Textbox2, 1, 40).validateNotMatches(list1,'Select a value').validateNotMatches(list2,'Select a value')
  .validateNotMatches(list3,'Select a value').validateMatches(DateB, '2','g').validateNotMatches(upLoad, 'FileUpload')
  .forTargets(submitButton).setEnabled(true)
  .forTargets(warning).setHTML('Now you can submit your form').setStyleAttribute('background','#99FF99').setStyleAttribute('fontSize','12px');

  //Grid layout of items on form
  grid.setText(0, 0, 'This is a ')
      .setWidget(0, 1, title)
      .setText(1, 0, 'List Selector 1')
      .setWidget(1, 1, list1.addClickHandler(cliHandler2))
      .setText(2, 0, 'List Selector 2')
      .setWidget(2, 1, list2.addClickHandler(cliHandler2))
      .setText(3, 0, 'List Selector 3')
      .setWidget(3, 1, list3.addClickHandler(cliHandler2))
      .setText(4, 0, 'Text Box 1')
      .setWidget(4, 1, Textbox1.addClickHandler(cliHandler2))
      .setText(5, 0, 'Text Box 2')
      .setWidget(5, 1, Textbox2.addClickHandler(cliHandler2))
      .setText(6, 0, 'Date Box')
      .setWidget(6, 1, DateB)
      .setText(7, 0, 'File Upload')
      .setWidget(7, 1, upLoad.addChangeHandler(cliHandler2))
      .setWidget(8, 0, submitButton)
      .setWidget(8, 1, warning);

  var cliHandler = app.createClientHandler().forTargets(warning).setHTML('<B>PLEASE WAIT WHILE DATA IS UPLOADING<B>').setStyleAttribute('background','yellow');
  submitButton.addClickHandler(cliHandler).setEnabled(false);  
  panel.add(grid);
  app.add(panel);
  return app;
}


function doPost(e) {
  var app = UiApp.getActiveApplication();
  var ListVal1 = e.parameter.list1;  
  var ListVal2 = e.parameter.list2;  
  var ListVal3 = e.parameter.list3;  
  var textVal1 = e.parameter.TB1;
  var textVal2 = e.parameter.TB2;
  var dateVal = e.parameter.dateB;
  var sheet = SpreadsheetApp.openById(submissionSSKey).getSheetByName('Summary');
  var lastRow = sheet.getLastRow();
  var targetRange = sheet.getRange(lastRow+1, 1, 1, 6).setValues([[ListVal1,ListVal2,ListVal3,textVal1,textVal2,dateVal]]);
  var fileBlob = e.parameter.uploadedFile;
  var doc = DocsList.createFile(fileBlob);
  app.add(app.createLabel('Thank you for submitting'));
  return app
}

编辑: 以下是Phil回答后代码的修改部分。验证工作更可靠,但仍有一些令人烦恼的用户友好性缺乏......

删除了代码,编辑2 最终代码,完整的doGet:

var submissionSSKey = '0AnqSFd3iikE3dFZ6M1JDekJIa1I5UEZIZURGN3hhM3c';
var listitems = ['Select a value','value1','value2','value3','value4','value5','value6']
var Panelstyle = {'background':'beige','padding':'40px','borderStyle':'ridge','borderWidth':'15PX','borderColor':'#eecc99'}

function doGet() {
  var app = UiApp.createApplication().setTitle('Form test').setStyleAttribute('padding','50PX');
  var panel = app.createFormPanel().setStyleAttributes(Panelstyle).setPixelSize(400, 250);
  var title = app.createHTML('<B>Form validation test</B>').setStyleAttribute('fontSize','20px').setStyleAttribute('color','brown');
  var grid = app.createGrid(10,2).setId('grid');
  var list1 = app.createListBox().setName('list1');
   for(var i in listitems){list1.addItem(listitems[i])}    
  var list2 = app.createListBox().setName('list2');
   for(var i in listitems){list2.addItem(listitems[i])}    
  var list3 = app.createListBox().setName('list3');
   for(var i in listitems){list3.addItem(listitems[i])}    
  var Textbox1 = app.createTextBox().setWidth('150px').setName('TB1');
  var Textbox2 = app.createTextBox().setWidth('150px').setName('TB2');
  var DateB = app.createDateBox().setWidth('150px').setName('dateB');
  var upLoad = app.createFileUpload().setName('uploadedFile');
  var uploadtracker = app.createTextBox().setVisible(false);
  var submitButton = app.createSubmitButton('<B>Submit</B>'); 
  var warning = app.createHTML('Please fill in all fields').setStyleAttribute('background','#FFcc99').setStyleAttribute('fontSize','20px');
  //file upload
  var cliHandler2 = app.createClientHandler()
  .validateLength(Textbox1, 1, 40).validateLength(Textbox2, 1, 40).validateNotMatches(list1,'Select a value').validateNotMatches(list2,'Select a value')
  .validateNotMatches(list3,'Select a value').validateMatches(DateB, '2','g').validateMatches(uploadtracker, 'selected')
  .forTargets(submitButton).setEnabled(true)
  .forTargets(warning).setHTML('Now you can submit your form').setStyleAttribute('background','#99FF99').setStyleAttribute('fontSize','12px');
  var cliHandler3 = app.createClientHandler().forTargets(uploadtracker).setText('selected')
  //Grid layout of items on form
  grid.setText(0, 0, 'This is a ')
      .setWidget(0, 1, title)
      .setText(1, 0, 'List Selector 1')
      .setWidget(1, 1, list1)
      .setText(2, 0, 'List Selector 2')
      .setWidget(2, 1, list2)
      .setText(3, 0, 'List Selector 3')
      .setWidget(3, 1, list3)
      .setText(4, 0, 'Text Box 1')
      .setWidget(4, 1, Textbox1)
      .setText(5, 0, 'Text Box 2')
      .setWidget(5, 1, Textbox2)
      .setText(6, 0, 'Date Box')
      .setWidget(6, 1, DateB.addValueChangeHandler(cliHandler2))
      .setText(7, 0, 'File Upload')
      .setWidget(7, 1, upLoad.addChangeHandler(cliHandler3).addChangeHandler(cliHandler2))
      .setWidget(8, 0, submitButton)
      .setWidget(8, 1, warning)
      .setWidget(9,0,uploadtracker)
      .addClickHandler(cliHandler2);

  var cliHandler = app.createClientHandler().forTargets(warning).setHTML('<B>PLEASE WAIT WHILE DATA IS UPLOADING<B>').setStyleAttribute('background','yellow');
  submitButton.addClickHandler(cliHandler).setEnabled(false);  
  panel.add(grid);
  app.add(panel);
  return app;
}

2 个答案:

答案 0 :(得分:2)

原始解决方法

&GT;这不完美

代码添加了一个隐藏的元素,用于保存FileUpload是否已更改。如果FileUpload已更改,它会将TextBox设置为SELECTED!,但用户可以轻松 FileUpload更改回没有选择文件,并且无法清除这个TextBox准确无误。

这是基于我们对FileUpload的一些了解。

  1. 当用户加载UiApp时,FileUpload最初未选择文件
  2. 当在FileUpload上触发更改事件时,所选文件已更改
  3. 基于这两件事情,当第一次调用 change 时,我们知道有一个文件被选中。

    &GT;变更摘要

    创建隐藏元素

    var hidden = app.createTextBox().setStyleAttribute("display","none").setValue("");
    

    删除.validateNotMatches(upLoad, 'FileUpload')并将其替换为

    .validateLength(hidden,1,100)
    

    创建一个新的ClientHandler

    var cliHandler3 = app.createClientHandler().forTargets(hidden).setText("SELECTED!");
    

    .addChangeHandler(cliHandler3)插入旧行。

    upLoad.addChangeHandler(cliHandler3).addChangeHandler(cliHandler2)
    

    panel.add(grid)替换为(必须将“隐藏”添加到FormPanel才能使其工作)

    var vert = app.createVerticalPanel().add(hidden).add(grid);
    panel.add(vert);
    

答案 1 :(得分:1)

无法查看添加评论的位置,但我想问一下.addClickHandler(clihandler2);到网格。这是通过在

的末尾添加它来实现的
grid.setText(0, 0, 'This is a ')  [rest of the code (.setText .setWidget etc) ].addClickHandler(cliHandler2);

另外,你能让我知道上传器跟踪器在小部件位置9,0 ??我没有看到它注明原始代码发布,但是在修改后的代码段中看到grid.set(text&amp; widgets)中注明的upload和uploadtracker。