I recently suggested (in this post) a script that checks if the different fields of a form have an answer before allowing to submit and I did it using a client handler with validators.
Playing around with that script I noticed that in some cases the submit button is enabled even if all the validation conditions are not fulfilled. It depends on the order in which one fills the different fields.
To be clear : if you fill each field one after the other everything is fine, if for some reason you change this sequence (starting from the end or from the middle) it happens that the fileupload
validation is not taken into account and that the submit button gets enabled without a file being selected.
(Writing this I realize it is not so clear ;-) but looking at the online test will show what I mean!!)
Here is the demo code I used, if you find something wrong in it that explains this behavior I'll be glad to know.
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
}
EDIT : Here is the modified part of the code following Phil's answer. The validation works more reliably but there is still some annoying user friendliness lacks...
code removed, EDIT 2 final code, the complete 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;
}