Validación de formularios mediante el controlador de clientes: ¿por qué el orden de la secuencia de entrada cambia el resultado?

Recientemente sugerí (enesta publicación) un script que verifica si los diferentes campos de un formulario tienen una respuesta antes de permitir el envío y lo hice utilizando un controlador de cliente con validadores.

Al jugar con ese script, noté que en algunos casos el botón de envío está habilitado incluso si no se cumplen todas las condiciones de validación. Depende del orden en que se rellenen los diferentes campos.

Para ser claros: si rellena cada campo uno tras otro, todo está bien, si por alguna razón cambia esta secuencia (comenzando desde el final o desde la mitad), sucede quefileupload la validación no se tiene en cuenta y el botón de envío se habilita sin que se seleccione un archivo.

(Escribiendo esto, me doy cuenta de que no es tan claro ;-) peromirando la prueba en línea mostrará lo que quiero decir !!

Aquí está el código de demostración que utilicé, si encuentra algún error en él que explique este comportamiento, estaré encantado de saberlo.

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
}

EDITAR: Aquí está la parte modificada del código que sigue a la respuesta de Phil. La validación funciona de manera más confiable, pero todavía hay algunas molestias para el usuario molestas ...

código eliminado,Editar 2 código final, el doGet completo:

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

Respuestas a la pregunta(2)

Su respuesta a la pregunta